Source code for aiida.orm.utils.links

# -*- coding: utf-8 -*-
###########################################################################
# 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               #
###########################################################################
"""Utilities for dealing with links between nodes."""
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

from collections import namedtuple

from aiida.common import exceptions

__all__ = ('LinkPair', 'LinkTriple', 'LinkManager', 'validate_link')

LinkPair = namedtuple('LinkPair', ['link_type', 'link_label'])
LinkTriple = namedtuple('LinkTriple', ['node', 'link_type', 'link_label'])





[docs]class LinkManager(object): # pylint: disable=useless-object-inheritance """ Class to convert a list of LinkTriple tuples into an iterator. It defines convenience methods to retrieve certain subsets of LinkTriple while checking for consistency. For example:: LinkManager.one(): returns the only entry in the list or it raises an exception LinkManager.first(): returns the first entry from the list LinkManager.all(): returns all entries from list The methods `all_nodes` and `all_link_labels` are syntactic sugar wrappers around `all` to get a list of only the incoming nodes or link labels, respectively. """
[docs] def __init__(self, link_triples): """Initialise the collection.""" self.link_triples = link_triples
[docs] def __iter__(self): """Return an iterator of LinkTriple instances. :return: iterator of LinkTriple instances """ return iter(self.link_triples)
[docs] def __next__(self): """Return the next element in the iterator. :return: LinkTriple """ for link_triple in self.link_triples: yield link_triple
[docs] def next(self): """Return the next element in the iterator. :return: LinkTriple """ return self.__next__()
[docs] def one(self): """Return a single entry from the iterator. If the iterator contains no or more than one entry, an exception will be raised :return: LinkTriple instance :raises ValueError: if the iterator contains anything but one entry """ if self.link_triples: if len(self.link_triples) > 1: raise ValueError('more than one entry found') return self.link_triples[0] raise ValueError('no entries found')
[docs] def first(self): """Return the first entry from the iterator. :return: LinkTriple instance :raises ValueError: if the iterator contains anything but one entry """ if self.link_triples: return self.link_triples[0] raise ValueError('no entries found')
[docs] def all(self): """Return all entries from the list. :return: list of LinkTriple instances """ return self.link_triples
[docs] def all_nodes(self): """Return a list of all nodes. :return: list of nodes """ return [entry.node for entry in self.all()]
[docs] def get_node_by_label(self, label): """Return the node from list for given label. :return: node that corresponds to the given label :raises aiida.common.NotExistent: if the label is not present among the link_triples """ matching_entry = None for entry in self.link_triples: if entry.link_label == label: if matching_entry is None: matching_entry = entry.node else: raise exceptions.MultipleObjectsError( 'more than one neighbor with the label {} found'.format(label)) if matching_entry is None: raise exceptions.NotExistent('no neighbor with the label {} found'.format(label)) return matching_entry