embody.util
Utility functions for embody: flattening, unflattening, and cycle detection.
This module provides helper functions for working with nested data structures, including path-based operations and cycle detection for safe traversal.
- exception embody.util.CycleError[source]
Raised when a circular reference is detected in a data structure.
- exception embody.util.PathNotFoundError[source]
Raised when a path doesn’t exist in a data structure.
- embody.util.count_template_markers(obj: Any, syntax: str = 'dollar_brace') int[source]
Count the number of template markers in a nested structure.
- Parameters:
obj – Object to count markers in
syntax – Template syntax to look for
- Returns:
Number of template markers found
Examples
>>> count_template_markers({'a': '${x}', 'b': '${y}'}) 2 >>> count_template_markers(['${a}', 'literal', '${b} and ${c}']) 3
- embody.util.detect_cycle(obj: Any, visited: Set[int] = None, path: List[str] = None) None[source]
Detect cycles in a nested data structure.
- Parameters:
obj – The object to check for cycles
visited – Set of object IDs already visited
path – Current path in the structure (for error reporting)
- Raises:
CycleError – If a cycle is detected
Examples
>>> d = {'a': 1, 'b': [2, 3]} >>> detect_cycle(d) # No cycle, returns None
>>> circular = {'a': 1} >>> circular['self'] = circular >>> try: ... detect_cycle(circular) ... except CycleError as e: ... print("Cycle detected") Cycle detected
- embody.util.flatten_dict(nested_dict: Dict[str, Any], separator: str = '.', parent_key: str = '') Dict[str, Any][source]
Flatten a nested dictionary into a single-level dictionary with path keys.
- Parameters:
nested_dict – Nested dictionary to flatten
separator – String to use for separating path components
parent_key – Key of the parent (used in recursion)
- Returns:
Flattened dictionary with path keys
Examples
>>> d = {'a': {'b': {'c': 1}}, 'd': 2} >>> flatten_dict(d) {'a.b.c': 1, 'd': 2}
>>> d = {'user': {'name': 'Alice', 'age': 30}} >>> flatten_dict(d) {'user.name': 'Alice', 'user.age': 30}
>>> d = {'items': [1, 2, 3]} >>> flatten_dict(d) {'items.0': 1, 'items.1': 2, 'items.2': 3}
- embody.util.flatten_to_tuples(obj: Any, parent_path: Tuple = ()) Dict[Tuple, Any][source]
Flatten a nested structure using tuple paths (unambiguous).
This avoids the ambiguity of string separators. A tuple path like (‘a’, ‘b’, 0) is unambiguous, while ‘a.b.0’ could mean multiple things if keys contain dots.
- Parameters:
obj – Object to flatten
parent_path – Current path as tuple
- Returns:
Dictionary mapping tuple paths to values
Examples
>>> d = {'a': {'b': [1, 2]}} >>> flatten_to_tuples(d) {('a', 'b', 0): 1, ('a', 'b', 1): 2}
- embody.util.get_by_path(obj: Any, path: str | Tuple, separator: str = '.', default: Any = None) Any[source]
Get a value from a nested structure by path.
- Parameters:
obj – Nested structure
path – Path as string or tuple
separator – Separator for string paths
default – Default value if path not found
- Returns:
Value at the path, or default if not found
Examples
>>> d = {'a': {'b': {'c': 42}}} >>> get_by_path(d, 'a.b.c') 42 >>> get_by_path(d, ('a', 'b', 'c')) 42 >>> get_by_path(d, 'a.b.x', default='not found') 'not found'
- embody.util.max_depth(obj: Any, current_depth: int = 0) int[source]
Calculate the maximum depth of a nested structure.
- Parameters:
obj – Object to measure
current_depth – Current depth (used in recursion)
- Returns:
Maximum depth
Examples
>>> max_depth({'a': 1}) 1 >>> max_depth({'a': {'b': {'c': 1}}}) 3 >>> max_depth([1, [2, [3, 4]]]) 3
- embody.util.set_by_path(obj: Dict, path: str | Tuple, value: Any, separator: str = '.', create_intermediate: bool = True) None[source]
Set a value in a nested structure by path (modifies in place).
- Parameters:
obj – Nested structure to modify
path – Path as string or tuple
value – Value to set
separator – Separator for string paths
create_intermediate – If True, create intermediate dicts/lists as needed
Examples
>>> d = {} >>> set_by_path(d, 'a.b.c', 42) >>> d {'a': {'b': {'c': 42}}}
- embody.util.unflatten_dict(flat_dict: Dict[str, Any], separator: str = '.') Dict[str, Any][source]
Unflatten a dictionary with path keys into a nested structure.
- Parameters:
flat_dict – Flattened dictionary with path keys
separator – String used for separating path components
- Returns:
Nested dictionary structure
Examples
>>> flat = {'a.b.c': 1, 'd': 2} >>> unflatten_dict(flat) {'a': {'b': {'c': 1}}, 'd': 2}
>>> flat = {'items.0': 'a', 'items.1': 'b'} >>> unflatten_dict(flat) {'items': ['a', 'b']}
- embody.util.unflatten_from_tuples(flat_dict: Dict[Tuple, Any]) Any[source]
Unflatten a dictionary with tuple paths into a nested structure.
- Parameters:
flat_dict – Dictionary with tuple paths as keys
- Returns:
Nested structure (dict or list)
Examples
>>> flat = {('a', 'b', 0): 1, ('a', 'b', 1): 2} >>> unflatten_from_tuples(flat) {'a': {'b': [1, 2]}}