Пример #1
0
 def test_can_create_relationship(self):
     a = Node("Person", name="Alice")
     b = Node("Person", name="Bob")
     r = Relationship(a, "KNOWS", b, since=1999)
     self.graph.create(r)
     assert remote(a)
     assert remote(b)
     assert remote(r)
     assert r.start_node() == a
     assert r.end_node() == b
Пример #2
0
 def test_walkable_repr(self):
     a = Node("Person", name="Alice")
     b = Node("Person", name="Bob")
     c = Node("Person", name="Carol")
     d = Node("Person", name="Dave")
     ab = Relationship(a, "LOVES", b)
     cb = Relationship(c, "HATES", b)
     cd = Relationship(c, "KNOWS", d)
     t = Walkable([a, ab, b, cb, c, cd, d])
     r = repr(t)
     expected = "(alice)-[:LOVES]->(bob)<-[:HATES]-(carol)-[:KNOWS]->(dave)"
     assert r == expected
Пример #3
0
 def hydrate_(data, inst=None):
     if isinstance(data, dict):
         if "self" in data:
             if "type" in data:
                 return Relationship.hydrate(data["self"], inst=inst, **data)
             else:
                 return Node.hydrate(data["self"], inst=inst, **data)
         elif "nodes" in data and "relationships" in data:
             if "directions" not in data:
                 directions = []
                 relationships = graph.evaluate(
                     "MATCH ()-[r]->() WHERE id(r) IN {x} RETURN collect(r)",
                     x=[int(uri.rpartition("/")[-1]) for uri in data["relationships"]])
                 node_uris = data["nodes"]
                 for i, relationship in enumerate(relationships):
                     if remote(relationship.start_node()).uri == node_uris[i]:
                         directions.append("->")
                     else:
                         directions.append("<-")
                 data["directions"] = directions
             return Path.hydrate(data)
         else:
             # from warnings import warn
             # warn("Map literals returned over the Neo4j REST interface are ambiguous "
             #      "and may be hydrated as graph objects")
             return data
     elif is_collection(data):
         return type(data)(map(hydrate_, data))
     else:
         return data
Пример #4
0
 def test_can_write_with_wrapper_function(self):
     alice, bob, carol, dave = Node(name="Alice"), Node(name="Bob"), \
                               Node(name="Carol"), Node(name="Dave")
     path = Path(alice, "LOVES", bob, Relationship(carol, "HATES", bob),
                 carol, "KNOWS", dave)
     written = cypher_repr(path)
     assert written == "(alice)-[:LOVES]->(bob)<-[:HATES]-(carol)-[:KNOWS]->(dave)"
Пример #5
0
 def test_can_write_relationship_with_name(self):
     r = Relationship(Node(name="Fred"), "LIVES WITH", Node(name="Wilma"))
     string = StringIO()
     writer = CypherWriter(string)
     writer.write_relationship(r, name="fred_wilma")
     written = string.getvalue()
     assert written == '(fred)-[fred_wilma:`LIVES WITH`]->(wilma)'
Пример #6
0
 def test_can_push_path(self):
     alice = Node(name="Alice")
     bob = Node(name="Bob")
     carol = Node(name="Carol")
     dave = Node(name="Dave")
     path = Path(alice, "LOVES", bob, Relationship(carol, "HATES", bob),
                 carol, "KNOWS", dave)
     self.graph.create(path)
     statement = ("MATCH ()-[ab]->() WHERE id(ab)={ab} "
                  "MATCH ()-[bc]->() WHERE id(bc)={bc} "
                  "MATCH ()-[cd]->() WHERE id(cd)={cd} "
                  "RETURN ab.amount, bc.amount, cd.since")
     parameters = {
         "ab": remote(path[0])._id,
         "bc": remote(path[1])._id,
         "cd": remote(path[2])._id
     }
     path[0]["amount"] = "lots"
     path[1]["amount"] = "some"
     path[2]["since"] = 1999
     ab_amount, bc_amount, cd_since = self.graph.run(statement,
                                                     parameters).next()
     assert ab_amount is None
     assert bc_amount is None
     assert cd_since is None
     self.graph.push(path)
     ab_amount, bc_amount, cd_since = self.graph.run(statement,
                                                     parameters).next()
     assert ab_amount == "lots"
     assert bc_amount == "some"
     assert cd_since == 1999
