def get_edge_by_uuid(self, edge_name, uuid): """retrieves a edge by id :param edge_name: the edge name or type :param uuid: the uuid value """ edge_name = resolve_edge_name(edge_name) pattern = os.sep.join([edge_name, '_ids', uuid]) for entry in self.glob(pattern): edge_blob_id = self.repository[entry.oid].data blob = self.repository[edge_blob_id] return Edge.from_data(edge_name, **self.deserialize(blob.data))
def scan_all(self, edge_name=None, treeish=None, pattern='*'): """scans all nodes :returns: a generator that produces :py:class:`Edge` instances with the scanned data """ edge_name = resolve_edge_name(edge_name) treeish = treeish or self.repository.index pattern = os.path.join(edge_name, 'objects', pattern) for entry in self.glob(pattern): blob = self.repository[entry.oid] data = self.deserialize(blob.data) yield Edge.from_data(edge_name, **data)
def add_spo(self, edge, predicate, data): """creates a staged entry of edge, predicate and object :param edge: :param predicate: :param data: :returns: ``bytes`` - the blob id """ edge = resolve_edge_name(edge) blob_id = self.repository.create_blob(data) entry = IndexEntry(os.path.join(edge, predicate), blob_id, GIT_FILEMODE_BLOB) self.repository.index.add(entry) return blob_id
def test_resolve_edge_name(): 'resolve_edge_name() should return a string' resolve_edge_name('Vehicle').should.equal('Vehicle') resolve_edge_name(None).should.equal('*') resolve_edge_name(Vehicle).should.equal('Vehicle') resolve_edge_name.when.called_with({}).should.have.raised( TypeError, 'resolve_edge_name() takes a Edge subclass, a string or None. Got {}' )
def match_edges_by_index(self, edge_name, field_name, match_callback): """retrieves multiple edges by indexed field :param edge_name: the edge name or type :param uuid: the uuid value """ edge_name = resolve_edge_name(edge_name) pattern = os.sep.join([edge_name or '*', 'indexes', '*']) # for index, oid in filter(lambda (index, oid): field_name in index, self.glob(pattern)): for index, oid in self.trace_path(self.glob(pattern)): path, blob_id = os.path.split(index) edge_name = path.split(os.sep)[0] value = self.repository[oid].data if match_callback(value): blob = self.repository[blob_id] data = self.deserialize(blob.data) Definition = Edge.definition(edge_name) yield Definition(**data)
def create_edge(self, edge, **obj): """creates a staged edge entry including its indexed fields. :param edge: a string or a :py:class:`Edge` subclass reference :param ``**kw``: the field values :returns: an instance of the given edge """ predicate_ids = [] edge = resolve_edge_name(edge) edge_uuid = obj.pop('uuid', generate_uuid()) obj['uuid'] = edge_uuid edge_data = self.serialize(obj) object_hash = bytes(pygit2.hash(edge_data)) object_path = os.path.join(edge, 'objects') id_path = os.path.join(edge, '_ids') uuid_path = os.path.join(edge, '_uuids') indexes = {} for key in obj.keys(): value = obj.get(key, None) if edge_has_index(edge, key): indexes[key] = value predicate_path = os.path.join(edge, 'indexes', key) predicate_ids.append( self.add_spo(predicate_path, object_hash, value)) self.add_spo(object_path, object_hash, edge_data) self.add_spo(id_path, edge_uuid, object_hash) self.add_spo(uuid_path, object_hash, edge_uuid) return Edge.from_data(edge, **obj)
def create_vertex(self, vertex, **obj): """creates a staged vertex entry including its indexed fields. :param vertex: a string or a :py:class:`Vertex` subclass reference :param ``**kw``: the field values :returns: an instance of the given vertex """ vertex = resolve_vertex_name(vertex) predicate_ids = [] vertex_uuid = obj.pop('uuid', generate_uuid()) obj['uuid'] = vertex_uuid vertex_data = self.serialize(obj) object_hash = bytes(pygit2.hash(vertex_data)) object_path = os.path.join(vertex, 'objects') id_path = os.path.join(vertex, '_ids') uuid_path = os.path.join(vertex, '_uuids') original_obj = obj.copy() origin = obj.pop('origin') target = obj.pop('target') indexes = {} for key in obj.keys(): value = obj.get(key, None) if vertex_has_index(vertex, key): indexes[key] = value predicate_path = os.path.join(vertex, 'indexes', key) predicate_ids.append( self.add_spo(predicate_path, object_hash, value)) self.add_spo(id_path, vertex_uuid, object_hash) self.add_spo(uuid_path, object_hash, vertex_uuid) origin_name = resolve_edge_name(origin) target_name = resolve_edge_name(target) RelationhipModel = Vertex.definition(vertex) label = RelationhipModel.label # call('Car/incoming/bought_by/Person', 'chuck-uuid', 'car-uuid'), # call('___vertices___/Car/bought_by/Person', 'chuck-uuid', 'car-uuid'), path_templates = { 'incoming': '{to}/incoming/{label}/{from}', 'outgoing': '{from}/outgoing/{label}/{to}', 'indirect': '{}/indirect/{label}/{}', } vertex_path_template = path_templates[RelationhipModel.direction] ctx = {'label': label} direction = RelationhipModel.direction # self.add_spo(object_path, object_hash, vertex_data) if direction == 'incoming': from_uuid = origin.uuid ctx['from'] = origin_name to_uuid = target.uuid ctx['to'] = target_name vertex_path = vertex_path_template.format(**ctx) self.add_spo(vertex_path, from_uuid, to_uuid) elif direction == 'outgoing': from_uuid = target.uuid ctx['from'] = target_name to_uuid = origin.uuid ctx['to'] = origin_name vertex_path = vertex_path_template.format(**ctx) self.add_spo(vertex_path, from_uuid, to_uuid) elif direction == 'indirect': from_uuid = target.uuid to_uuid = origin.uuid path = vertex_path_template.format(target_name, origin_name, **ctx) self.add_spo(path, from_uuid, to_uuid) path = vertex_path_template.format(origin_name, target_name, **ctx) self.add_spo(path, to_uuid, from_uuid) return RelationhipModel.from_data(vertex, **original_obj)