dantro.base module

This module implements the base classes of dantro, based on the abstract classes.

The base classes are classes that combine features of the abstract classes. For example, the data group gains attribute functionality by being a combination of the AbstractDataGroup and the BaseDataContainer. In turn, the BaseDataContainer uses the BaseDataAttrs class as an attribute and thereby extends the AbstractDataContainer class.

NOTE: These classes are not meant to be instantiated but used as a basis to implement more specialized BaseDataGroup- or BaseDataContainer-derived classes.

class dantro.base.BaseDataProxy(obj: Any = None)[source]

Bases: dantro.abc.AbstractDataProxy

The base class for data proxies.

NOTE: This is still an abstract class and needs to be subclassed.

_tags = ()
abstract __init__(obj: Any = None)[source]

Initialize a proxy object for the given object.

property tags

The tags describing this proxy object

_abc_impl = <_abc_data object>
property classname

Returns this proxy’s class name

abstract resolve(*, astype: type = None)

Get the data that this proxy is a placeholder for and return it.

Note that this method does not place the resolved data in the container of which this proxy object is a placeholder for! This only returns the data.

class dantro.base.BaseDataAttrs(attrs: dict = None, **dc_kwargs)[source]

Bases: dantro.mixins.base.MappingAccessMixin, dantro.abc.AbstractDataAttrs

A class to store attributes that belong to a data container.

This implements a dict-like interface and serves as default attribute class.

NOTE: Unlike the other base classes, this can already be instantiated. That is required as it is needed in BaseDataContainer where no previous subclassing or mixin is reasonable.

__init__(attrs: dict = None, **dc_kwargs)[source]

Initialize a DataAttributes object.

Parameters
  • attrs (dict, optional) – The attributes to store

  • **dc_kwargs – Further kwargs to the parent DataContainer

as_dict() → dict[source]

Returns a shallow copy of the attributes as a dict

_format_info() → str[source]

A __format__ helper function: returns info about these attributes

__contains__(key) → bool

Whether the given key is contained in the items.

__delitem__(key)

Deletes an item

__format__(spec_str: str) → str

Creates a formatted string from the given specification.

Invokes further methods which are prefixed by _format_.

__getitem__(key)

Returns an item.

__iter__()

Iterates over the items.

__len__() → int

The number of items.

__repr__() → str

Same as __str__

__setitem__(key, val)

Sets an item.

__str__() → str

An info string, that describes the object. This invokes the formatting helpers to show the log string (type and name) as well as the info string of this object.

_abc_impl = <_abc_data object>
_check_data(data: Any) → None

This method can be used to check the data provided to this container

It is called before the data is stored in the __init__ method and should raise an exception or create a warning if the data is not as desired.

This method can be subclassed to implement more specific behaviour. To propagate the parent classes’ behaviour the subclassed method should always call its parent method using super().

Note

The CheckDataMixin provides a generalised implementation of this method to perform some type checks and react to unexpected types.

Parameters

data (Any) – The data to check

_check_name(new_name: str) → None

Called from name.setter and can be used to check the name that the container is supposed to have. On invalid name, this should raise.

This method can be subclassed to implement more specific behaviour. To propagate the parent classes’ behaviour the subclassed method should always call its parent method using super().

Parameters

new_name (str) – The new name, which is to be checked.

_format_cls_name() → str

A __format__ helper function: returns the class name

_format_logstr() → str

A __format__ helper function: returns the log string, a combination of class name and name

_format_name() → str

A __format__ helper function: returns the name

_format_path() → str

A __format__ helper function: returns the path to this container

_item_access_convert_list_key(key)

If given something that is not a list, just return that key

property classname

Returns the name of this DataContainer-derived class

property data

The stored data.

get(key, default=None)

Return the value at key, or default if key is not available.

items()

Returns an iterator over data’s (key, value) tuples

keys()

Returns an iterator over the data’s keys.

property logstr

Returns the classname and name of this object

property name

The name of this DataContainer-derived object.

property parent

The associated parent of this container or group

property path

The path to get to this container or group from some root path

values()

Returns an iterator over the data’s values.