Пример #7
0
 def test_can_pull_path(self):
     alice = Node(name="Alice")
     bob = Node(name="Bob")
     carol = Node(name="Carol")
     dave = Node(name="Dave")
     path = Path(alice, "LOVES", bob, Relationship(carol, "HATES", bob),
                 carol, "KNOWS", dave)
     self.graph.create(path)
     assert path[0]["amount"] is None
     assert path[1]["amount"] is None
     assert path[2]["since"] is None
     statement = (
         "MATCH ()-[ab]->() WHERE id(ab)={ab} "
         "MATCH ()-[bc]->() WHERE id(bc)={bc} "
         "MATCH ()-[cd]->() WHERE id(cd)={cd} "
         "SET ab.amount = 'lots', bc.amount = 'some', cd.since = 1999")
     id_0 = remote(path[0])._id
     id_1 = remote(path[1])._id
     id_2 = remote(path[2])._id
     parameters = {"ab": id_0, "bc": id_1, "cd": id_2}
     self.graph.run(statement, parameters)
     self.graph.pull(path)
     assert path[0]["amount"] == "lots"
     assert path[1]["amount"] == "some"
     assert path[2]["since"] == 1999
Пример #8
0
 def test_can_delete_nodes_and_relationship_nodes_first(self):
     alice = Node("Person", name="Alice")
     bob = Node("Person", name="Bob")
     ab = Relationship(alice, "KNOWS", bob)
     self.graph.create(alice | bob | ab)
     assert self.graph.exists(alice | bob | ab)
     self.graph.delete(alice | bob | ab)
     assert not self.graph.exists(alice | bob | ab)
Пример #9
0
 def test_can_delete_path(self):
     alice, bob, carol, dave = Node(), Node(), Node(), Node()
     path = Path(alice, "LOVES", bob, Relationship(carol, "HATES", bob),
                 carol, "KNOWS", dave)
     self.graph.create(path)
     assert self.graph.exists(path)
     self.graph.delete(path)
     assert not self.graph.exists(path)
Пример #10
0
 def test_can_write_relationship_with_properties(self):
     r = Relationship(Node(name="Fred"), ("LIVES WITH", {
         "place": "Bedrock"
     }), Node(name="Wilma"))
     string = StringIO()
     writer = CypherWriter(string)
     writer.write(r)
     written = string.getvalue()
     assert written == '(fred)-[:`LIVES WITH` {place:"Bedrock"}]->(wilma)'
Пример #11
0
 def test_can_write_simple_path(self):
     alice, bob, carol, dave = Node(name="Alice"), Node(name="Bob"), \
                               Node(name="Carol"), Node(name="Dave")
     path = Path(alice, "LOVES", bob, Relationship(carol, "HATES", bob),
                 carol, "KNOWS", dave)
     string = StringIO()
     writer = CypherWriter(string)
     writer.write(path)
     written = string.getvalue()
     assert written == "(alice)-[:LOVES]->(bob)<-[:HATES]-(carol)-[:KNOWS]->(dave)"
Пример #12
0
 def test_can_write_simple_relationship(self):
     a = Node()
     b = Node()
     r = Relationship(a, "KNOWS", b)
     a.__name__ = "a"
     b.__name__ = "b"
     string = StringIO()
     writer = CypherWriter(string)
     writer.write(r)
     written = string.getvalue()
     assert written == "(a)-[:KNOWS]->(b)"
Пример #13
0
 def test_subgraph_repr(self):
     a = Node("Person", name="Alice")
     b = Node("Person", name="Bob")
     ab = Relationship(a, "TO", b)
     ba = Relationship(b, "FROM", a)
     s = ab | ba
     assert isinstance(s, Subgraph)
     r = repr(s)
     assert r.startswith("({")
     assert r.endswith("})")
     nodes, _, relationships = r[2:-2].partition("}, {")
     items = [item.strip() for item in nodes.split(",")]
     assert len(items) == 2
     for i, item in enumerate(items):
         assert re.match(
             r'\(_?[0-9A-Za-z]+:Person \{name:"(Alice|Bob)"\}\)', item)
     items = [item.strip() for item in relationships.split(",")]
     assert len(items) == 2
     for _ in items:
         assert re.match(r'\(.*\)-\[:(TO|FROM)\]->\(.*\)', repr(ab))
Пример #14
0
 def test_can_add_single_relationship(self):
     alice = Node(name="Alice Smith")
     bob = Node(name="Bob Smith")
     ab = Relationship(alice, "KNOWS", bob)
     self.graph.create(alice | bob | ab)
     self.batch.add_to_index(Relationship, self.friendships, "friends",
                             "alice_&_bob", ab)
     self.batch.run()
     # check entries
     rels = self.friendships.get("friends", "alice_&_bob")
     assert len(rels) == 1
     assert ab in rels
     # done
     self.recycling = [ab, alice, bob]
