Example #1
0
    def add_terms(self, prop, *terms):
        """Add a list of :class:`Term` and/or strings to a :class:`Property` with a value domain of ``value_set``

        :param Property prop: :class:`Property` to modify
        :param list terms: A list of :class:`Term` instances and/or str

        :class:`Term` instances are created for strings; `Term.value` is set to the string.
        """
        if not isinstance(prop, Property):
            raise ArgError("arg1 must be Property")
        if not re.match("value_set|enum", prop.value_domain):
            raise AttributeError(
                "Property value domain is not value_set or enum, can't add terms"
            )
        if not prop.value_set:
            warn("Creating ValueSet object for Property " + prop.handle)
            prop.value_set = ValueSet({"prop": prop, "_id": str(uuid4())})
            prop.value_set.handle = self.handle + prop.value_set._id[0:8]

        for t in terms:
            if isinstance(t, str):
                warn("Creating Term object for string '{term}'".format(term=t))
                t = Term({"value": t})
            elif not isinstance(t, Term):
                raise ArgError(
                    "encountered arg that was not a str or Term object")
            prop.value_set.terms[t.value] = t
Example #2
0
    def add_edge(self, edge=None):
        """Add an :class:`Edge` to the model.

        :param Edge edge: A :class:`Edge` instance

        The model attribute of ``edge`` is set to `Model.handle`
        """
        if not edge:
            raise ArgError("arg must be Edge, dict, or graph.Node")
        if isinstance(edge, (dict, neo4j.graph.Node)):
            edge = Edge(edge)
        if not edge.src or not edge.dst:
            raise ArgError("edge must have both src and dst set")
        if not edge.model:
            edge.model = self.handle
        if not self.contains(edge.src):
            warn("Edge source node not yet in model; adding it")
            self.add_node(edge.src)
        if not self.contains(edge.dst):
            warn("Edge destination node not yet in model; adding it")
            self.add_node(edge.dst)
        for p in edge.props.values():
            self.add_prop(edge, p)
        self.edges[edge.triplet] = edge
        return edge
Example #3
0
    def add_prop(self, ent, prop=None):
        """Add a :class:`Property` to the model.

        :param Node|Edge ent: Attach ``prop`` to this entity
        :param Property prop: A :class:`Property` instance

        The model attribute of ``prop`` is set to `Model.handle`. Within a model,
        :class:`Property` entities are unique with respect to their
        handle (but can be reused). This method will look for an existing
        property within the model with the given handle, and add an item to
        Model.props pointing to it if found.
        """
        if not isinstance(ent, (Node, Edge)):
            raise ArgError("arg 1 must be Node or Edge")
        if not prop:
            raise ArgError("arg 2 must be Property, dict, or graph.Node")
        if isinstance(prop, (dict, neo4j.graph.Node)):
            handle = prop["handle"]
            pkeys = [x for x in self.props if handle in x]
            if pkeys:
                prop = self.props[pkeys.pop()]
            else:
                prop = Property(prop)
        if not prop.model:
            prop.model = self.handle
        key = [ent.handle] if isinstance(ent, Node) else list(ent.triplet)
        key.append(prop.handle)
        ent.props[getattr(prop, type(prop).mapspec()["key"])] = prop
        self.props[tuple(key)] = prop
        return prop
Example #4
0
    def rm_node(self, node):
        """Remove a :class:`Node` from the Model instance.

        :param Node node: Node to be removed

        Note: A node can't be removed if it is participating in an edge (i.e.,
        if the node is some edge's src or dst attribute)

        *Clarify what happens in the Model object, in the database when versioning
        is off, in the database when versioning is on*
        """
        if not isinstance(node, Node):
            raise ArgError("arg must be a Node object")
        if not self.contains(node):
            warn("node '{node}' not contained in model '{model}'".format(
                node=node.handle, model=self.handle))
            return
        if self.edges_by_src(node) or self.edges_by_dst(node):
            raise ValueError(
                "can't remove node '{node}', it is participating in edges".
                format(node=node.handle))
        for p in node.props:
            try:
                del self.props[(node.handle, p.handle)]
            except:
                pass
        del self.nodes[node.handle]
        self.removed_entities.append(node)
        return node