class dantro.base.BaseDataContainer(*, name: str, data, attrs=None)[source]

Bases: dantro.mixins.base.AttrsMixin, dantro.mixins.base.SizeOfMixin, dantro.mixins.base.BasicComparisonMixin, dantro.abc.AbstractDataContainer

The BaseDataContainer extends the abstract base class by the ability to hold attributes and be path-aware.

_ATTRS_CLS

alias of BaseDataAttrs

__init__(*, name: str, data, attrs=None)[source]

Initialize a BaseDataContainer, which can store data and attributes.

Parameters
  • name (str) – The name of this data container

  • data – The data to store in this container

  • attrs (None, optional) – A mapping that is stored as attributes

property attrs

The container attributes.

_format_info() → str[source]

A __format__ helper function: returns info about the content of this data container.

abstract __delitem__(key) → None

Deletes an item from the container.

__eq__(other) → bool

Evaluates equality by making the following comparisons: identity, strict type equality, and finally: equality of the _data and _attrs attributes, i.e. the private attribute. This ensures that comparison does not trigger any downstream effects like resolution of proxies.

If types do not match exactly, NotImplemented is returned, thus referring the comparison to the other side of the ==.

__format__(spec_str: str) → str

Creates a formatted string from the given specification.

Invokes further methods which are prefixed by _format_.

abstract __getitem__(key)

Gets an item from the container.

__repr__() → str

Same as __str__

abstract __setitem__(key, val) → None

Sets an item in the container.

__sizeof__() → int

Returns the size of the data (in bytes) stored in this container’s data and its attributes.

Note that this value is approximate. It is computed by calling the sys.getsizeof function on the data, the attributes, the name and some caching attributes that each dantro data tree class contains. Importantly, this is not a recursive algorithm.

Also, derived classes might implement further attributes that are not taken into account either. To be more precise in a subclass, create a specific __sizeof__ method and invoke this parent method additionally.

For more information, see the documentation of sys.getsizeof:

__str__() → str

An info string, that describes the object. This invokes the formatting helpers to show the log string (type and name) as well as the info string of this object.

_abc_impl = <_abc_data object>
_attrs = None
_check_data(data: Any) → None

This method can be used to check the data provided to this container

It is called before the data is stored in the __init__ method and should raise an exception or create a warning if the data is not as desired.

This method can be subclassed to implement more specific behaviour. To propagate the parent classes’ behaviour the subclassed method should always call its parent method using super().

Note

The CheckDataMixin provides a generalised implementation of this method to perform some type checks and react to unexpected types.

Parameters

data (Any) – The data to check

_check_name(new_name: str) → None

Called from name.setter and can be used to check the name that the container is supposed to have. On invalid name, this should raise.

This method can be subclassed to implement more specific behaviour. To propagate the parent classes’ behaviour the subclassed method should always call its parent method using super().

Parameters

new_name (str) – The new name, which is to be checked.

_format_cls_name() → str

A __format__ helper function: returns the class name

_format_logstr() → str

A __format__ helper function: returns the log string, a combination of class name and name

_format_name() → str

A __format__ helper function: returns the name

_format_path() → str

A __format__ helper function: returns the path to this container

property classname

Returns the name of this DataContainer-derived class

property data

The stored data.

property logstr

Returns the classname and name of this object

property name

The name of this DataContainer-derived object.

property parent

The associated parent of this container or group

property path

The path to get to this container or group from some root path

class dantro.base.BaseDataGroup(*, name: str, containers: list = None, attrs=None)[source]

Bases: dantro.mixins.base.LockDataMixin, dantro.mixins.base.AttrsMixin, dantro.mixins.base.SizeOfMixin, dantro.mixins.base.BasicComparisonMixin, dantro.mixins.base.DirectInsertionModeMixin, dantro.abc.AbstractDataGroup

The BaseDataGroup serves as base group for all data groups.

It implements all functionality expected of a group, which is much more than what is expected of a general container.

_ATTRS_CLS

alias of BaseDataAttrs

_STORAGE_CLS

alias of builtins.dict

