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)
            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
Example #2
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 == []
Example #3
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 == []
Example #4
0
def _node_remove_labels(self, *labels):
    from py2neo.batch import WriteBatch
    labels = [ustr(label) for label in set(flatten(labels))]
    batch = WriteBatch(self.graph)
    for label in labels:
        batch.remove_label(self, label)
    batch.run()
Example #5
0
def _node_remove_labels(self, *labels):
    """ Remove one or more labels from this node.

    :param labels: one or more text labels
    """
    from py2neo.batch import WriteBatch
    labels = [ustr(label) for label in set(flatten(labels))]
    batch = WriteBatch(self.graph)
    for label in labels:
        batch.remove_label(self, label)
    batch.run()
Example #6
0
def test_cypher_job_with_bad_syntax(graph):
    batch = WriteBatch(graph)
    batch.append(CypherJob("X"))
    try:
        batch.submit()
    except BatchError as error:
        assert error.batch is batch
        assert error.job_id == 0
        assert error.status_code == 400
        assert error.uri == "cypher"
    else:
        assert False
Example #7
0
def test_cypher_job_with_non_existent_node_id(graph):
    node = Node()
    graph.create(node)
    node_id = node._id
    graph.delete(node)
    batch = WriteBatch(graph)
    batch.append(CypherJob("START n=node({N}) RETURN n", {"N": node_id}))
    try:
        batch.submit()
    except BatchError as error:
        assert error.batch is batch
        assert error.job_id == 0
        assert error.status_code == 400
        assert error.uri == "cypher"
    else:
        assert False
Example #8
0
 def setup(self, graph):
     self.batch = WriteBatch(graph)
     self.alice, self.bob, self.friends = graph.create(
         {
             "name": "Alice",
             "surname": "Allison"
         },
         {
             "name": "Bob",
             "surname": "Robertson"
         },
         (0, "KNOWS", 1, {
             "since": 2000
         }),
     )
     self.graph = graph
Example #9
0
 def setup(self, graph):
     self.batch = WriteBatch(graph)
     self.alice, self.bob, self.friends = graph.create(
         {"name": "Alice", "surname": "Allison"},
         {"name": "Bob", "surname": "Robertson"},
         (0, "KNOWS", 1, {"since": 2000}),
     )
     self.graph = graph
Example #10
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"
Example #11
0
def _node_remove_labels(self, *labels):
    from py2neo.batch import WriteBatch
    labels = [ustr(label) for label in set(flatten(labels))]
    batch = WriteBatch(self.graph)
    for label in labels:
        batch.remove_label(self, label)
    batch.run()
Example #12
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
Example #13
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_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"
Example #14
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"
Example #15
0
def test_cypher_job_with_bad_syntax(graph):
    batch = WriteBatch(graph)
    batch.append(CypherJob("X"))
    try:
        batch.submit()
    except BatchError as error:
        assert error.batch is batch
        assert error.job_id == 0
        assert error.status_code == 400
        assert error.uri == "cypher"
    else:
        assert False
Example #16
0
def test_cypher_job_with_non_existent_node_id(graph):
    node = Node()
    graph.create(node)
    node_id = node._id
    graph.delete(node)
    batch = WriteBatch(graph)
    batch.append(CypherJob("START n=node({N}) RETURN n", {"N": node_id}))
    try:
        batch.submit()
    except BatchError as error:
        assert error.batch is batch
        assert error.job_id == 0
        assert error.status_code == 400
        assert error.uri == "cypher"
    else:
        assert False
Example #17
0
class TestPropertyManagement(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)
        self.alice, self.bob, self.friends = graph.create(
            {"name": "Alice", "surname": "Allison"},
            {"name": "Bob", "surname": "Robertson"},
            (0, "KNOWS", 1, {"since": 2000}),
        )
        self.graph = graph

    def _check_properties(self, entity, expected_properties):
        actual_properties = entity.get_properties()
        assert len(actual_properties) == len(expected_properties)
        for key, value in expected_properties.items():
            assert key in actual_properties
            assert str(actual_properties[key]) == str(value)

    def test_can_add_new_node_property(self):
        self.batch.set_property(self.alice, "age", 33)
        self.batch.run()
        self._check_properties(
            self.alice, {"name": "Alice", "surname": "Allison", "age": 33})

    def test_can_overwrite_existing_node_property(self):
        self.batch.set_property(self.alice, "name", "Alison")
        self.batch.run()
        self._check_properties(
            self.alice, {"name": "Alison", "surname": "Allison"})

    def test_can_replace_all_node_properties(self):
        props = {"full_name": "Alice Allison", "age": 33}
        self.batch.set_properties(self.alice, props)
        self.batch.run()
        self._check_properties(self.alice, props)

    def test_can_add_delete_node_property(self):
        self.batch.delete_property(self.alice, "surname")
        self.batch.run()
        self._check_properties(self.alice, {"name": "Alice"})

    def test_can_add_delete_all_node_properties(self):
        self.batch.delete_properties(self.alice)
        self.batch.run()
        self._check_properties(self.alice, {})

    def test_can_add_new_relationship_property(self):
        self.batch.set_property(self.friends, "foo", "bar")
        self.batch.run()
        self._check_properties(self.friends, {"since": 2000, "foo": "bar"})
Example #18
0
 def setup(self, graph):
     self.batch = WriteBatch(graph)
     self.graph = graph
Example #19
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
Example #20
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]
Example #21
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]
Example #22
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"
Example #23
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
Example #24
0
 def setup(self, graph):
     self.batch = WriteBatch(graph)
     self.graph = graph
Example #25
0
class TestPropertyManagement(object):
    @pytest.fixture(autouse=True)
    def setup(self, graph):
        self.batch = WriteBatch(graph)
        self.alice, self.bob, self.friends = graph.create(
            {
                "name": "Alice",
                "surname": "Allison"
            },
            {
                "name": "Bob",
                "surname": "Robertson"
            },
            (0, "KNOWS", 1, {
                "since": 2000
            }),
        )
        self.graph = graph

    def _check_properties(self, entity, expected_properties):
        entity.pull()
        actual_properties = entity.properties
        assert len(actual_properties) == len(expected_properties)
        for key, value in expected_properties.items():
            assert key in actual_properties
            assert str(actual_properties[key]) == str(value)

    def test_can_add_new_node_property(self):
        self.batch.set_property(self.alice, "age", 33)
        self.batch.run()
        self._check_properties(self.alice, {
            "name": "Alice",
            "surname": "Allison",
            "age": 33
        })

    def test_can_overwrite_existing_node_property(self):
        self.batch.set_property(self.alice, "name", "Alison")
        self.batch.run()
        self._check_properties(self.alice, {
            "name": "Alison",
            "surname": "Allison"
        })

    def test_can_replace_all_node_properties(self):
        props = {"full_name": "Alice Allison", "age": 33}
        self.batch.set_properties(self.alice, props)
        self.batch.run()
        self._check_properties(self.alice, props)

    def test_can_add_delete_node_property(self):
        self.batch.delete_property(self.alice, "surname")
        self.batch.run()
        self._check_properties(self.alice, {"name": "Alice"})

    def test_can_add_delete_all_node_properties(self):
        self.batch.delete_properties(self.alice)
        self.batch.run()
        self._check_properties(self.alice, {})

    def test_can_add_new_relationship_property(self):
        self.batch.set_property(self.friends, "foo", "bar")
        self.batch.run()
        self._check_properties(self.friends, {"since": 2000, "foo": "bar"})