Example #5
0
 def load_yaml(self):
     """Load YAML files or open file handles specified in constructor"""
     yloader = yaml.loader.Loader
     for f in self.files:
         if isinstance(f, str):
             if re.match("(?:file|https?)://", f):
                 response = requests.get(f)
                 if not response.ok:
                     raise ArgError(
                         "Fetching url {} returned code {}".format(
                             response.url, response.status_code))
                 response.encoding = "utf8"
                 f = response.text
             else:
                 f = open(f, "r")
         try:
             yml = yaml.load(f, Loader=yloader)
             self.schema.update(yml)
         except ConstructorError as ce:
             print("YAML constructor failed in '{fn}':\n{e}".format(
                 fn=f.name, e=ce))
             raise ce
         except ParserError as pe:
             print("YAML parser failed in '{fn}':\n{e}".format(fn=f.name,
                                                               e=pe))
             raise pe
         except Exception:
             raise
Example #6
0
    def rm_edge(self, edge):
        """Remove an :class:`Edge` instance from the Model instance.

        :param Edge edge: Edge to be removed

        *Clarify what happens in the Model object, in the database when versioning
        is off, in the database when versioning is on*
        """
        if not isinstance(edge, Edge):
            raise ArgError("arg must be an Edge object")
        if not self.contains(edge):
            warn("edge '{edge}' not contained in model '{model}'".format(
                edge=edge.triplet, model=self.handle))
            return
        for p in edge.props:
            try:
                k = list(edge.triplet)
                k.append(p.handle)
                del self.props[tuple(k)]
            except:
                pass
        del self.edges[edge.triplet]
        edge.src = None
        edge.dst = None
        self.removed_entities.append(edge)
        return edge
Example #7
0
 def edges_by(self, key, item):
     if key not in ["src", "dst", "type"]:
         raise ArgError("arg 'key' must be one of src|dst|type")
     if isinstance(item, Node):
         idx = 1 if key == "src" else 2
         return [self.edges[x] for x in self.edges if x[idx] == item.handle]
     else:
         return [self.edges[x] for x in self.edges if x[0] == item]
Example #8
0
    def edges_by_type(self, edge_handle):
        """Get all :class:`Edge` that have a given edge type (i.e., handle)

        :param str edge_handle: The edge type
        :return: list of :class:`Edge`
        """
        if not isinstance(edge_handle, str):
            raise ArgError("arg must be str")
        return self.edges_by("type", edge_handle)
Example #9
0
    def edges_out(self, node):
        """Get all :class:`Edge` that have a given :class:`Node` as their src attribute

        :param Node node: The node
        :return: list of :class:`Edge`
        """
        if not isinstance(node, Node):
            raise ArgError("arg must be Node")
        return [self.edges[i] for i in self.edges if i[1] == node.handle]
        pass
Example #10
0
 def mdb(self, value):
     if isinstance(value, MDB):
         self._mdb = value
         for cls in (Node, Property, Edge, Term, ValueSet, Concept,
                     Predicate, Origin, Tag):
             cls.object_map = ObjectMap(cls=cls, drv=value.driver)
     elif not value:
         self._mdb = None
         for cls in (Node, Property, Edge, Term, ValueSet, Concept, Origin,
                     Tag):
             cls.object_map = None
     else:
         raise ArgError("mdb= arg must be a bento_meta.mdb.MDB object")
Example #11
0
    def assign_edge_end(self, edge=None, end=None, node=None):
        """Move the src or dst of an :class:`Edge` to a different :class:`Node`.

        :param Edge edge: Edge to manipulate
        :param str end: Edge end to change (src|dst)
        :param Node node: Node to be connected

        Note: Both ``node`` and ``edge`` must be present in the Model instance
        (via :meth:`add_node` and :meth:`add_edge`)
        """
        if not isinstance(edge, Edge):
            raise ArgError("edge= must an Edge object")
        if not isinstance(node, Node):
            raise ArgError("node= must a Node object")
        if end not in ["src", "dst"]:
            raise ArgError("end= must be one of 'src' or 'dst'")
        if not self.contains(edge) or not self.contains(node):
            warn("model must contain both edge and node")
            return
        del self.edges[edge.triplet]
        setattr(edge, end, node)
        self.edges[edge.triplet] = edge
        return edge
