Example #1
0
    def save(self, subj, node=None):
        """ Save an object to a database node.

        :param subj: the object to save
        :param node: the database node to save to (if omitted, will re-save to
            same node as previous save)
        """
        if node is not None:
            subj.__node__ = node
        # naively copy properties from object to node
        props = {}
        for key, value in subj.__dict__.items():
            if not key.startswith("_"):
                props[key] = value
        if hasattr(subj, "__node__"):
            subj.__node__.set_properties(props)
            query = CypherQuery(self.graph, "START a=node({A}) "
                                                     "MATCH (a)-[r]->(b) "
                                                     "DELETE r")
            query.execute(A=subj.__node__._id)
        else:
            subj.__node__, = self.graph.create(props)
        # write rels
        if hasattr(subj, "__rel__"):
            batch = WriteBatch(self.graph)
            for rel_type, rels in subj.__rel__.items():
                for rel_props, endpoint in rels:
                    end_node = self._get_node(endpoint)
                    if end_node not in self.graph:
                        raise ValueError(end_node)
                    batch.create((subj.__node__, rel_type, end_node, rel_props))
            batch.run()
        return subj
Example #2
0
 def setup(self, graph):
     try:
         graph.legacy.delete_index(Node, "People")
     except LookupError:
         pass
     self.people = graph.legacy.get_or_create_index(Node, "People")
     self.batch = LegacyWriteBatch(graph)
     self.graph = graph
Example #3
0
 def setup(self, graph):
     try:
         graph.legacy.delete_index(Relationship, "Friendships")
     except LookupError:
         pass
     self.friendships = graph.legacy.get_or_create_index(
         Relationship, "Friendships")
     self.batch = LegacyWriteBatch(graph)
     self.graph = graph
Example #4
0
 def setup(self, legacy_graph):
     try:
         legacy_graph.delete_index(Node, "People")
     except LookupError:
         pass
     self.people = legacy_graph.get_or_create_index(Node, "People")
     self.batch = LegacyWriteBatch(legacy_graph)
     self.graph = legacy_graph
Example #5
0
 def setup(self, legacy_graph):
     try:
         legacy_graph.delete_index(Relationship, "Friendships")
     except LookupError:
         pass
     self.friendships = legacy_graph.get_or_create_index(Relationship, "Friendships")
     self.batch = LegacyWriteBatch(legacy_graph)
     self.graph = legacy_graph
Example #6
0
 def setup(self, graph):
     self.graph = graph
     try:
         graph.legacy.delete_index(Node, "node_removal_test_index")
     except LookupError:
         pass
     self.index = graph.legacy.get_or_create_index(
         Node, "node_removal_test_index")
     self.fred, self.wilma, = graph.create(
         {"name": "Fred Flintstone"},
         {"name": "Wilma Flintstone"},
     )
     self.index.add("name", "Fred", self.fred)
     self.index.add("name", "Wilma", self.wilma)
     self.index.add("name", "Flintstone", self.fred)
     self.index.add("name", "Flintstone", self.wilma)
     self.index.add("flintstones", "%", self.fred)
     self.index.add("flintstones", "%", self.wilma)
     self.batch = LegacyWriteBatch(graph)
Example #7
0
 def setup(self, graph):
     self.graph = graph
     try:
         graph.legacy.delete_index(Node, "node_removal_test_index")
     except LookupError:
         pass
     self.index = graph.legacy.get_or_create_index(Node, "node_removal_test_index")
     self.fred, self.wilma, = graph.create({"name": "Fred Flintstone"}, {"name": "Wilma Flintstone"})
     self.index.add("name", "Fred", self.fred)
     self.index.add("name", "Wilma", self.wilma)
     self.index.add("name", "Flintstone", self.fred)
     self.index.add("name", "Flintstone", self.wilma)
     self.index.add("flintstones", "%", self.fred)
     self.index.add("flintstones", "%", self.wilma)
     self.batch = LegacyWriteBatch(graph)
