DeepDict#

class sigmaepsilon.deepdict.deepdict.DeepDict(*args, parent: T | None = None, root: T | None = None, locked: bool | None = None, **kwargs)#

An nested dictionary class with a self-replicating default factory. It can be a drop-in replacement for the bulit-in dictionary type, but it’s more capable as it handles nested layouts.

Examples

Basic usage:

>>> from sigmaepsilon.deepdict import DeepDict
>>> d = {'a' : {'aa' : {'aaa' : 0}}, 'b' : 1, 'c' : {'cc' : 2}}
>>> dd = DeepDict(d)
>>> list(dd.values(deep=True))
[0, 1, 2]
property address: Tuple | None#

Returns the address of an item or None it has no parent.

containers(*, inclusive: bool | None = False, deep: bool | None = True, dtype: Any | None = None) Iterable[T]#

Returns all the containers in a nested layout. A dictionary in a nested layout is called a container, only if it contains other containers (it is a parent).

Parameters:
  • inclusive (bool, Optional) – If True, the object the call is made upon also gets returned. This can be important if you make the call on the root object, which most of the time does not hold onto relevant data directly. Default is False.

  • deep (bool, Optional) – If True the parser goes into nested dictionaries. Default is True

  • dtype (Any, Optional) – Constrains the type of the returned objects. Default is None, which means no restriction.

Returns:

Returns a generator object.

Return type:

generator

Examples

A simple example:

>>> from sigmaepsilon.deepdict import DeepDict
>>> data = DeepDict()
>>> data['a', 'b', 'c'] = 1
>>> [c.key for c in data.containers()]
['a', 'b']

We can see, that dictionaries ‘a’ and ‘b’ are returned as containers, but ‘c’ isn’t, because it is not a parent, there are no deeper levels.

>>> [c.key for c in data.containers(inclusive=True, deep=True)]
[None, 'a', 'b']
>>> [c.key for c in data.containers(inclusive=True, deep=False)]
[None, 'a']
>>> [c.key for c in data.containers(inclusive=False, deep=True)]
['a', 'b']
>>> [c.key for c in data.containers(inclusive=False, deep=False)]
['a']
property depth: int#

Retuns the depth of the actual instance in a layout, starting from 0..

is_leaf(dtype: Any | None = None) bool#

Returns True, if the instance has no children.

Parameters:

dtype (Any, Optional) – It can be a type that controls what is considered as a children. It is None by default, which means that only instances of the same class are considered children. In this case, a simple dict wouldn’t make it.

Example

>>> from sigmaepsilon.deepdict import DeepDict
>>> d = {
...     "a" : {"aa" : 1},
...     "b" : 2,
...     "c" : {"cc" : {"ccc" : 3}},
... }
>>> dd = DeepDict.wrap(d)
>>> dd.is_leaf(), dd["a"].is_leaf()
(False, True)
is_root() bool#

Returns True, if the instance is the root.

items(*, deep: bool | None = False, return_address: bool | None = False) Iterable[Tuple]#

Returns the items. When called without arguments, it works the same as for standard dictionaries.

Parameters:
  • deep (bool, Optional) – If True the parser goes into nested dictionaries. Default is True.

  • return_address (bool, Optional) – If True, addresses are returned instead of keys. The difference is similar than that of absolute and repative paths. In this respect, keys are the relative paths (relative to the parent), and addresses are absolute paths (relative to the root). Default is False.

property key: Hashable | None#

Returns the key of the instance, or None if it has no parent.

keys(*, deep: bool | None = False, return_address: bool | None = False) Iterable[Hashable]#

Returns the keys. When called without arguments, it works the same as for standard dictionaries.

Parameters:
  • deep (bool, Optional) – If True the parser goes into nested dictionaries. Default is True.

  • return_address (bool, Optional) – If True, addresses are returned instead of keys. The difference is similar than that of absolute and repative paths. In this respect, keys are the relative paths (relative to the parent), and addresses are absolute paths (relative to the root). Default is False.

lock() None#

Locks the layout of the dictionary. If a DeepDict is locked, missing keys are handled the same way as they would’ve been handled if it was a ´dict´. Also, setting or deleting items in a locked dictionary and not possible and you will experience an error upon trying.

property locked: bool#

Returns True if the object is locked. The property is equpped with a setter.

property parent: T | None | DeepDict#

Returns the parent of the instance, or None if it has no parent.

root() T#

Returns the top-level object in a nested layout.

unlock() None#

Releases the layout of the dictionary. If a DeepDict is not locked, a missing key creates a new level in the layout, also setting and deleting items becomes an option.

values(*, deep: bool | None = False, return_address: bool | None = False) Iterable[Any | T]#

Returns the values. When called without arguments, it works the same as for standard dictionaries.

Parameters:
  • deep (bool, Optional) – If True the parser goes into nested dictionaries. Default is True.

  • return_address (bool, Optional) – If True, addresses are returned as well. Default is False.

classmethod wrap(d: dict) T | DeepDict#

Wraps a dictionary with all nested dictionaries and content.

Example

>>> from sigmaepsilon.deepdict import DeepDict
>>> d = {
...     "a" : {"aa" : 1},
...     "b" : 2,
...     "c" : {"cc" : {"ccc" : 3}},
... }
>>> DeepDict.wrap(d)["c", "cc", "ccc"]
3
>>> list(DeepDict.wrap(d).items(deep=True))
[('aa', 1), ('b', 2), ('ccc', 3)]
class sigmaepsilon.deepdict.deepdict.Key(arg: Any)#

Helper class for keys.

class sigmaepsilon.deepdict.deepdict.Value(arg: Any)#

Helper class for values.