def test_loop(self): assert dave_works_for_dave.start_node == dave assert dave_works_for_dave.end_node == dave assert list( walk(dave_works_for_dave)) == [dave, dave_works_for_dave, dave] assert set(dave_works_for_dave.nodes) == {dave} assert set(dave_works_for_dave.relationships) == {dave_works_for_dave}
def test_relationship(self): assert alice_knows_bob.start_node == alice assert alice_knows_bob.end_node == bob assert list(walk(alice_knows_bob)) == [alice, alice_knows_bob, bob] assert type(alice_knows_bob).__name__ == "KNOWS" assert dict(alice_knows_bob) == {"since": 1999} assert alice_knows_bob["since"] == 1999 assert set(alice_knows_bob.nodes) == {alice, bob} assert set(alice_knows_bob.relationships) == {alice_knows_bob}
def test_construction_of_path_length_0(self): sequence = [alice] path = Path(*sequence) assert len(path) == 0 assert set(path.nodes) == {alice} assert set(path.relationships) == set() assert path.start_node == alice assert path.end_node == alice assert len(path) == 0 assert list(walk(path)) == sequence
def test_construction_of_path_length_1(self): sequence = [alice, alice_knows_bob, bob] path = Path(*sequence) assert len(path) == 1 assert set(path.nodes) == {alice, bob} assert set(path.relationships) == {alice_knows_bob} assert path.start_node == alice assert path.end_node == bob assert len(path) == 1 assert list(walk(path)) == sequence
def test_construction_of_path_with_loop(self): sequence = [carol, carol_married_to_dave, dave, dave_works_for_dave, dave] path = Path(*sequence) assert len(path) == 2 assert set(path.nodes) == {carol, dave} assert set(path.relationships) == {carol_married_to_dave, dave_works_for_dave} assert path.start_node == carol assert path.end_node == dave assert len(path) == 2 assert list(walk(path)) == sequence
def test_construction_of_path_length_2(self): sequence = [alice, alice_knows_bob, bob, carol_dislikes_bob, carol] path = Path(*sequence) assert len(path) == 2 assert set(path.nodes) == {alice, bob, carol} assert set(path.relationships) == {alice_knows_bob, carol_dislikes_bob} assert path.start_node == alice assert path.end_node == carol assert len(path) == 2 assert list(walk(path)) == sequence
def test_construction_of_path_with_revisits(self): sequence = [alice, alice_knows_bob, bob, carol_dislikes_bob, carol, alice_likes_carol, alice, alice_knows_bob, bob] path = Path(*sequence) assert len(path) == 4 assert set(path.nodes) == {alice, bob, carol} assert set(path.relationships) == {alice_knows_bob, alice_likes_carol, carol_dislikes_bob} assert path.start_node == alice assert path.end_node == bob assert len(path) == 4 assert list(walk(path)) == sequence
def test_node(self): assert alice.start_node == alice assert alice.end_node == alice assert alice.__bool__() assert alice.__nonzero__() assert len(alice) == 2 assert list(walk(alice)) == [alice] assert set(alice.labels) == {"Person", "Employee"} assert dict(alice) == {"name": "Alice", "age": 33} assert dict(alice)["name"] == "Alice" assert alice["name"] == "Alice" assert len(alice.nodes) == 1 assert len(alice.relationships) == 0 assert set(alice.nodes) == {alice} assert set(alice.relationships) == set()
def drawSubgraph(subgraph, options, physics=False, height="400", filename=None, node_shape='dot', edge_width=1.0): # slightly adapted version of draw which fixes compatibility issues with py2neo # draws a py2neo Subgraph object in an IFrame which can be displayed in a jupyter notebook # rendering is based on the vis.js library nodes = [] edges = [] def get_vis_info(node): node_label = list(node.labels)[0] prop_key = options.get(node_label) vis_label = node[prop_key] #return {"id": node["node_id"], "label": vis_label, "group": node_label, "title": repr(dict(node))} return { "id": node["node_id"], "label": vis_label, "group": node_label, "title": vis_label } for node in subgraph.nodes: info = get_vis_info(node) if info not in nodes: nodes.append(info) from py2neo.data import walk for rel in subgraph.relationships: elements = list(walk(rel)) source_info = get_vis_info(elements[0]) target_info = get_vis_info(elements[2]) edges.append({ "from": source_info["id"], "to": target_info["id"], "label": elements[1].__class__.__name__ }) return vis_network(nodes, edges, physics=physics, height=height, filename=filename, node_shape=node_shape, edge_width=edge_width)
def test_can_walk_node_relationship_and_node_in_reverse(self): result = list(walk(bob, alice_knows_bob, alice)) assert result == [bob, alice_knows_bob, alice]
def test_can_walk_node_relationship_and_node(self): result = list(walk(alice, alice_knows_bob, bob)) assert result == [alice, alice_knows_bob, bob]
def test_can_walk_node_twice(self): result = list(walk(alice, alice)) assert result == [alice]
def test_can_walk_nothing(self): result = list(walk()) assert result == []
def _process_node_on_graph(self, note: Note): if smdc.DEBUG: print(note, flush=True) in_graph = self.nodes.match(**{ 'name': note.name, PROP_VAULT: self.vault_name }) if len(in_graph) == 0: # Create new node node = node_from_note(note, self.tags, self.communities, self.args.community) if smdc.DEBUG: print("creating") print(node, flush=True) self.graph.create(node) return # Update node = in_graph.first() if smdc.DEBUG: print("updating") print(node, flush=True) # Update labels node.clear_labels() note_tags = [CAT_NO_TAGS] if note.tags: note_tags = list(map(escape_cypher, note.tags)) node.update_labels(note_tags) for tag in note_tags: if tag not in self.tags: create_index(self.graph, tag) self.tags.append(tag) # Update properties node.clear() escaped_properties = {} for key, value in note.properties.items(): escaped_properties[key] = escape_cypher(str(value)) escaped_properties[PROP_COMMUNITY] = get_community( note, self.communities, self.args.community) node.update(escaped_properties) self.graph.push(node) # # Delete active relations # self._clear_outgoing(node) # Insert up-to-date relations rels_to_create = [] nodes_to_create = [] not_matched_active_rels = list( map(lambda r: r.identity, self.relationships.match([node, None]))) for trgt, rels in note.out_rels.items(): trgt_node = self.nodes.match(**{ 'name': trgt, PROP_VAULT: self.vault_name }) if len(trgt_node) == 0: trgt_node = create_dangling(trgt, self.vault_name, self.tags) nodes_to_create.append(trgt_node) else: trgt_node = trgt_node.first() # Possibly refactor this with for i, rel in enumerate(rels): properties = {} for property, value in rel.properties.items(): properties[property] = escape_cypher(str(value)) rel_type = escape_cypher(rel.type) found_rel = False active_rels = list( filter(lambda r: r.identity in not_matched_active_rels, self.relationships.match([node, None]))) # Update instead of removing makes sure the relationship has a persistent id for active_rel in active_rels: walks = list(walk(active_rel)) if type(active_rel ).__name__ == rel_type and walks[2] == trgt_node: # Maybe this can leave dangling properties? But that'' an edge case. Not sure how to clear properties. active_rel.clear() active_rel.update(properties) self.graph.push(active_rel) found_rel = True not_matched_active_rels.remove(active_rel.identity) break if not found_rel: rels_to_create.append( Relationship(node, rel_type, trgt_node, **properties)) if rels_to_create or nodes_to_create: self.graph.create( Subgraph(nodes=nodes_to_create, relationships=rels_to_create)) if len(not_matched_active_rels) > 0: rels = list( filter(lambda r: r.identity in not_matched_active_rels, self.relationships.match([node, None]))) if len(rels) > 0: self.graph.separate(Subgraph(relationships=rels)) print("onSMDRelDeletedEvent/" + "/".join(map(str, not_matched_active_rels)))
def test_cannot_walk_non_walkable_as_first_argument(self): with self.assertRaises(TypeError): list(walk(object()))
def getServeFromPerson(self, p_node): relation_res = self.RelationshipMather.match({p_node}, r_type="serve") return [list(walk(i)) for i in list(relation_res)]
def getHoldFromCompany(self, c_node): relation_res = self.RelationshipMather.match({c_node}, r_type="hold") return [list(walk(i)) for i in list(relation_res)]
def test_walking_matched_relationships(movie_graph): keanu = movie_graph.nodes.match("Person", name="Keanu Reeves").first() acting = movie_graph.match((keanu, ), "ACTED_IN").order_by("endNode(_).title").all() for i, acted in enumerate(acting): walked = [dict(x) for x in walk(acted)] assert walked[0] == {'name': 'Keanu Reeves', 'born': 1964} assert walked[1] == [ { 'roles': ['Johnny Mnemonic'] }, { 'roles': ['Julian Mercer'] }, { 'roles': ['Kevin Lomax'] }, { 'roles': ['Neo'] }, { 'roles': ['Neo'] }, { 'roles': ['Neo'] }, { 'roles': ['Shane Falco'] }, ][i] assert walked[2] == [ { 'title': 'Johnny Mnemonic', 'tagline': 'The hottest data on earth. ' 'In the coolest head in town', 'released': 1995 }, { 'title': "Something's Gotta Give", 'released': 2003 }, { 'title': "The Devil's Advocate", 'tagline': 'Evil has its winning ways', 'released': 1997 }, { 'title': 'The Matrix', 'tagline': 'Welcome to the Real World', 'released': 1999 }, { 'title': 'The Matrix Reloaded', 'tagline': 'Free your mind', 'released': 2003 }, { 'title': 'The Matrix Revolutions', 'tagline': 'Everything that has a beginning ' 'has an end', 'released': 2003 }, { 'title': 'The Replacements', 'tagline': 'Pain heals, Chicks dig scars... ' 'Glory lasts forever', 'released': 2000 }, ][i]
def test_cannot_walk_non_walkable_as_second_argument(self): with self.assertRaises(TypeError): list(walk(alice, object()))
def _print_debug_rel(self, node, relationship): print(len(list(self.relationships.match([node, None])))) l = list(walk(relationship)) print(l[0].identity, l[0]["name"]) print(l[1]) print(l[2].identity, l[2]["name"])