Ejemplo n.º 1
0
    def set_attribute(self, key, value):
        """Set an attribute to the given value.

        :param key: name of the attribute
        :param value: value of the attribute
        :raise aiida.common.exceptions.ModificationNotAllowed: if the node is already sealed or if the node
            is already stored and the attribute is not updatable.
        """
        if self.is_sealed:
            raise exceptions.ModificationNotAllowed('attributes of a sealed node are immutable')

        if self.is_stored and key not in self._updatable_attributes:  # pylint: disable=unsupported-membership-test
            raise exceptions.ModificationNotAllowed('`{}` is not an updatable attribute'.format(key))

        self.backend_entity.set_attribute(key, value)
Ejemplo n.º 2
0
    def delete_attribute(self, key):
        """Delete an attribute.

        :param key: name of the attribute
        :raises AttributeError: if the attribute does not exist
        :raise aiida.common.exceptions.ModificationNotAllowed: if the node is already sealed or if the node
            is already stored and the attribute is not updatable.
        """
        if self.is_sealed:
            raise exceptions.ModificationNotAllowed('attributes of a sealed node are immutable')

        if self.is_stored and key not in self._updatable_attributes:  # pylint: disable=unsupported-membership-test
            raise exceptions.ModificationNotAllowed('`{}` is not an updatable attribute'.format(key))

        self.backend_entity.delete_attribute(key)
Ejemplo n.º 3
0
    def restore(self):
        """Move the contents from the repository folder back into the sandbox folder."""
        if not self._is_stored:
            raise exceptions.ModificationNotAllowed('repository is not yet stored')

        self._temp_folder.replace_with_folder(self._repo_folder.abspath, move=True, overwrite=True)
        self._is_stored = False
Ejemplo n.º 4
0
    def store(self):
        """Store the contents of the sandbox folder into the repository folder."""
        if self._is_stored:
            raise exceptions.ModificationNotAllowed('repository is already stored')

        self._repo_folder.replace_with_folder(self._get_temp_folder().abspath, move=True, overwrite=True)
        self._is_stored = True
Ejemplo n.º 5
0
    def clear_attributes(self):
        """Delete all attributes."""
        if self.is_stored:
            raise exceptions.ModificationNotAllowed(
                'the attributes of a stored entity are immutable')

        self.backend_entity.clear_attributes()
Ejemplo n.º 6
0
    def add_nodes(self, nodes):
        """Add a node or a set of nodes to the family.

        .. note: Each family instance can only contain a single pseudo potential for each element.

        :param nodes: a single or list of ``Node`` instances of type that is in ``PseudoPotentialFamily._pseudo_types``.
        :raises ModificationNotAllowed: if the family is not stored.
        :raises TypeError: if nodes are not an instance or list of instance of any of the classes listed by
            ``PseudoPotentialFamily._pseudo_types``.
        :raises ValueError: if any of the nodes are not stored or their elements already exist in this family.
        """
        if not self.is_stored:
            raise exceptions.ModificationNotAllowed('cannot add nodes to an unstored group')

        if not isinstance(nodes, (list, tuple)):
            nodes = [nodes]

        if any(not isinstance(node, self._pseudo_types) for node in nodes):
            raise TypeError(f'only nodes of types `{self._pseudo_types}` can be added: {nodes}')

        pseudos = {}

        # Check for duplicates before adding any pseudo to the internal cache
        for pseudo in nodes:
            if pseudo.element in self.elements:
                raise ValueError(f'element `{pseudo.element}` already present in this family')
            pseudos[pseudo.element] = pseudo

        self.pseudos.update(pseudos)
        self.update_pseudo_type()

        super().add_nodes(nodes)
Ejemplo n.º 7
0
    def validate_mutability(self):
        """Raise if the repository is immutable.

        :raises aiida.common.ModificationNotAllowed: if repository is marked as immutable because the corresponding node
            is stored
        """
        if self._is_stored:
            raise exceptions.ModificationNotAllowed('cannot modify the repository after the node has been stored')