Example #8
0
 def _execute_load_batch(self, graph, unique):
     # build batch request
     batch = LegacyWriteBatch(graph)
     # 1. indexed nodes
     index_entries = list(self.index_entries.values())
     for entry in index_entries:
         batch.get_or_create_in_index(Node, entry.index_name, entry.key, entry.value, entry.node.properties)
     # 2. related nodes
     if self._rels:
         query, params, related_names = self._get_relationship_query(unique)
         batch.append(CypherJob(query, params))
     else:
         related_names = []
     # 3. odd nodes
     odd_names = list(self._odd_nodes.keys())
     for name in odd_names:
         batch.create(self._nodes[name].properties)
     # submit batch unless empty (in which case bail out and return nothing)
     if batch:
         responses = batch.submit()
     else:
         return {}
     # parse response and build return value
     return_nodes = {}
     # 1. unique_nodes
     for i, entry in enumerate(index_entries):
         return_nodes[entry.node.name] = responses.pop(0)
     # 2. related nodes
     if self._rels:
         r = responses.pop(0)
         if r:
             for i, value in enumerate(r):
                 return_nodes[related_names[i]] = value
     # 3. odd nodes
     for i, name in enumerate(odd_names):
         return_nodes[name] = responses.pop(0)
     return return_nodes
Example #9
0
 def setup(self, legacy_graph):
     self.batch = LegacyWriteBatch(legacy_graph)
Example #10
0
class TestIndexedNodeRemoval(object):

    @pytest.fixture(autouse=True)
    def setup(self, legacy_graph):
        self.graph = legacy_graph
        try:
            legacy_graph.delete_index(Node, "node_removal_test_index")
        except LookupError:
            pass
        self.index = legacy_graph.get_or_create_index(Node, "node_removal_test_index")
        self.fred, self.wilma, = legacy_graph.create(
            {"name": "Fred Flintstone"}, {"name": "Wilma Flintstone"},
        )
        self.index.add("name", "Fred", self.fred)
        self.index.add("name", "Wilma", self.wilma)
        self.index.add("name", "Flintstone", self.fred)
        self.index.add("name", "Flintstone", self.wilma)
        self.index.add("flintstones", "%", self.fred)
        self.index.add("flintstones", "%", self.wilma)
        self.batch = LegacyWriteBatch(legacy_graph)

    def check(self, key, value, *entities):
        e = self.index.get(key, value)
        assert len(entities) == len(e)
        for entity in entities:
            assert entity in e

    def test_remove_key_value_entity(self):
        self.batch.remove_from_index(Node, self.index, key="name",
                                     value="Flintstone", entity=self.fred)
        self.batch.run()
        self.check("name", "Fred", self.fred)
        self.check("name", "Wilma", self.wilma)
        self.check("name", "Flintstone", self.wilma)
        self.check("flintstones", "%", self.fred, self.wilma)

    def test_remove_key_entity(self):
        self.batch.remove_from_index(Node, self.index, key="name", entity=self.fred)
        self.batch.run()
        self.check("name", "Fred")
        self.check("name", "Wilma", self.wilma)
        self.check("name", "Flintstone", self.wilma)
        self.check("flintstones", "%", self.fred, self.wilma)

    def test_remove_entity(self):
        self.batch.remove_from_index(Node, self.index, entity=self.fred)
        self.batch.run()
        self.check("name", "Fred")
        self.check("name", "Wilma", self.wilma)
        self.check("name", "Flintstone", self.wilma)
        self.check("flintstones", "%", self.wilma)