_NEW_GROUP_CLS = None
_NEW_CONTAINER_CLS = None
_ALLOWED_CONT_TYPES = None
_COND_TREE_MAX_LEVEL = 10
_COND_TREE_CONDENSE_THRESH = 10
__init__(*, name: str, containers: list = None, attrs=None)[source]

Initialize a BaseDataGroup, which can store other containers and attributes.

Parameters
  • name (str) – The name of this data container

  • containers (list, optional) – The containers that are to be stored as members of this group. If given, these are added one by one using the .add method.

  • attrs (None, optional) – A mapping that is stored as attributes

property attrs

The container attributes.

__getitem__(key: Union[str, List[str]]) → dantro.abc.AbstractDataContainer[source]

Looks up the given key and returns the corresponding item.

This supports recursive relative lookups in two ways:

  • By supplying a path as a string that includes the path separator. For example, foo/bar/spam walks down the tree along the given path segments.

  • By directly supplying a key sequence, i.e. a list or tuple of key strings.

With the last path segment, it is possible to access an element that is no longer part of the data tree; successive lookups thus need to use the interface of the corresponding leaf object of the data tree.

Absolute lookups, i.e. from path /foo/bar, are not possible!

Lookup complexity is that of the underlying data structure: for groups based on dict-like storage containers, lookups happen in constant time.

Note

This method aims to replicate the behavior of POSIX paths.

Thus, it can also be used to access the element itself or the parent element: Use . to refer to this object and .. to access this object’s parent.

Parameters

key (Union[str, List[str]]) – The name of the object to retrieve or a path via which it can be found in the data tree.

Returns

The object at key, which concurs to the

dantro tree interface.

Return type

AbstractDataContainer

Raises

ItemAccessError – If no object could be found at the given key or if an absolute lookup, starting with /, was attempted.

__setitem__(key: Union[str, List[str]], val: dantro.base.BaseDataContainer) → None[source]

This method is used to allow access to the content of containers of this group. For adding an element to this group, use the add method!

Parameters
  • key (Union[str, List[str]]) – The key to which to set the value. If this is a path, will recurse down to the lowest level. Note that all intermediate keys need to be present.

  • val (BaseDataContainer) – The value to set

Returns

None

Raises

ValueError – If trying to add an element to this group, which should be done via the add method.

__delitem__(key: str) → None[source]

Deletes an item from the group

add(*conts, overwrite: bool = False)[source]

Add the given containers to this group.

_add_container(cont, *, overwrite: bool)[source]

Private helper method to add a container to this group.

_check_cont(cont) → None[source]

Can be used by a subclass to check a container before adding it to this group. Is called by _add_container before checking whether the object exists or not.

This is not expected to return, but can raise errors, if something did not work out as expected.

Parameters

cont – The container to check

_add_container_to_data(cont: dantro.abc.AbstractDataContainer) → None[source]

Performs the operation of adding the container to the _data. This can be used by subclasses to make more elaborate things while adding data, e.g. specify ordering …

NOTE This method should NEVER be called on its own, but only via the

_add_container method, which takes care of properly linking the container that is to be added.

NOTE After adding, the container need be reachable under its .name!

Parameters

cont – The container to add

_add_container_callback(cont) → None[source]

Called after a container was added.

new_container(path: Union[str, List[str]], *, Cls: type = None, **kwargs)[source]

Creates a new container of class Cls and adds it at the given path relative to this group.

If needed, intermediate groups are automatically created.

Parameters
  • path (Union[str, List[str]]) – Where to add the container.

  • Cls (type, optional) – The class of the container to add. If None, the _NEW_CONTAINER_CLS class variable’s value is used.

  • **kwargs – passed on to Cls.__init__

Returns

the created container

Return type

Cls

Raises
  • ValueError – If neither the Cls argument nor the class variable _NEW_CONTAINER_CLS were set or if path was empty.

  • TypeError – When Cls is not compatible to the data tree

new_group(path: Union[str, list], *, Cls: type = None, **kwargs)[source]

Creates a new group at the given path.