Example #12
0
 def drv(self, value):
     if isinstance(value, (BoltDriver, Neo4jDriver)):
         self._drv = value
         for cls in (Node, Property, Edge, Term, ValueSet, Concept, Origin,
                     Tag):
             cls.object_map = ObjectMap(cls=cls, drv=value)
     elif not value:
         self._drv = None
         for cls in (Node, Property, Edge, Term, ValueSet, Concept, Origin,
                     Tag):
             cls.object_map = None
     else:
         raise ArgError(
             "drv= arg must be Neo4jDriver or BoltDriver (returned from GraphDatabase.driver())"
         )
Example #13
0
 def __init__(self, *yaml_files, handle=None):
     """Create a :class:`Model` from MDF YAML files.
     :param str|file|url *yaml_files: MDF filenames or file objects, in desired merge order
     :param str handle: Handle (name) for the resulting Model
     :attribute model: the :class:`bento_meta.model.Model` created"""
     if not handle or not isinstance(handle, str):
         raise ArgError("arg handle= must be a str - name for model")
     self.handle = handle
     self.files = yaml_files
     self.schema = om.MergedOptions()
     self._model = None
     if self.files:
         self.load_yaml()
         self.create_model()
     else:
         warn("No MDF files provided to constructor")
     pass
Example #14
0
    def add_node(self, node=None):
        """Add a :class:`Node` to the model.

        :param Node node: A :class:`Node` instance

        The model attribute of ``node`` is set to `Model.handle`
        """
        if not node:
            raise ArgError("arg must be Node, dict, or graph.Node")
        if isinstance(node, (dict, neo4j.graph.Node)):
            node = Node(node)
        if not node.model:
            node.model = self.handle
        for p in node.props.values():
            self.add_prop(node, p)
        self.nodes[node.handle] = node
        return node
Example #15
0
    def __init__(self, handle=None, mdb=None):
        """Model constructor.

        :param str handle: A string name for the model. Corresponds to the model property in MDB database nodes.
        :param bento_meta.mdb.MDB mdb: An MDB object containing the db connection (see :class:`bento_meta.mdb.MDB`)
        """
        if not handle:
            raise ArgError("model requires arg 'handle' set")
        self.handle = handle
        self._mdb = None
        self.nodes = {}
        self.edges = {
        }  # keys are (edge.handle, src.handle, dst.handle) tuples
        self.props = {}  # keys are ({edge|node}.handle, prop.handle) tuples
        self.terms = {}
        self.removed_entities = []

        if mdb:
            self.mdb = mdb
Example #16
0
    def __init__(self, handle=None, drv=None):
        """Model constructor.

        :param str handle: A string name for the model. Corresponds to the model property in MDB database nodes.
        :param neo4j.Driver drv: A `neo4j.Driver` object describing the db connection (see :class:`neo4j.GraphDatabase`)
        """
        if not handle:
            raise ArgError("model requires arg 'handle' set")
        self.handle = handle
        self._drv = None
        self.nodes = {}
        self.edges = {
        }  # keys are (edge.handle, src.handle, dst.handle) tuples
        self.props = {}  # keys are ({edge|node}.handle, prop.handle) tuples
        self.terms = {}
        self.removed_entities = []

        if drv:
            self.drv = drv
        else:
            self.drv = None
Example #17
0
    def rm_prop(self, prop):
        """Remove a :class:`Property` instance from the Model instance.

        :param Property prop: Property to be removed

        *Clarify what happens in the Model object, in the database when versioning
        is off, in the database when versioning is on*
        """
        if not isinstance(prop, Property):
            raise ArgError("arg must be a Property object")
        if not self.contains(prop):
            warn("prop '{prop}' not contained in model '{model}'".format(
                prop=prop.handle, model=self.handle))
            return
        for okey in prop.belongs:
            owner = prop.belongs[okey]
            (i, att, key) = okey
            getattr(owner, att)[key] == None
            k = [owner.handle] if isinstance(owner, Node) else list(
                owner.triplet)
            k.append(key)
            del self.props[tuple(k)]
        self.removed_entities.append(prop)
        pass
Example #18
0
 def rm_term(self, term):
     """Not implemented."""
     if not isinstance(term, Term):
         raise ArgError("arg must be a Term object")
     pass