Example #11
0
class TestIndexedNodeCreation(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        try:
            graph.legacy.delete_index(Node, "People")
        except LookupError:
            pass
        self.people = graph.legacy.get_or_create_index(Node, "People")
        self.batch = LegacyWriteBatch(graph)
        self.graph = graph

    def test_can_create_single_indexed_node(self):
        properties = {"name": "Alice Smith"}
        # need to execute a pair of commands as "create in index" not available
        self.batch.create(properties)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", 0)
        alice, index_entry = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice.properties == properties
        self.graph.delete(alice)

    def test_can_create_two_similarly_indexed_nodes(self):
        # create Alice
        alice_props = {"name": "Alice Smith"}
        # need to execute a pair of commands as "create in index" not available
        self.batch.create(alice_props)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", 0)
        alice, alice_index_entry = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice.properties == alice_props
        self.batch.clear()
        # create Bob
        bob_props = {"name": "Bob Smith"}
        # need to execute a pair of commands as "create in index" not available
        self.batch.create(bob_props)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", 0)
        bob, bob_index_entry = self.batch.submit()
        assert isinstance(bob, Node)
        assert bob.properties == bob_props
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 2
        assert alice in smiths
        assert bob in smiths
        # done
        self.graph.delete(alice, bob)

    def test_can_get_or_create_uniquely_indexed_node(self):
        # create Alice
        alice_props = {"name": "Alice Smith"}
        self.batch.get_or_create_in_index(Node, self.people, "surname",
                                          "Smith", alice_props)
        alice, = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice.properties == alice_props
        self.batch.clear()
        # create Bob
        bob_props = {"name": "Bob Smith"}
        self.batch.get_or_create_in_index(Node, self.people, "surname",
                                          "Smith", bob_props)
        bob, = self.batch.submit()
        assert isinstance(bob, Node)
        assert bob.properties != bob_props
        assert bob.properties == alice_props
        assert bob == alice
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 1
        assert alice in smiths
        # done
        self.graph.delete(alice, bob)
Example #12
0
class TestRelationshipCreation(object):

    @pytest.fixture(autouse=True)
    def setup(self, legacy_graph):
        self.batch = LegacyWriteBatch(legacy_graph)

    def test_can_create_relationship_with_new_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1))
        alice, bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.get_properties() == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_new_indexed_nodes(self, legacy_graph):
        try:
            legacy_graph.delete_index(Node, "people")
        except LookupError:
            pass
        try:
            legacy_graph.delete_index(Relationship, "friendships")
        except LookupError:
            pass
        self.batch.get_or_create_in_index(Node, "people", "name", "Alice", {"name": "Alice"})
        self.batch.get_or_create_in_index(Node, "people", "name", "Bob", {"name": "Bob"})
        self.batch.get_or_create_in_index(Relationship, "friendships",
                                          "names", "alice_bob", (0, "KNOWS", 1))
        #self.batch.create((0, "KNOWS", 1))
        alice, bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.get_properties() == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_existing_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        alice, bob = self.batch.submit()
        self.batch.clear()
        self.batch.create((alice, "KNOWS", bob))
        knows, = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.get_properties() == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_existing_start_node(self):
        self.batch.create({"name": "Alice"})
        alice, = self.batch.submit()
        self.batch.clear()
        self.batch.create({"name": "Bob"})
        self.batch.create((alice, "KNOWS", 0))
        bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.get_properties() == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_existing_end_node(self):
        self.batch.create({"name": "Bob"})
        bob, = self.batch.submit()
        self.batch.clear()
        self.batch.create({"name": "Alice"})
        self.batch.create((0, "KNOWS", bob))
        alice, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.get_properties() == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_multiple_relationships(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create({"name": "Carol"})
        self.batch.create((0, "KNOWS", 1))
        self.batch.create((1, "KNOWS", 2))
        self.batch.create((2, "KNOWS", 0))
        alice, bob, carol, ab, bc, ca = self.batch.submit()
        for relationship in [ab, bc, ca]:
            assert isinstance(relationship, Relationship)
            assert relationship.type == "KNOWS"

    def test_can_create_overlapping_relationships(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1))
        self.batch.create((0, "KNOWS", 1))
        alice, bob, knows1, knows2 = self.batch.submit()
        assert isinstance(knows1, Relationship)
        assert knows1.start_node == alice
        assert knows1.type == "KNOWS"
        assert knows1.end_node == bob
        assert knows1.get_properties() == {}
        assert isinstance(knows2, Relationship)
        assert knows2.start_node == alice
        assert knows2.type == "KNOWS"
        assert knows2.end_node == bob
        assert knows2.get_properties() == {}
        self.recycling = [knows1, knows2, alice, bob]

    def test_can_create_relationship_with_properties(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1, {"since": 2000}))
        alice, bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows["since"] == 2000
        self.recycling = [knows, alice, bob]

    def test_create_function(self):
        self.batch.create(node(name="Alice"))
        self.batch.create(node(name="Bob"))
        self.batch.create(rel(0, "KNOWS", 1))
        alice, bob, ab = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice["name"] == "Alice"
        assert isinstance(bob, Node)
        assert bob["name"] == "Bob"
        assert isinstance(ab, Relationship)
        assert ab.start_node == alice
        assert ab.type == "KNOWS"
        assert ab.end_node == bob
        self.recycling = [ab, alice, bob]