Ejemplo n.º 8
0
    def store(self):
        """Can only store if both the node and user are stored as well."""
        if self._dbmodel.dbnode.id is None or self._dbmodel.user.id is None:
            self._dbmodel.dbnode = None
            raise exceptions.ModificationNotAllowed(
                'The corresponding node and/or user are not stored')

        super().store()
Ejemplo n.º 9
0
    def add_incoming(self, source, link_type, link_label):
        """Add a link of the given type from a given node to ourself.

        :param source: the node from which the link is coming
        :param link_type: the link type
        :param link_label: the link label
        :return: True if the proposed link is allowed, False otherwise
        :raise aiida.common.ModificationNotAllowed: if either source or target node is not stored
        """
        type_check(source, DjangoNode)

        if not self.is_stored:
            raise exceptions.ModificationNotAllowed('node has to be stored when adding an incoming link')

        if not source.is_stored:
            raise exceptions.ModificationNotAllowed('source node has to be stored when adding a link from it')

        self._add_link(source, link_type, link_label)
Ejemplo n.º 10
0
    def store(self):
        """Can only store if both the node and user are stored as well."""
        from aiida.backends.djsite.db.models import suppress_auto_now

        if self._dbmodel.dbnode.id is None or self._dbmodel.user.id is None:
            raise exceptions.ModificationNotAllowed('The corresponding node and/or user are not stored')

        with suppress_auto_now([(models.DbComment, ['mtime'])]) if self.mtime else contextlib.nullcontext():
            super().store()
Ejemplo n.º 11
0
    def out(self, link_label, node):
        """Register a node as an output with the given link label.

        :param link_label: the name of the link label
        :param node: the node to register as an output
        :raises aiida.common.ModificationNotAllowed: if an output node was already registered with the same link label
        """
        if link_label in self._outputs:
            raise exceptions.ModificationNotAllowed('the output {} already exists'.format(link_label))
        self._outputs[link_label] = node
Ejemplo n.º 12
0
    def store(self):
        """Can only store if both the node and user are stored as well."""
        from aiida.backends.djsite.db.models import suppress_auto_now

        if self._dbmodel.dbnode.id is None or self._dbmodel.user.id is None:
            raise exceptions.ModificationNotAllowed('The corresponding node and/or user are not stored')

        # `contextlib.suppress` provides empty context and can be replaced with `contextlib.nullcontext` after we drop
        # support for python 3.6
        with suppress_auto_now([(models.DbComment, ['mtime'])]) if self.mtime else contextlib.suppress():
            super().store()
Ejemplo n.º 13
0
    def delete_attribute(self, key):
        """Delete an attribute.

        :param key: name of the attribute
        :raises AttributeError: if the attribute does not exist
        :raise aiida.common.ModificationNotAllowed: if the entity is stored
        """
        if self.is_stored:
            raise exceptions.ModificationNotAllowed(
                'the attributes of a stored entity are immutable')

        self.backend_entity.delete_attribute(key)
Ejemplo n.º 14
0
    def delete_attribute_many(self, keys):
        """Delete multiple attributes.

        :param keys: names of the attributes to delete
        :raises AttributeError: if at least one of the attribute does not exist
        :raise aiida.common.ModificationNotAllowed: if the entity is stored
        """
        if self.is_stored:
            raise exceptions.ModificationNotAllowed(
                'the attributes of a stored entity are immutable')

        self.backend_entity.delete_attribute_many(keys)
Ejemplo n.º 15
0
    def set_attribute(self, key, value):
        """Set an attribute to the given value.

        :param key: name of the attribute
        :param value: value of the attribute
        :raise aiida.common.ValidationError: if the key is invalid, i.e. contains periods
        :raise aiida.common.ModificationNotAllowed: if the entity is stored
        """
        if self.is_stored:
            raise exceptions.ModificationNotAllowed(
                'the attributes of a stored entity are immutable')

        self.backend_entity.set_attribute(key, value)
