def test_invert(self): prop = model.get_qname('Thing:name') node = Node(registry.entity, 'banana') stmt = Statement(node, prop, "Theodore") assert not stmt.inverted inv = stmt.invert() assert inv.inverted assert inv.rdf() is None banana = Node(registry.entity, 'banana') peach = Node(registry.entity, 'peach') prop = model.get_qname('Thing:sameAs') stmt = Statement(banana, prop, peach.value) inv = stmt.invert() assert inv.subject == peach assert inv.value_node == banana assert inv.prop == stmt.prop
def test_base(self): prop = model.get_qname('Thing:name') node = Node(registry.entity, 'banana') stmt = Statement(node, prop, "Theodore Böln") assert stmt.subject == node value = stmt.to_tuple() other = stmt.from_tuple(model, value) assert other == stmt, (stmt, other) assert hash(other) == hash(stmt) assert repr(other) == repr(stmt)
def test_base(self): prop = model.get_qname('Thing:name') node = Node(registry.entity, 'banana') link = Link(node, prop, "Theodore Böln") assert link.subject == node value = link.to_tuple() other = link.from_tuple(model, value) assert other == link, (link, other) assert hash(other) == hash(link) assert repr(other) == repr(link)
def entity_expand(entity, collection_ids, edge_types, limit, properties=None, authz=None): """Expand an entity's graph to find adjacent entities that are connected by a common property value(eg: having the same email or phone number), a property (eg: Passport entity linked to a Person) or an Entity type edge. (eg: Person connected to Company through Directorship) collection_ids: list of collection_ids to search edge_types: list of FtM Types to expand as edges properties: list of FtM Properties to expand as edges. limit: max number of entities to return """ proxy = model.get_proxy(entity) node = Node.from_proxy(proxy) graph = Graph(edge_types=edge_types) graph.add(proxy) query = graph.query(authz=authz, collection_ids=collection_ids) # Get relevant property set props = set(proxy.schema.properties.values()) props = [p for p in props if p.type in graph.edge_types] properties = ensure_list(properties) if len(properties): props = [p for p in props if p.name in properties] # Query for reverse properties for prop in props: if prop.stub: query.edge(node, prop.reverse, limit=limit, count=True) query.execute() # Fill in missing graph entities: if limit > 0: graph.resolve() for prop in props: count = len(proxy.get(prop)) if prop.stub: for res in query.patterns: if res.prop == prop.reverse: count = res.count proxies = set() # Too much effort to do this right. This works, too: for edge in graph.get_adjacent(node, prop=prop): for part in (edge.proxy, edge.source.proxy, edge.target.proxy): if part is not None and part != proxy: proxies.add(part) if count > 0: yield (prop, count, proxies)
def _expand_adjacent(graph, proxy, prop): """Return all proxies related to the given proxy/prop combo as an array. This creates the very awkward return format for the API, which simply gives you a list of entities and lets the UI put them in some meaningful relation. Gotta revise this some day....""" # Too much effort to do this right. This works, too: adjacent = set() node = Node.from_proxy(proxy) for edge in graph.get_adjacent(node, prop=prop): for part in (edge.proxy, edge.source.proxy, edge.target.proxy): if part is not None and part != proxy: adjacent.add(part) return adjacent
def entity_references(entity, authz=None): """Given a particular entity, find all the references to it from other entities, grouped by the property where they are used.""" proxy = model.get_proxy(entity) node = Node.from_proxy(proxy) graph = Graph() query = graph.query(authz=authz) for prop in proxy.schema.properties.values(): if not prop.stub: continue query.edge(node, prop.reverse, count=True) for res in query.execute(): if res.count > 0: yield (res.prop, res.count)
def entity_tags(entity, authz=None, edge_types=registry.pivots): """Do a search on tags of an entity.""" proxy = model.get_proxy(entity) graph = Graph(edge_types=edge_types) query = graph.query(authz=authz) for prop, value in proxy.itervalues(): if prop.type not in graph.edge_types: continue if prop.specificity(value) < 0.1: continue query.node(Node(prop.type, value), count=True) for res in query.execute(): field = res.node.type.group if res.count is not None and res.count > 1: yield (field, res.node.value, res.count)
def test_graph(self): g = DiGraph() proxy = model.get_proxy(ENTITY) node = proxy.node self.assertEqual(str(node), node.id) for link in proxy.links: link.to_digraph(g) self.assertEqual(g.number_of_edges(), 8) self.assertEqual(g.number_of_nodes(), 9) self.assertIn(node.id, g.nodes) prop = model.get_qname('Thing:name') link = Link(Node(registry.name, 'Bob'), prop, proxy.id, inverted=True) link.to_digraph(g) self.assertEqual(g.number_of_edges(), 9) link = Link(node, prop, 'Blub', weight=0) link.to_digraph(g) self.assertEqual(g.number_of_edges(), 9) prop = model.get_qname('Thing:summary') link = Link(node, prop, 'This is a text') link.to_digraph(g) self.assertEqual(g.number_of_edges(), 9)
def test_adjacent(self): graph = Graph(edge_types=registry.pivots) graph.add(model.get_proxy(ENTITY)) graph.add(model.get_proxy(ENTITY2)) graph.add(model.get_proxy(REL)) graph.add(model.get_proxy(PASS)) node = Node(registry.entity, 'jodie') adj = list(graph.get_adjacent(node)) assert len(adj) == 3, adj node = Node(registry.entity, 'ralph') adj = list(graph.get_adjacent(node)) assert len(adj) == 7, adj node = Node(registry.entity, 'passpoat') adj = list(graph.get_adjacent(node)) assert len(adj) == 2, adj node = Node(registry.entity, 'passpoat') prop = model.get_qname('Passport:holder') adj = list(graph.get_adjacent(node, prop)) assert len(adj) == 1, adj assert adj[0].source_prop == prop, adj[0].source_prop assert adj[0].target_prop == prop.reverse, adj[0].target_prop node = Node(registry.entity, 'jodie') prop = model.get_qname('Person:familyPerson') adj = list(graph.get_adjacent(node, prop)) assert len(adj) == 1, adj assert adj[0].source_prop == prop, adj[0].source_prop node = Node(registry.entity, 'ralph') prop = model.get_qname('Person:familyRelative') adj2 = list(graph.get_adjacent(node, prop)) assert len(adj2) == 1, adj2 assert adj2[0].target_prop == prop, adj2[0].target_prop assert adj[0] == adj2[0], (adj[0], adj2[0]) assert adj[0].id in repr(adj[0]), repr(adj[0])
def test_adjacent(self): graph = Graph(edge_types=registry.pivots) graph.add(model.get_proxy(ENTITY, cleaned=False)) graph.add(model.get_proxy(ENTITY2, cleaned=False)) graph.add(model.get_proxy(REL, cleaned=False)) graph.add(model.get_proxy(PASS, cleaned=False)) node = Node(registry.entity, "jodie") adj = list(graph.get_adjacent(node)) assert len(adj) == 3, adj node = Node(registry.entity, "ralph") adj = list(graph.get_adjacent(node)) assert len(adj) == 7, adj node = Node(registry.entity, "passpoat") adj = list(graph.get_adjacent(node)) assert len(adj) == 2, adj node = Node(registry.entity, "passpoat") prop = model.get_qname("Identification:holder") adj = list(graph.get_adjacent(node, prop)) assert len(adj) == 1, adj assert adj[0].source_prop == prop, adj[0].source_prop assert adj[0].target_prop == prop.reverse, adj[0].target_prop node = Node(registry.entity, "jodie") prop = model.get_qname("Person:familyPerson") adj = list(graph.get_adjacent(node, prop)) assert len(adj) == 1, adj assert adj[0].source_prop == prop, adj[0].source_prop node = Node(registry.entity, "ralph") prop = model.get_qname("Person:familyRelative") adj2 = list(graph.get_adjacent(node, prop)) assert len(adj2) == 1, adj2 assert adj2[0].target_prop == prop, adj2[0].target_prop assert adj[0] == adj2[0], (adj[0], adj2[0]) assert adj[0].id in repr(adj[0]), repr(adj[0])
def node(self): if self.id is None: return return Node(registry.entity, self.id)
def test_nodes(self): node = Node(registry.phone, '+4917778271717') assert '+49177' in repr(node), repr(node) assert node == node, repr(node) assert node.caption == str(node), str(node) assert hash(node) == hash(node.id), repr(node)