Example #13
0
class TestIndexedNodeAddition(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        try:
            graph.legacy.delete_index(Node, "People")
        except LookupError:
            pass
        self.people = graph.legacy.get_or_create_index(Node, "People")
        self.batch = LegacyWriteBatch(graph)
        self.graph = graph

    def test_can_add_single_node(self):
        alice, = self.graph.create({"name": "Alice Smith"})
        self.batch.add_to_index(Node, self.people, "surname", "Smith", alice)
        self.batch.run()
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 1
        assert alice in smiths
        # done
        self.graph.delete(alice)

    def test_can_add_two_similar_nodes(self):
        alice, bob = self.graph.create({"name": "Alice Smith"},
                                       {"name": "Bob Smith"})
        self.batch.add_to_index(Node, self.people, "surname", "Smith", alice)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", bob)
        nodes = self.batch.submit()
        assert nodes[0] != nodes[1]
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 2
        assert alice in smiths
        assert bob in smiths
        # done
        self.graph.delete(alice, bob)

    def test_can_add_nodes_only_if_none_exist(self):
        alice, bob = self.graph.create({"name": "Alice Smith"},
                                       {"name": "Bob Smith"})
        self.batch.get_or_add_to_index(Node, self.people, "surname", "Smith",
                                       alice)
        self.batch.get_or_add_to_index(Node, self.people, "surname", "Smith",
                                       bob)
        nodes = self.batch.submit()
        assert nodes[0] == nodes[1]
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 1
        assert alice in smiths
        # done
        self.graph.delete(alice, bob)
Example #14
0
class TestIndexedRelationshipAddition(object):

    @pytest.fixture(autouse=True)
    def setup(self, legacy_graph):
        try:
            legacy_graph.delete_index(Relationship, "Friendships")
        except LookupError:
            pass
        self.friendships = legacy_graph.get_or_create_index(Relationship, "Friendships")
        self.batch = LegacyWriteBatch(legacy_graph)
        self.graph = legacy_graph

    def test_can_add_single_relationship(self, legacy_graph):
        alice, bob, ab = self.graph.create({"name": "Alice"}, {"name": "Bob"}, (0, "KNOWS", 1))
        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]

    def test_can_add_two_similar_relationships(self, legacy_graph):
        alice, bob, ab1, ab2 = self.graph.create(
            {"name": "Alice"}, {"name": "Bob"},
            (0, "KNOWS", 1), (0, "KNOWS", 1))
        self.batch.add_to_index(Relationship, self.friendships, "friends", "alice_&_bob", ab1)
        self.batch.add_to_index(Relationship, self.friendships, "friends", "alice_&_bob", ab2)
        self.batch.run()
        # check entries
        entries = self.friendships.get("friends", "alice_&_bob")
        assert len(entries) == 2
        assert ab1 in entries
        assert ab2 in entries
        # done
        self.recycling = [ab1, ab2, alice, bob]

    def test_can_add_relationships_only_if_none_exist(self):
        alice, bob, ab1, ab2 = self.graph.create(
            {"name": "Alice"}, {"name": "Bob"},
            (0, "KNOWS", 1), (0, "KNOWS", 1))
        self.batch.get_or_add_to_index(Relationship, self.friendships,
                                       "friends", "alice_&_bob", ab1)
        self.batch.get_or_add_to_index(Relationship, self.friendships,
                                       "friends", "alice_&_bob", ab2)
        results = self.batch.submit()
        assert results[0] == results[1]
        # check entries
        entries = self.friendships.get("friends", "alice_&_bob")
        assert len(entries) == 1
        assert ab1 in entries
        # done
        self.recycling = [ab1, ab2, alice, bob]