Пример #15
0
 def test_can_push_relationship(self):
     a = Node()
     b = Node()
     ab = Relationship(a, "KNOWS", b)
     self.graph.create(ab)
     value = self.graph.evaluate(
         "MATCH ()-[ab:KNOWS]->() WHERE id(ab)={i} "
         "RETURN ab.since",
         i=remote(ab)._id)
     assert value is None
     ab["since"] = 1999
     self.graph.push(ab)
     value = self.graph.evaluate(
         "MATCH ()-[ab:KNOWS]->() WHERE id(ab)={i} "
         "RETURN ab.since",
         i=remote(ab)._id)
     assert value == 1999
Пример #16
0
 def test_param_reused_twice_after_with_statement(self):
     a, b, ab = self.alice_and_bob
     c = Node(name="Carol", age=88)
     bc = Relationship(b, "KNOWS", c)
     self.graph.create(c | bc)
     query = ("MATCH (a) WHERE id(a)={A} "
              "MATCH (a)-[:KNOWS]->(b) "
              "WHERE a.age > {min_age} "
              "WITH a "
              "MATCH (a)-[:KNOWS]->(b) "
              "WHERE b.age > {min_age} "
              "WITH b "
              "MATCH (b)-[:KNOWS]->(c) "
              "WHERE c.age > {min_age} "
              "RETURN c")
     params = {"A": remote(a)._id, "min_age": 50}
     record = self.graph.run(query, params).next()
     assert record["c"] == c
Пример #17
0
class RelationshipLoopTestCase(TestCase):

    loop = Relationship(alice, "LIKES", alice)

    def test_nodes(self):
        nodes = self.loop.nodes()
        assert isinstance(nodes, tuple)
        assert nodes == (alice, alice)

    def test_relationships(self):
        relationships = self.loop.relationships()
        assert isinstance(relationships, tuple)
        assert relationships == (self.loop, )

    def test_order(self):
        assert order(self.loop) == 1

    def test_size(self):
        assert size(self.loop) == 1
Пример #18
0
 def test_relationship_property_pull_scenarios(self):
     property_sets = [{}, {
         "name": "Alice"
     }, {
         "name": "Alice",
         "age": 33
     }, {
         "name": "Bob"
     }]
     for old_props in property_sets:
         for new_props in property_sets:
             a = Node()
             b = Node()
             relationship = Relationship(a, "TO", b, **old_props)
             self.graph.create(relationship)
             relationship_id = remote(relationship)._id
             assert dict(relationship) == old_props
             self.graph.run("MATCH ()-[r]->() WHERE id(r)={x} SET r={y}",
                            x=relationship_id,
                            y=new_props)
             self.graph.pull(relationship)
             assert dict(relationship) == new_props, \
                 "Failed to pull new properties %r over old properties %r" % \
                 (new_props, old_props)
Пример #19
0
 def test_construction_from_no_arguments(self):
     with self.assertRaises(TypeError):
         _ = Relationship()
Пример #20
0
 def setUp(self):
     a = Node(name="Alice", age=66)
     b = Node(name="Bob", age=77)
     ab = Relationship(a, "KNOWS", b)
     self.graph.create(ab)
     self.alice_and_bob = (a, b, ab)
Пример #21
0
 def test_can_create_nodes_and_relationship(self):
     self.graph.delete_all()
     a = Node()
     b = Node()
     c = Node()
     ab = Relationship(a, "TO", b)
     bc = Relationship(b, "TO", c)
     ca = Relationship(c, "TO", a)
     self.graph.create(ab | bc | ca)
     assert remote(a)
     assert remote(b)
     assert remote(c)
     assert remote(ab)
     assert ab.start_node() == a
     assert ab.end_node() == b
     assert remote(bc)
     assert bc.start_node() == b
     assert bc.end_node() == c
     assert remote(ca)
     assert ca.start_node() == c
     assert ca.end_node() == a
     assert order(self.graph) == 3
     assert size(self.graph) == 3
Пример #22
0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from unittest import TestCase

from py2neo.types import PropertyDict, Subgraph, Walkable, Node, Relationship, Path, walk, order, size

alice = Node("Person", "Employee", name="Alice", age=33)
bob = Node("Person")
carol = Node("Person")
dave = Node("Person")

