From b8d0b4337672d9ba4c73aa40201bd5707b539359 Mon Sep 17 00:00:00 2001 From: Nigel Small Date: Tue, 1 Jun 2021 10:26:54 +0100 Subject: [PATCH] Fixes #903 by reintroducing entity-level label/key overrides --- py2neo/data/__init__.py | 23 ++++++++-- test/integration/test_merge.py | 78 ++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/py2neo/data/__init__.py b/py2neo/data/__init__.py index a5131f72..ae82c987 100644 --- a/py2neo/data/__init__.py +++ b/py2neo/data/__init__.py @@ -279,12 +279,21 @@ def __db_merge__(self, tx, primary_label=None, primary_key=None): node_dict = {} for node in self.nodes: if not self._is_bound(node, graph): - if node.__model__ is None: - p_label = primary_label - p_key = primary_key - else: + # Determine primary label + if node.__primarylabel__ is not None: + p_label = node.__primarylabel__ + elif node.__model__ is not None: p_label = node.__model__.__primarylabel__ or primary_label + else: + p_label = primary_label + # Determine primary key + if node.__primarykey__ is not None: + p_key = node.__primarykey__ + elif node.__model__ is not None: p_key = node.__model__.__primarykey__ or primary_key + else: + p_key = primary_key + # Add node to the node dictionary key = (p_label, p_key, frozenset(node.labels)) node_dict.setdefault(key, []).append(node) @@ -611,6 +620,12 @@ class Node(Entity): #: OGM model class __model__ = None + #: Entity-level override for merge label + __primarylabel__ = None + + #: Entity-level override for merge key + __primarykey__ = None + @classmethod def ref(cls, graph, identity): obj = cls() diff --git a/test/integration/test_merge.py b/test/integration/test_merge.py index 8e979927..3fa31594 100644 --- a/test/integration/test_merge.py +++ b/test/integration/test_merge.py @@ -347,3 +347,81 @@ class ModelB(Model): graph.merge(node, label_a, "a") assert node.identity != a_id assert node.identity == b_id + + +def test_can_merge_node_with_merge_arguments(graph): + graph.delete_all() + a = Node("Person", name="Alice") + graph.merge(a, "Person", "name") + assert graph.nodes.match("Person", name="Alice").first() == a + + +def test_can_merge_node_with_primary_label_and_key(graph): + graph.delete_all() + a = Node("Person", name="Alice") + a.__primarylabel__ = "Person" + a.__primarykey__ = "name" + graph.merge(a) + assert graph.nodes.match("Person", name="Alice").first() == a + + +def test_can_merge_node_with_model(graph): + from py2neo.ogm import Model + + class Person(Model): + __primarylabel__ = "Person" + __primarykey__ = "name" + + graph.delete_all() + + a = Node("Person", name="Alice") + a.__model__ = Person + graph.merge(a) + assert graph.nodes.match("Person", name="Alice").first() == a + + +def test_can_merge_node_with_model_overriding_arguments(graph): + from py2neo.ogm import Model + + class Person(Model): + __primarylabel__ = "Person" + __primarykey__ = "name" + + graph.delete_all() + + a = Node("Person", name="Alice") + a.__model__ = Person + graph.merge(a, "Human", "nom") + assert graph.nodes.match("Person", name="Alice").first() == a + + +def test_can_merge_node_with_primary_label_overriding_model(graph): + from py2neo.ogm import Model + + class Person(Model): + __primarylabel__ = "Human" + __primarykey__ = "name" + + graph.delete_all() + + a = Node("Person", name="Alice") + a.__model__ = Person + a.__primarylabel__ = "Person" + graph.merge(a) + assert graph.nodes.match("Person", name="Alice").first() == a + + +def test_can_merge_node_with_primary_key_overriding_model(graph): + from py2neo.ogm import Model + + class Person(Model): + __primarylabel__ = "Person" + __primarykey__ = "nom" + + graph.delete_all() + + a = Node("Person", name="Alice") + a.__model__ = Person + a.__primarykey__ = "name" + graph.merge(a) + assert graph.nodes.match("Person", name="Alice").first() == a