Parameters
  • path (Union[str, list]) – The path to create the group at. Note that the whole intermediate path needs to already exist.

  • Cls (type, optional) – If given, use this type to create the group. If not given, uses the class specified in the _NEW_GROUP_CLS class variable or, as last resort, the type of this instance.

  • **kwargs – Passed on to Cls.__init__

Returns

the created group

Return type

Cls

Raises

TypeError – For the given class not being derived from BaseDataGroup

recursive_update(other, *, overwrite: bool = True)[source]

Recursively updates the contents of this data group with the entries of the given data group

Note

This will create shallow copies of those elements in other that are added to this object.

Parameters
  • other (BaseDataGroup) – The group to update with

  • overwrite (bool, optional) – Whether to overwrite already existing object. If False, a conflict will lead to an error being raised and the update being stopped.

Raises

TypeError – If other was of invalid type

clear()[source]

Clears all containers from this group.

This is done by unlinking all children and then overwriting _data with an empty _STORAGE_CLS object.

Links the new_child to this class, unlinking the old one.

This method should be called from any method that changes which items are associated with this group.

Unlink a child from this class.

This method should be called from any method that removes an item from this group, be it through deletion or through

__len__() → int[source]

The number of members in this group.

__contains__(cont: Union[str, dantro.abc.AbstractDataContainer]) → bool[source]

Whether the given container is in this group or not.

If this is a data tree object, it will be checked whether this specific instance is part of the group, using is-comparison.

Otherwise, assumes that cont is a valid argument to the __getitem__() method (a key or key sequence) and tries to access the item at that path, returning True if this succeeds and False if not.

Lookup complexity is that of item lookup (scalar) for both name and object lookup.

Parameters

cont (Union[str, AbstractDataContainer]) – The name of the container, a path, or an object to check via identity comparison.

Returns

Whether the given container object is part of this group or

whether the given path is accessible from this group.

Return type

bool

_ipython_key_completions_() → List[str][source]

For ipython integration, return a list of available keys

__iter__()[source]

Returns an iterator over the OrderedDict

keys()[source]

Returns an iterator over the container names in this group.

values()[source]

Returns an iterator over the containers in this group.

items()[source]

Returns an iterator over the (name, data container) tuple of this group.

get(key, default=None)[source]

Return the container at key, or default if container with name key is not available.

setdefault(key, default=None)[source]

This method is not supported for a data group

property tree

Returns the default (full) tree representation of this group

property tree_condensed

Returns the condensed tree representation of this group. Uses the _COND_TREE_* prefixed class attributes as parameters.

_format_info() → str[source]

A __format__ helper function: returns an info string that is used to characterize this object. Does NOT include name and classname!

_format_tree() → str[source]

Returns the default tree representation of this group by invoking the .tree property

_format_tree_condensed() → str[source]

Returns the default tree representation of this group by invoking the .tree property

_tree_repr(*, level: int = 0, max_level: int = None, info_fstr='<{:cls_name,info}>', info_ratio: float = 0.6, condense_thresh: Union[int, Callable[[int, int], int]] = None, total_item_count: int = 0) → Union[str, List[str]][source]

Recursively creates a multi-line string tree representation of this group. This is used by, e.g., the _format_tree method.

Parameters
  • level (int, optional) – The depth within the tree

  • max_level (int, optional) – The maximum depth within the tree; recursion is not continued beyond this level.

  • info_fstr (str, optional) – The format string for the info string

  • info_ratio (float, optional) – The width ratio of the whole line width that the info string takes

  • condense_thresh (Union[int, Callable[[int, int], int]], optional) – If given, this specifies the threshold beyond which the tree view for the current element becomes condensed by hiding the output for some elements. The minimum value for this is 3, indicating that there should be at most 3 lines be generated from this level (excluding the lines coming from recursion), i.e.: two elements and one line for indicating how many values are hidden. If a smaller value is given, this is silently brought up to 3. Half of the elements are taken from the beginning of the item iteration, the other half from the end. If given as integer, that number is used. If a callable is given, the callable will be invoked with the current level, number of elements to be added at this level, and the current total item count along this recursion branch. The callable should then return the number of lines to be shown for the current element.

  • total_item_count (int, optional) – The total number of items already created in this recursive tree representation call. Passed on between recursive calls.

