Beispiel #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)
            self.graph.cypher.run("START a=node({a}) MATCH (a)-[r]->(b) DELETE r",
                                  {"a": subj.__node__})
        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
Beispiel #2
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)
            self.graph.cypher.run(
                "START a=node({a}) MATCH (a)-[r]->(b) DELETE r",
                {"a": subj.__node__})
        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
Beispiel #3
0
class TestNodeCreation(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)
        self.graph = graph

    def test_can_create_single_empty_node(self):
        self.batch.create(node())
        a, = self.batch.submit()
        assert isinstance(a, Node)
        assert a.properties == {}

    def test_can_create_single_node_with_streaming(self):
        self.batch.create(Node(name="Alice"))
        for result in self.batch.stream():
            assert isinstance(result, Node)
            assert result.properties == {"name": "Alice"}

    def test_can_create_multiple_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create(node({"name": "Bob"}))
        self.batch.create(node(name="Carol"))
        alice, bob, carol = self.batch.submit()
        assert isinstance(alice, Node)
        assert isinstance(bob, Node)
        assert isinstance(carol, Node)
        assert alice["name"] == "Alice"
        assert bob["name"] == "Bob"
        assert carol["name"] == "Carol"
Beispiel #4
0
def test_can_handle_json_response_with_no_content(graph):
    # This example might fail if the server bug is fixed that returns
    # a 200 response with application/json content-type and no content.
    batch = WriteBatch(graph)
    batch.create((0, "KNOWS", 1))
    results = batch.submit()
    assert results == []
Beispiel #5
0
def test_can_handle_json_response_with_no_content(graph):
    # This example might fail if the server bug is fixed that returns
    # a 200 response with application/json content-type and no content.
    batch = WriteBatch(graph)
    batch.create((0, "KNOWS", 1))
    results = batch.submit()
    assert results == []
Beispiel #6
0
class TestNodeCreation(object):

    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)
        self.graph = graph

    def test_can_create_single_empty_node(self):
        self.batch.create(node())
        a, = self.batch.submit()
        assert isinstance(a, Node)
        assert a.properties == {}

    def test_can_create_single_node_with_streaming(self):
        self.batch.create(Node(name="Alice"))
        for result in self.batch.stream():
            assert isinstance(result, Node)
            assert result.properties == {"name": "Alice"}

    def test_can_create_multiple_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create(node({"name": "Bob"}))
        self.batch.create(node(name="Carol"))
        alice, bob, carol = self.batch.submit()
        assert isinstance(alice, Node)
        assert isinstance(bob, Node)
        assert isinstance(carol, Node)
        assert alice["name"] == "Alice"
        assert bob["name"] == "Bob"
        assert carol["name"] == "Carol"
Beispiel #7
0
def test_can_use_return_values_as_references(graph):
    batch = WriteBatch(graph)
    a = batch.create(node(name="Alice"))
    b = batch.create(node(name="Bob"))
    batch.create(rel(a, "KNOWS", b))
    results = batch.submit()
    ab = results[2]
    assert isinstance(ab, Relationship)
    assert ab.start_node["name"] == "Alice"
    assert ab.end_node["name"] == "Bob"
Beispiel #8
0
def test_can_use_return_values_as_references(graph):
    batch = WriteBatch(graph)
    a = batch.create(node(name="Alice"))
    b = batch.create(node(name="Bob"))
    batch.create(rel(a, "KNOWS", b))
    results = batch.submit()
    ab = results[2]
    assert isinstance(ab, Relationship)
    assert ab.start_node["name"] == "Alice"
    assert ab.end_node["name"] == "Bob"
Beispiel #9
0
class TestDeletion(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)
        self.graph = graph

    def test_can_delete_relationship_and_related_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1))
        alice, bob, ab = self.batch.submit()
        assert alice.exists
        assert bob.exists
        assert ab.exists
        self.batch.clear()
        self.batch.delete(ab)
        self.batch.delete(alice)
        self.batch.delete(bob)
        self.batch.run()
        assert not alice.exists
        assert not bob.exists
        assert not ab.exists
