Source code for aiida.orm.extras

###########################################################################
# Copyright (c), The AiiDA team. All rights reserved.                     #
# This file is part of the AiiDA code.                                    #
#                                                                         #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core #
# For further information on the license, see the LICENSE.txt file        #
# For further information please visit http://www.aiida.net               #
###########################################################################
"""Interface to the extras of a node instance."""
import copy
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple, Union

if TYPE_CHECKING:
    from .groups import Group
    from .nodes.node import Node

__all__ = ('EntityExtras',)

_NO_DEFAULT: Any = tuple()


[docs] class EntityExtras: """Interface to the extras of a node or group instance. Extras are a JSONable dictionary, stored on each entity, allowing for arbitrary data to be stored by users. Extras are mutable, even after storing the entity, and as such are not deemed a core part of the provenance graph. """
[docs] def __init__(self, entity: Union['Node', 'Group']) -> None: """Initialize the interface.""" self._entity = entity self._backend_entity = entity.backend_entity
[docs] def __contains__(self, key: str) -> bool: """Check if the extras contain the given key.""" return key in self._backend_entity.extras
@property def all(self) -> Dict[str, Any]: """Return the complete extras dictionary. .. warning:: While the entity is unstored, this will return references of the extras on the database model, meaning that changes on the returned values (if they are mutable themselves, e.g. a list or dictionary) will automatically be reflected on the database model as well. As soon as the entity is stored, the returned extras will be a deep copy and mutations of the database extras will have to go through the appropriate set methods. Therefore, once stored, retrieving a deep copy can be a heavy operation. If you only need the keys or some values, use the iterators `extras_keys` and `extras_items`, or the getters `get_extra` and `get_extra_many` instead. :return: the extras as a dictionary """ extras = self._backend_entity.extras if self._entity.is_stored: extras = copy.deepcopy(extras) return extras
[docs] def get(self, key: str, default: Any = _NO_DEFAULT) -> Any: """Return the value of an extra. .. warning:: While the entity is unstored, this will return a reference of the extra on the database model, meaning that changes on the returned value (if they are mutable themselves, e.g. a list or dictionary) will automatically be reflected on the database model as well. As soon as the entity is stored, the returned extra will be a deep copy and mutations of the database extras will have to go through the appropriate set methods. :param key: name of the extra :param default: return this value instead of raising if the attribute does not exist :return: the value of the extra :raises AttributeError: if the extra does not exist and no default is specified """ try: extra = self._backend_entity.get_extra(key) except AttributeError: if default is _NO_DEFAULT: raise extra = default if self._entity.is_stored: extra = copy.deepcopy(extra) return extra
[docs] def get_many(self, keys: List[str]) -> List[Any]: """Return the values of multiple extras. .. warning:: While the entity is unstored, this will return references of the extras on the database model, meaning that changes on the returned values (if they are mutable themselves, e.g. a list or dictionary) will automatically be reflected on the database model as well. As soon as the entity is stored, the returned extras will be a deep copy and mutations of the database extras will have to go through the appropriate set methods. Therefore, once stored, retrieving a deep copy can be a heavy operation. If you only need the keys or some values, use the iterators `extras_keys` and `extras_items`, or the getters `get_extra` and `get_extra_many` instead. :param keys: a list of extra names :return: a list of extra values :raises AttributeError: if at least one extra does not exist """ extras = self._backend_entity.get_extra_many(keys) if self._entity.is_stored: extras = copy.deepcopy(extras) return extras
[docs] def set(self, key: str, value: Any) -> None: """Set an extra to the given value. :param key: name of the extra :param value: value of the extra :raise aiida.common.ValidationError: if the key is invalid, i.e. contains periods """ self._backend_entity.set_extra(key, value)
[docs] def set_many(self, extras: Dict[str, Any]) -> None: """Set multiple extras. .. note:: This will override any existing extras that are present in the new dictionary. :param extras: a dictionary with the extras to set :raise aiida.common.ValidationError: if any of the keys are invalid, i.e. contain periods """ self._backend_entity.set_extra_many(extras)
[docs] def reset(self, extras: Dict[str, Any]) -> None: """Reset the extras. .. note:: This will completely clear any existing extras and replace them with the new dictionary. :param extras: a dictionary with the extras to set :raise aiida.common.ValidationError: if any of the keys are invalid, i.e. contain periods """ self._backend_entity.reset_extras(extras)
[docs] def delete(self, key: str) -> None: """Delete an extra. :param key: name of the extra :raises AttributeError: if the extra does not exist """ self._backend_entity.delete_extra(key)
[docs] def delete_many(self, keys: List[str]) -> None: """Delete multiple extras. :param keys: names of the extras to delete :raises AttributeError: if at least one of the extra does not exist """ self._backend_entity.delete_extra_many(keys)
[docs] def clear(self) -> None: """Delete all extras.""" self._backend_entity.clear_extras()
[docs] def items(self) -> Iterable[Tuple[str, Any]]: """Return an iterator over the extras. :return: an iterator with extra key value pairs """ return self._backend_entity.extras_items()
[docs] def keys(self) -> Iterable[str]: """Return an iterator over the extra keys. :return: an iterator with extra keys """ return self._backend_entity.extras_keys()