Returns

The (multi-line) tree representation of

this group. If this method was invoked with level == 0, a string will be returned; otherwise, a list of strings will be returned.

Return type

Union[str, List[str]]

_DirectInsertionModeMixin__in_direct_insertion_mode = False
_LockDataMixin__locked = False
_MutableMapping__marker = <object object>
__eq__(other) → bool

Evaluates equality by making the following comparisons: identity, strict type equality, and finally: equality of the _data and _attrs attributes, i.e. the private attribute. This ensures that comparison does not trigger any downstream effects like resolution of proxies.

If types do not match exactly, NotImplemented is returned, thus referring the comparison to the other side of the ==.

__format__(spec_str: str) → str

Creates a formatted string from the given specification.

Invokes further methods which are prefixed by _format_.

__repr__() → str

Same as __str__

__sizeof__() → int

Returns the size of the data (in bytes) stored in this container’s data and its attributes.

Note that this value is approximate. It is computed by calling the sys.getsizeof function on the data, the attributes, the name and some caching attributes that each dantro data tree class contains. Importantly, this is not a recursive algorithm.

Also, derived classes might implement further attributes that are not taken into account either. To be more precise in a subclass, create a specific __sizeof__ method and invoke this parent method additionally.

For more information, see the documentation of sys.getsizeof:

__str__() → str

An info string, that describes the object. This invokes the formatting helpers to show the log string (type and name) as well as the info string of this object.

_abc_impl = <_abc_data object>
_attrs = None
_check_data(data: Any) → None

This method can be used to check the data provided to this container

It is called before the data is stored in the __init__ method and should raise an exception or create a warning if the data is not as desired.

This method can be subclassed to implement more specific behaviour. To propagate the parent classes’ behaviour the subclassed method should always call its parent method using super().

Note

The CheckDataMixin provides a generalised implementation of this method to perform some type checks and react to unexpected types.

Parameters

data (Any) – The data to check

_check_name(new_name: str) → None

Called from name.setter and can be used to check the name that the container is supposed to have. On invalid name, this should raise.

This method can be subclassed to implement more specific behaviour. To propagate the parent classes’ behaviour the subclassed method should always call its parent method using super().

Parameters

new_name (str) – The new name, which is to be checked.

_direct_insertion_mode(*, enabled: bool = True)

A context manager that brings the class this mixin is used in into direct insertion mode. While in that mode, the with_direct_insertion() property will return true.

This context manager additionally invokes two callback functions, which can be specialized to perform certain operations when entering or exiting direct insertion mode: Before entering, _enter_direct_insertion_mode() is called. After exiting, _exit_direct_insertion_mode() is called.

Parameters

enabled (bool, optional) – whether to actually use direct insertion mode. If False, will yield directly without setting the toggle. This is equivalent to a null-context.

_enter_direct_insertion_mode()

Called after entering direct insertion mode; can be overwritten to attach additional behaviour.

_exit_direct_insertion_mode()

Called before exiting direct insertion mode; can be overwritten to attach additional behaviour.

_format_cls_name() → str

A __format__ helper function: returns the class name

_format_logstr() → str

A __format__ helper function: returns the log string, a combination of class name and name

_format_name() → str

A __format__ helper function: returns the name

_format_path() → str

A __format__ helper function: returns the path to this container

_lock_hook()

Invoked upon locking.

_unlock_hook()

Invoked upon unlocking.

property classname

Returns the name of this DataContainer-derived class

property data

The stored data.

lock()

Locks the data of this object

property locked

Whether this object is locked

property logstr

Returns the classname and name of this object

property name

The name of this DataContainer-derived object.

property parent

The associated parent of this container or group

property path

The path to get to this container or group from some root path

pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() → (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

raise_if_locked(*, prefix: str = None)

Raises an exception if this object is locked; does nothing otherwise

unlock()

Unlocks the data of this object

update([E, ]**F) → None. Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

property with_direct_insertion

Whether the class this mixin is mixed into is currently in direct insertion mode.