Skip to content

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 default if the path does not exist.

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 data in place.

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 list.pop(). Defaults to False to prevent unintended side effects.

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 allow_list_mutation=True, or uses an out-of-bounds index.

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.

MAX_DEPTH module-attribute

MAX_DEPTH = 100

Maximum allowed depth for nested paths. Paths exceeding this depth will raise a PathError.

MAX_LIST_SIZE module-attribute

MAX_LIST_SIZE = 10000

Maximum allowed list index. List indices exceeding this value will raise a PathError.

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")
INVALID_INDEX class-attribute instance-attribute
INVALID_INDEX = 'INVALID_INDEX'
MISSING_KEY class-attribute instance-attribute
MISSING_KEY = 'MISSING_KEY'
EMPTY_PATH class-attribute instance-attribute
EMPTY_PATH = 'EMPTY_PATH'
IMMUTABLE_CONTAINER class-attribute instance-attribute
IMMUTABLE_CONTAINER = 'IMMUTABLE_CONTAINER'
INVALID_PATH class-attribute instance-attribute
INVALID_PATH = 'INVALID_PATH'
INVALID_FILL_STRATEGY class-attribute instance-attribute
INVALID_FILL_STRATEGY = 'INVALID_FILL_STRATEGY'

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)
AUTO class-attribute instance-attribute
AUTO = 'auto'
NONE class-attribute instance-attribute
NONE = 'none'
DICT class-attribute instance-attribute
DICT = 'dict'
LIST class-attribute instance-attribute
LIST = 'list'

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")