Skip to content

Commit e66ff23

Browse files
authored
Fix pickle and deepcopy of graph types (#1133)
Since the types of `Relationship`s are tied to the `Graph` object they belong to, fixing `pickle` support for graph types means that `Relationship`s with the same name will have a different type after `deepcopy`ing or pickling and unpickling them or their graph.
1 parent 0e41043 commit e66ff23

File tree

4 files changed

+404
-1
lines changed

4 files changed

+404
-1
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog.
44

55
## NEXT RELEASE
6-
- No breaking or major changes.
6+
- Since the types of `Relationship`s are tied to the `Graph` object they belong to, fixing `pickle` support for graph types means that `Relationship`s with the same name will have a different type after `deepcopy`ing or pickling and unpickling them or their graph.
7+
For more details, see https://github.com/neo4j/neo4j-python-driver/pull/1133
78

89

910
## Version 5.27

src/neo4j/graph/__init__.py

+23
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ def relationship_type(self, name: str) -> type[Relationship]:
8080
)
8181
return cls
8282

83+
def __reduce__(self):
84+
state = self.__dict__.copy()
85+
relationship_types = tuple(state.pop("_relationship_types", {}).keys())
86+
restore_args = (relationship_types,)
87+
return Graph._restore, restore_args, state
88+
89+
@staticmethod
90+
def _restore(relationship_types: tuple[str, ...]) -> Graph:
91+
graph = Graph().__new__(Graph)
92+
graph.__dict__["_relationship_types"] = {
93+
name: type(str(name), (Relationship,), {})
94+
for name in relationship_types
95+
}
96+
return graph
97+
8398

8499
class Entity(t.Mapping[str, t.Any]):
85100
"""
@@ -287,6 +302,14 @@ def type(self) -> str:
287302
"""
288303
return type(self).__name__
289304

305+
def __reduce__(self):
306+
return Relationship._restore, (self.graph, self.type), self.__dict__
307+
308+
@staticmethod
309+
def _restore(graph: Graph, name: str) -> Relationship:
310+
type_ = graph.relationship_type(name)
311+
return type_.__new__(type_)
312+
290313

291314
class Path:
292315
"""Self-contained graph path."""

tests/unit/common/graph/__init__.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Copyright (c) "Neo4j"
2+
# Neo4j Sweden AB [https://neo4j.com]
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# https://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.

0 commit comments

Comments
 (0)