Ejemplo n.º 16
0
    def set_attribute_many(self, attributes):
        """Set multiple attributes.

        .. note:: This will override any existing attributes that are present in the new dictionary.

        :param attributes: a dictionary with the attributes to set
        :raise aiida.common.ValidationError: if any of the keys are invalid, i.e. contain periods
        :raise aiida.common.ModificationNotAllowed: if the entity is stored
        """
        if self.is_stored:
            raise exceptions.ModificationNotAllowed(
                'the attributes of a stored entity are immutable')

        self.backend_entity.set_attribute_many(attributes)
Ejemplo n.º 17
0
    def reset_attributes(self, attributes):
        """Reset the attributes.

        .. note:: This will completely clear any existing attributes and replace them with the new dictionary.

        :param attributes: a dictionary with the attributes to set
        :raise aiida.common.ValidationError: if any of the keys are invalid, i.e. contain periods
        :raise aiida.common.ModificationNotAllowed: if the entity is stored
        """
        if self.is_stored:
            raise exceptions.ModificationNotAllowed(
                'the attributes of a stored entity are immutable')

        self.backend_entity.reset_attributes(attributes)
Ejemplo n.º 18
0
    def validate_outgoing(self, target, link_type, link_label):
        """Validate adding a link of the given type from ourself to a given node.

        Adding an outgoing link from a sealed node is forbidden.

        :param target: the node to which the link is going
        :param link_type: the link type
        :param link_label: the link label
        :raise aiida.common.ModificationNotAllowed: if the source node (self) is sealed
        """
        if self.is_sealed:
            raise exceptions.ModificationNotAllowed('Cannot add a link from a sealed node')

        super().validate_outgoing(target, link_type=link_type, link_label=link_label)
Ejemplo n.º 19
0
    def validate_incoming(self, source, link_type, link_label):
        """Validate adding a link of the given type from a given node to ourself.

        Adding an incoming link to a sealed node is forbidden.

        :param source: the node from which the link is coming
        :param link_type: the link type
        :param link_label: the link label
        :raise aiida.common.ModificationNotAllowed: if the target node (self) is sealed
        """
        if self.is_sealed:
            raise exceptions.ModificationNotAllowed('Cannot add a link to a sealed node')

        super().validate_incoming(source, link_type=link_type, link_label=link_label)
Ejemplo n.º 20
0
    def remove_nodes(self, nodes):
        """Remove a node or a set of nodes to the group.

        :note: all the nodes *and* the group itself have to be stored.

        :param nodes: a single `Node` or a list of `Nodes`
        :type nodes: :class:`aiida.orm.Node` or list
        """
        from .nodes import Node

        if not self.is_stored:
            raise exceptions.ModificationNotAllowed('cannot add nodes to an unstored group')

        # Cannot use `collections.Iterable` here, because that would also match iterable `Node` sub classes like `List`
        if not isinstance(nodes, (list, tuple)):
            nodes = [nodes]

        for node in nodes:
            type_check(node, Node)

        self._backend_entity.remove_nodes([node.backend_entity for node in nodes])
Ejemplo n.º 21
0
    def add_nodes(self, nodes):
        """Add a node or a set of nodes to the basis set.

        .. note: Each basis set instance can only contain a single basis for each element.

        :param nodes: a single or list of ``Node`` instances of type that is in ``BasisSet._basis_types``.
        :raises ModificationNotAllowed: if the basis set is not stored.
        :raises TypeError: if nodes are not an instance or list of instance of any of the classes listed by
            ``BasisSet._basis_types``.
        :raises ValueError: if any of the nodes are not stored or their elements already exist in this basis set.
        """
        if not self.is_stored:
            raise exceptions.ModificationNotAllowed(
                'cannot add nodes to an unstored group')

        if not isinstance(nodes, (list, tuple)):
            nodes = [nodes]

        if any(not isinstance(node, self._basis_types) for node in nodes):
            raise TypeError(
                f'only nodes of types `{self._basis_types}` can be added: {nodes}'
            )

        bases = {}

        # Check for duplicates before adding any basis to the internal cache
        for basis in nodes:
            if basis.element in self.elements:
                raise ValueError(
                    f'element `{basis.element}` already present in this basis set'
                )
            bases[basis.element] = basis

        self.bases.update(bases)
        self.update_basis_type()

        super().add_nodes(nodes)