API Reference
nestedutils.access ¶
get_at ¶
get_at(data: Any, path: Union[str, List[Any]], default: Any = None) -> Any
Retrieve a value from a nested data structure.
Navigates through nested dictionaries, lists, and tuples using a path specified as either
a dot-notation string or a list of keys/indices. Returns default if the path does not
exist or an index is out of bounds (positive or negative). Supports negative indexing for
lists and tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data |
Any
|
The data structure to navigate (dict, list, tuple, or nested combinations). |
required |
path |
Union[str, List[Any]]
|
Path to the value. Accepts either a dot-separated string (e.g., "a.b.0.name") or a list of keys/indices (e.g., ["a", "b", 0, "name"]). Indices may be integers or strings representing integers (including negative indices). |
required |
default |
Any
|
Value to return if the path does not exist (default: None). |
None
|
Returns:
| Type | Description |
|---|---|
Any
|
The value at the specified path, or |
Raises:
| Type | Description |
|---|---|
PathError
|
If the path is malformed, empty, or contains empty keys. |
Examples:
data = {"a": {"b": {"c": 5}}}
get_at(data, "a.b.c") # Returns: 5
get_at(data, "a.b.d", default=99) # Returns: 99
data = {"items": [{"name": "apple"}, {"name": "banana"}]}
get_at(data, "items.1.name") # Returns: 'banana'
get_at(data, "items.-1.name") # Returns: 'banana'
get_at(data, "items.-5.name", default="not found") # Returns: 'not found'
data = (10, 20, 30)
get_at(data, "-1") # Returns: 30
set_at ¶
set_at(data: Any, path: Union[str, List[Any]], value: Any, fill_strategy: Literal['auto', 'none', 'dict', 'list'] = 'auto') -> None
Set a value in a nested data structure, creating intermediate containers as needed.
Navigates to the specified path and sets the value, automatically creating missing
intermediate dictionaries or lists according to fill_strategy.
List indexing rules
- Non-negative indices can extend the list, filling gaps as needed.
- Negative indices can only modify existing elements (no extension allowed).
- Out-of-bounds negative indices raise PathError.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data |
Any
|
The mutable data structure to modify (dict or list). Intermediate containers are created automatically, but the root must be mutable. |
required |
path |
Union[str, List[Any]]
|
Path where to set the value. Accepts either a dot-separated string (e.g., "a.b.0.name") or a list of keys/indices (e.g., ["a", "b", 0, "name"]). |
required |
value |
Any
|
The value to set at the specified path. |
required |
fill_strategy |
Literal['auto', 'none', 'dict', 'list']
|
Controls how missing intermediate containers are created. Must be one of: - 'auto' (default): creates {} for dict keys, [] for list indices, and None for sparse list gaps. - 'none': fills sparse list gaps with None. - 'dict': always creates dictionaries {} for missing containers. - 'list': always creates lists [] for missing containers. |
'auto'
|
Returns:
| Type | Description |
|---|---|
None
|
None. The function modifies |
Raises:
| Type | Description |
|---|---|
PathError
|
If the path is malformed, empty, attempts to modify a tuple, uses an invalid fill_strategy, or uses an out-of-bounds negative index. |
Note
When extending lists with gaps (e.g., setting index 5 on a list of length 2),
intermediate positions are filled based on fill_strategy ('auto' and 'none' use None;
'dict' uses {}; 'list' uses []).
Examples:
data = {}
set_at(data, "user.profile.name", "Alice")
# data is now: {'user': {'profile': {'name': 'Alice'}}}
data = {}
set_at(data, "items.0.name", "Item 1")
# data is now: {'items': [{'name': 'Item 1'}]}
data = {}
set_at(data, "items.5", "last", fill_strategy="none")
# data is now: {'items': [None, None, None, None, None, 'last']}
data = {}
set_at(data, "items.2.sub.value", 42) # 'auto' creates dict at target index, None for gaps
# data is now: {'items': [None, None, {'sub': {'value': 42}}]}
data = [1, 2, 3]
set_at(data, "5", 99) # extends with None gaps
# data is now: [1, 2, 3, None, None, 99]
set_at(data, "-1", 100) # modifies existing last element
# data is now: [1, 2, 3, None, None, 100]
delete_at ¶
delete_at(data: Any, path: Union[str, List[Any]], *, allow_list_mutation: bool = False) -> Any
Delete a value from a nested data structure and return it.
Removes the item at the specified path. For dictionaries, the key-value pair is removed. For lists, deletion is disabled by default to prevent accidental index shifting that could break subsequent code.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data |
Any
|
The mutable data structure to modify (dict or list). |
required |
path |
Union[str, List[Any]]
|
Path to the value to delete. Accepts either a dot-separated string (e.g., "a.b.0") or a list of keys/indices (e.g., ["a", "b", 0]). |
required |
allow_list_mutation |
bool
|
If True, allows deletion from lists using |
False
|
Returns:
| Type | Description |
|---|---|
Any
|
The deleted value. |
Raises:
| Type | Description |
|---|---|
PathError
|
If the path does not exist, is malformed, attempts deletion from a tuple,
attempts list deletion without |
Examples:
data = {"a": {"b": 1, "c": 2}}
delete_at(data, "a.b") # Returns: 1
# data is now: {'a': {'c': 2}}
data = {"items": [1, 2, 3]}
delete_at(data, "items.1", allow_list_mutation=True) # Returns: 2
# data is now: {'items': [1, 3]}
delete_at(data, "items.-1", allow_list_mutation=True) # Returns: 3
# data is now: {'items': [1]}
# Without allow_list_mutation=True, list deletion raises PathError
delete_at(data, "items.0") # Raises: PathError: List deletion disabled...
exists_at ¶
exists_at(data: Any, path: Union[str, List[Any]]) -> bool
Check if a path exists in a nested data structure.
Navigates through nested dictionaries, lists, and tuples. Returns True if the full path exists, False otherwise (including for any out-of-bounds index, positive or negative). Supports negative indexing for lists and tuples.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data |
Any
|
The data structure to navigate (dict, list, tuple, or nested combinations). |
required |
path |
Union[str, List[Any]]
|
Path to check. Accepts either a dot-separated string (e.g., "a.b.0.name") or a list of keys/indices (e.g., ["a", "b", 0, "name"]). |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the path exists, False otherwise. |
Raises:
| Type | Description |
|---|---|
PathError
|
If the path is malformed, empty, or contains empty keys. |
Examples:
data = {"a": {"b": {"c": 5}}}
exists_at(data, "a.b.c") # Returns: True
exists_at(data, "a.b.d") # Returns: False
data = {"items": [{"name": "apple"}, {"name": "banana"}]}
exists_at(data, "items.1.name") # Returns: True
exists_at(data, "items.-1.name") # Returns: True
exists_at(data, "items.-5.name") # Returns: False
exists_at(data, "items.10.name") # Returns: False
data = (10, 20, 30)
exists_at(data, "2") # Returns: True
exists_at(data, "5") # Returns: False
nestedutils.constants ¶
Constants for nestedutils library.
nestedutils.enums ¶
Enumerations for nestedutils library.
This module defines error codes and configuration enums used throughout the nestedutils library for consistent error handling and behavior control.
PathErrorCode ¶
Bases: Enum
Error codes for path-related exceptions.
Example
from nestedutils import get_at, PathError, PathErrorCode
data = {"a": {"b": 1}}
try:
get_at(data, "a.c.d")
except PathError as e:
if e.code == PathErrorCode.MISSING_KEY:
print("Key not found")
FillStrategy ¶
Bases: Enum
Strategy for filling missing containers when setting nested paths.
Example
from nestedutils import set_at, FillStrategy
data = {}
set_at(data, "items.0.name", "apple", fill_strategy=FillStrategy.AUTO)
nestedutils.exceptions ¶
Custom exceptions for the nestedutils library.
This module defines all custom exceptions used throughout the nestedutils library. The main exception class is PathError, which includes error codes for detailed error handling.
PathError ¶
PathError(message: str, code: Optional[PathErrorCode] = None)
Bases: Exception
Raised when a nested path cannot be navigated or modified.
Attributes:
| Name | Type | Description |
|---|---|---|
message |
Human-readable error message. |
|
code |
Optional PathErrorCode for programmatic error handling. |
Example
from nestedutils import get_at, PathError, PathErrorCode
data = {"a": {"b": 1}}
try:
get_at(data, "a.c.d")
except PathError as e:
if e.code == PathErrorCode.MISSING_KEY:
print("Key not found")