Example #15
0
class TestIndexedNodeCreation(object):

    @pytest.fixture(autouse=True)
    def setup(self, legacy_graph):
        try:
            legacy_graph.delete_index(Node, "People")
        except LookupError:
            pass
        self.people = legacy_graph.get_or_create_index(Node, "People")
        self.batch = LegacyWriteBatch(legacy_graph)
        self.graph = legacy_graph

    def test_can_create_single_indexed_node(self):
        properties = {"name": "Alice Smith"}
        # need to execute a pair of commands as "create in index" not available
        self.batch.create(properties)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", 0)
        alice, index_entry = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice.get_properties() == properties
        self.graph.delete(alice)

    def test_can_create_two_similarly_indexed_nodes(self):
        # create Alice
        alice_props = {"name": "Alice Smith"}
        # need to execute a pair of commands as "create in index" not available
        self.batch.create(alice_props)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", 0)
        alice, alice_index_entry = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice.get_properties() == alice_props
        self.batch.clear()
        # create Bob
        bob_props = {"name": "Bob Smith"}
        # need to execute a pair of commands as "create in index" not available
        self.batch.create(bob_props)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", 0)
        bob, bob_index_entry = self.batch.submit()
        assert isinstance(bob, Node)
        assert bob.get_properties() == bob_props
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 2
        assert alice in smiths
        assert bob in smiths
        # done
        self.graph.delete(alice, bob)

    def test_can_get_or_create_uniquely_indexed_node(self):
        # create Alice
        alice_props = {"name": "Alice Smith"}
        self.batch.get_or_create_in_index(Node, self.people, "surname", "Smith", alice_props)
        alice, = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice.get_properties() == alice_props
        self.batch.clear()
        # create Bob
        bob_props = {"name": "Bob Smith"}
        self.batch.get_or_create_in_index(Node, self.people, "surname", "Smith", bob_props)
        bob, = self.batch.submit()
        assert isinstance(bob, Node)
        assert bob.get_properties() != bob_props
        assert bob.get_properties() == alice_props
        assert bob == alice
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 1
        assert alice in smiths
        # done
        self.graph.delete(alice, bob)
Example #16
0
class TestIndexedNodeAddition(object):

    @pytest.fixture(autouse=True)
    def setup(self, legacy_graph):
        try:
            legacy_graph.delete_index(Node, "People")
        except LookupError:
            pass
        self.people = legacy_graph.get_or_create_index(Node, "People")
        self.batch = LegacyWriteBatch(legacy_graph)
        self.graph = legacy_graph

    def test_can_add_single_node(self):
        alice, = self.graph.create({"name": "Alice Smith"})
        self.batch.add_to_index(Node, self.people, "surname", "Smith", alice)
        self.batch.run()
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 1
        assert alice in smiths
        # done
        self.graph.delete(alice)

    def test_can_add_two_similar_nodes(self):
        alice, bob = self.graph.create(
            {"name": "Alice Smith"}, {"name": "Bob Smith"})
        self.batch.add_to_index(Node, self.people, "surname", "Smith", alice)
        self.batch.add_to_index(Node, self.people, "surname", "Smith", bob)
        nodes = self.batch.submit()
        assert nodes[0] != nodes[1]
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 2
        assert alice in smiths
        assert bob in smiths
        # done
        self.graph.delete(alice, bob)

    def test_can_add_nodes_only_if_none_exist(self):
        alice, bob = self.graph.create(
            {"name": "Alice Smith"}, {"name": "Bob Smith"})
        self.batch.get_or_add_to_index(Node, self.people, "surname", "Smith", alice)
        self.batch.get_or_add_to_index(Node, self.people, "surname", "Smith", bob)
        nodes = self.batch.submit()
        assert nodes[0] == nodes[1]
        # check entries
        smiths = self.people.get("surname", "Smith")
        assert len(smiths) == 1
        assert alice in smiths
        # done
        self.graph.delete(alice, bob)