alice_knows_bob = Relationship(alice, "KNOWS", bob, since=1999)
alice_likes_carol = Relationship(alice, "LIKES", carol)
carol_dislikes_bob = Relationship(carol, "DISLIKES", bob)
carol_married_to_dave = Relationship(carol, "MARRIED_TO", dave)
dave_works_for_dave = Relationship(dave, "WORKS_FOR", dave)


class PropertyCoercionTestCase(TestCase):
    def test_boolean(self):
        props = PropertyDict({"value": True})
        assert props == {"value": True}

    def test_integer_in_range(self):
        props = PropertyDict({"value": 1})
        assert props == {"value": 1}
Пример #23
0
 def test_can_concatenate_node_and_reversed_relationship(self):
     bob_knows_alice = Relationship(bob, "KNOWS", alice)
     result = alice + bob_knows_alice
     assert result == Walkable([alice, bob_knows_alice, bob])
Пример #24
0
 def test_inequality(self):
     other_rel = Relationship(alice, "KNOWS", bob, since=1999)
     assert alice != other_rel
Пример #25
0
 def test_construction_from_more_arguments(self):
     with self.assertRaises(TypeError):
         Relationship(alice, "KNOWS", bob, carol)
Пример #26
0
 def test_construction_from_three_arguments(self):
     rel = Relationship(alice, "KNOWS", bob)
     assert rel.start_node() is alice
     assert rel.end_node() is bob
     assert rel.type() == "KNOWS"
Пример #27
0
 def test_construction_from_node_and_type_arguments(self):
     rel = Relationship(alice, "LIKES")
     assert rel.start_node() is alice
     assert rel.end_node() is alice
     assert rel.type() == "LIKES"
Пример #28
0
 def test_relationship_repr(self):
     a = Node("Person", name="Alice")
     b = Node("Person", name="Bob")
     ab = Relationship(a, "KNOWS", b, since=1999)
     assert repr(ab) == '(alice)-[:KNOWS {since:1999}]->(bob)'
Пример #29
0
 def test_construction_from_one_argument(self):
     rel = Relationship(alice)
     assert rel.start_node() is alice
     assert rel.end_node() is alice
     assert rel.type() == "TO"
Пример #30
0
 def hydrate_(obj, inst=None):
     # TODO: hydrate directly instead of via HTTP hydration
     if isinstance(obj, Structure):
         signature, args = obj
         if signature == b"N":
             uri = "%snode/%s" % (graph_uri, args[0])
             return Node.hydrate(uri,
                                 inst=inst,
                                 metadata={"labels": list(args[1])},
                                 data=hydrate_(args[2]))
         elif signature == b"R":
             uri = "%srelationship/%s" % (graph_uri, args[0])
             return Relationship.hydrate(
                 uri,
                 inst=inst,
                 start="%snode/%s" % (graph_uri, args[1]),
                 end="%snode/%s" % (graph_uri, args[2]),
                 type=args[3],
                 data=hydrate_(args[4]))
         elif signature == b"P":
             nodes = [hydrate_(node) for node in args[0]]
             u_rels = [
                 UnboundRelationship.hydrate(*map(hydrate_, r))
                 for _, r in args[1]
             ]
             sequence = args[2]
             last_node = nodes[0]
             steps = [last_node]
             for i, rel_index in enumerate(sequence[::2]):
                 next_node = nodes[sequence[2 * i + 1]]
                 last_node_uri = "%snode/%s" % (graph_uri,
                                                remote(last_node)._id)
                 next_node_uri = "%snode/%s" % (graph_uri,
                                                remote(next_node)._id)
                 if rel_index > 0:
                     u_rel = u_rels[rel_index - 1]
                     uri = "%srelationship/%s" % (graph_uri, u_rel.id)
                     rel = Relationship.hydrate(uri,
                                                start=last_node_uri,
                                                end=next_node_uri,
                                                type=u_rel.type,
                                                data=u_rel.properties)
                 else:
                     u_rel = u_rels[-rel_index - 1]
                     uri = "%srelationship/%s" % (graph_uri, u_rel.id)
                     rel = Relationship.hydrate(uri,
                                                start=next_node_uri,
                                                end=last_node_uri,
                                                type=u_rel.type,
                                                data=u_rel.properties)
                 steps.append(rel)
                 steps.append(next_node)
                 last_node = next_node
             return Path(*steps)
         else:
             # If we don't recognise the structure type, just return it as-is
             # TODO: add warning for unsupported structure types
             return obj
     elif isinstance(obj, list):
         return list(map(hydrate_, obj))
     elif isinstance(obj, dict):
         return {key: hydrate_(value) for key, value in obj.items()}
     else:
         return obj