Beispiel #10
0
class TestDeletion(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)
        self.graph = graph

    def test_can_delete_relationship_and_related_nodes(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        self.batch.create((0, "KNOWS", 1))
        alice, bob, ab = self.batch.submit()
        assert alice.exists
        assert bob.exists
        assert ab.exists
        self.batch.clear()
        self.batch.delete(ab)
        self.batch.delete(alice)
        self.batch.delete(bob)
        self.batch.run()
        assert not alice.exists
        assert not bob.exists
        assert not ab.exists
Beispiel #11
0
class TestUniqueRelationshipCreation(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)

    def test_can_create_relationship_if_none_exists(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        alice, bob = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(
            alice, ("KNOWS", {"since": 2000}), bob)
        path, = self.batch.submit()
        knows = path.relationships[0]
        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_will_get_relationship_if_one_exists(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        alice, bob = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(
            alice, ("KNOWS", {"since": 2000}), bob)
        self.batch.get_or_create_path(
            alice, ("KNOWS", {"since": 2000}), bob)
        path1, path2 = self.batch.submit()
        assert path1 == path2

    def test_will_fail_batch_if_more_than_one_exists(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, k1, k2 = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(alice, "KNOWS", bob)
        try:
            self.batch.submit()
        except BatchError as error:
            cause = error.__cause__
            assert isinstance(cause, GraphError)
            assert cause.__class__.__name__ == "UniquePathNotUniqueException"
        else:
            assert False

    def test_can_create_relationship_and_start_node(self):
        self.batch.create({"name": "Bob"})
        bob, = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(None, "KNOWS", bob)
        path, = self.batch.submit()
        knows = path.relationships[0]
        alice = knows.start_node
        assert isinstance(knows, Relationship)
        assert isinstance(alice, Node)
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_and_end_node(self):
        self.batch.create({"name": "Alice"})
        alice, = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(alice, "KNOWS", None)
        path, = self.batch.submit()
        knows = path.relationships[0]
        bob = knows.end_node
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert isinstance(bob, Node)
        self.recycling = [knows, alice, bob]
Beispiel #12
0
class TestUniqueRelationshipCreation(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)

    def test_can_create_relationship_if_none_exists(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        alice, bob = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(alice, ("KNOWS", {"since": 2000}), bob)
        path, = self.batch.submit()
        knows = path.relationships[0]
        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_will_get_relationship_if_one_exists(self):
        self.batch.create({"name": "Alice"})
        self.batch.create({"name": "Bob"})
        alice, bob = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(alice, ("KNOWS", {"since": 2000}), bob)
        self.batch.get_or_create_path(alice, ("KNOWS", {"since": 2000}), bob)
        path1, path2 = self.batch.submit()
        assert path1 == path2

    def test_will_fail_batch_if_more_than_one_exists(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, k1, k2 = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(alice, "KNOWS", bob)
        try:
            self.batch.submit()
        except BatchError as error:
            cause = error.__cause__
            assert cause.__class__.__name__ == "UniquePathNotUniqueException"
        else:
            assert False

    def test_can_create_relationship_and_start_node(self):
        self.batch.create({"name": "Bob"})
        bob, = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(None, "KNOWS", bob)
        path, = self.batch.submit()
        knows = path.relationships[0]
        alice = knows.start_node
        assert isinstance(knows, Relationship)
        assert isinstance(alice, Node)
        assert knows.type == "KNOWS"
        assert knows.end_node == bob
        self.recycling = [knows, alice, bob]

    def test_can_create_relationship_and_end_node(self):
        self.batch.create({"name": "Alice"})
        alice, = self.batch.submit()
        self.batch.clear()
        self.batch.get_or_create_path(alice, "KNOWS", None)
        path, = self.batch.submit()
        knows = path.relationships[0]
        bob = knows.end_node
        assert isinstance(knows, Relationship)
        assert knows.start_node == alice
        assert knows.type == "KNOWS"
        assert isinstance(bob, Node)
        self.recycling = [knows, alice, bob]