Example #17
0
class TestIndexedRelationshipAddition(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        try:
            graph.legacy.delete_index(Relationship, "Friendships")
        except LookupError:
            pass
        self.friendships = graph.legacy.get_or_create_index(
            Relationship, "Friendships")
        self.batch = LegacyWriteBatch(graph)
        self.graph = graph

    def test_can_add_single_relationship(self, graph):
        alice, bob, ab = self.graph.create({"name": "Alice"}, {"name": "Bob"},
                                           (0, "KNOWS", 1))
        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]

    def test_can_add_two_similar_relationships(self, graph):
        alice, bob, ab1, ab2 = self.graph.create({"name": "Alice"},
                                                 {"name": "Bob"},
                                                 (0, "KNOWS", 1),
                                                 (0, "KNOWS", 1))
        self.batch.add_to_index(Relationship, self.friendships, "friends",
                                "alice_&_bob", ab1)
        self.batch.add_to_index(Relationship, self.friendships, "friends",
                                "alice_&_bob", ab2)
        self.batch.run()
        # check entries
        entries = self.friendships.get("friends", "alice_&_bob")
        assert len(entries) == 2
        assert ab1 in entries
        assert ab2 in entries
        # done
        self.recycling = [ab1, ab2, alice, bob]

    def test_can_add_relationships_only_if_none_exist(self):
        alice, bob, ab1, ab2 = self.graph.create({"name": "Alice"},
                                                 {"name": "Bob"},
                                                 (0, "KNOWS", 1),
                                                 (0, "KNOWS", 1))
        self.batch.get_or_add_to_index(Relationship, self.friendships,
                                       "friends", "alice_&_bob", ab1)
        self.batch.get_or_add_to_index(Relationship, self.friendships,
                                       "friends", "alice_&_bob", ab2)
        results = self.batch.submit()
        assert results[0] == results[1]
        # check entries
        entries = self.friendships.get("friends", "alice_&_bob")
        assert len(entries) == 1
        assert ab1 in entries
        # done
        self.recycling = [ab1, ab2, alice, bob]
Example #18
0
 def setup(self, graph):
     self.batch = LegacyWriteBatch(graph)
Example #19
0
class TestIndexedNodeRemoval(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.graph = graph
        try:
            graph.legacy.delete_index(Node, "node_removal_test_index")
        except LookupError:
            pass
        self.index = graph.legacy.get_or_create_index(
            Node, "node_removal_test_index")
        self.fred, self.wilma, = graph.create(
            {"name": "Fred Flintstone"},
            {"name": "Wilma Flintstone"},
        )
        self.index.add("name", "Fred", self.fred)
        self.index.add("name", "Wilma", self.wilma)
        self.index.add("name", "Flintstone", self.fred)
        self.index.add("name", "Flintstone", self.wilma)
        self.index.add("flintstones", "%", self.fred)
        self.index.add("flintstones", "%", self.wilma)
        self.batch = LegacyWriteBatch(graph)

    def check(self, key, value, *entities):
        e = self.index.get(key, value)
        assert len(entities) == len(e)
        for entity in entities:
            assert entity in e

    def test_remove_key_value_entity(self):
        self.batch.remove_from_index(Node,
                                     self.index,
                                     key="name",
                                     value="Flintstone",
                                     entity=self.fred)
        self.batch.run()
        self.check("name", "Fred", self.fred)
        self.check("name", "Wilma", self.wilma)
        self.check("name", "Flintstone", self.wilma)
        self.check("flintstones", "%", self.fred, self.wilma)

    def test_remove_key_entity(self):
        self.batch.remove_from_index(Node,
                                     self.index,
                                     key="name",
                                     entity=self.fred)
        self.batch.run()
        self.check("name", "Fred")
        self.check("name", "Wilma", self.wilma)
        self.check("name", "Flintstone", self.wilma)
        self.check("flintstones", "%", self.fred, self.wilma)

    def test_remove_entity(self):
        self.batch.remove_from_index(Node, self.index, entity=self.fred)
        self.batch.run()
        self.check("name", "Fred")
        self.check("name", "Wilma", self.wilma)
        self.check("name", "Flintstone", self.wilma)
        self.check("flintstones", "%", self.wilma)
Example #20
0
 def setup(self, graph):
     self.batch = LegacyWriteBatch(graph)
Example #21
0
class TestRelationshipCreation(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = LegacyWriteBatch(graph)

    def test_can_create_relationship_with_new_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1))
        alice, bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.properties == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_new_indexed_nodes(self, graph):
        try:
            graph.legacy.delete_index(Node, "people")
        except LookupError:
            pass
        try:
            graph.legacy.delete_index(Relationship, "friendships")
        except LookupError:
            pass
        self.batch.get_or_create_in_index(Node, "people", "name", "Alice",
                                          {"name": "Alice"})
        self.batch.get_or_create_in_index(Node, "people", "name", "Bob",
                                          {"name": "Bob"})
        self.batch.get_or_create_in_index(Relationship, "friendships", "names",
                                          "alice_bob", (0, "KNOWS", 1))
        #self.batch.create((0, "KNOWS", 1))
        alice, bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.properties == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_existing_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        alice, bob = self.batch.submit()
        self.batch.clear()
        self.batch.create((alice, "KNOWS", bob))
        knows, = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.properties == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_existing_start_node(self):
        self.batch.create({"name": "Alice"})
        alice, = self.batch.submit()
        self.batch.clear()
        self.batch.create({"name": "Bob"})
        self.batch.create((alice, "KNOWS", 0))
        bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.properties == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_with_existing_end_node(self):
        self.batch.create({"name": "Bob"})
        bob, = self.batch.submit()
        self.batch.clear()
        self.batch.create({"name": "Alice"})
        self.batch.create((0, "KNOWS", bob))
        alice, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows.properties == {}
        self.recycling = [knows, alice, bob]

    def test_can_create_multiple_relationships(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create({"name": "Carol"})
        self.batch.create((0, "KNOWS", 1))
        self.batch.create((1, "KNOWS", 2))
        self.batch.create((2, "KNOWS", 0))
        alice, bob, carol, ab, bc, ca = self.batch.submit()
        for relationship in [ab, bc, ca]:
            assert isinstance(relationship, Relationship)
            assert relationship.type == "KNOWS"

    def test_can_create_overlapping_relationships(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1))
        self.batch.create((0, "KNOWS", 1))
        alice, bob, knows1, knows2 = self.batch.submit()
        assert isinstance(knows1, Relationship)
        assert knows1.start_node == alice
        assert knows1.type == "KNOWS"
        assert knows1.end_node == bob
        assert knows1.properties == {}
        assert isinstance(knows2, Relationship)
        assert knows2.start_node == alice
        assert knows2.type == "KNOWS"
        assert knows2.end_node == bob
        assert knows2.properties == {}
        self.recycling = [knows1, knows2, alice, bob]

    def test_can_create_relationship_with_properties(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1, {"since": 2000}))
        alice, bob, knows = self.batch.submit()
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        assert knows["since"] == 2000
        self.recycling = [knows, alice, bob]

    def test_create_function(self):
        self.batch.create(node(name="Alice"))
        self.batch.create(node(name="Bob"))
        self.batch.create(rel(0, "KNOWS", 1))
        alice, bob, ab = self.batch.submit()
        assert isinstance(alice, Node)
        assert alice["name"] == "Alice"
        assert isinstance(bob, Node)
        assert bob["name"] == "Bob"
        assert isinstance(ab, Relationship)
        assert ab.start_node == alice
        assert ab.type == "KNOWS"
        assert ab.end_node == bob
        self.recycling = [ab, alice, bob]