Skip to content

Commit e6a2efc

Browse files
authored
Drop EntitySetView indexing by int id (#1187)
Graph type sets (`neo4j.graph.EntitySetView`) can no longer by indexed by legacy `id` (`int`, e.g., `graph.nodes[0]`). Use the `element_id` instead (`str`, e.g., `graph.nodes["..."]`).
1 parent 185f24f commit e6a2efc

File tree

7 files changed

+49
-60
lines changed

7 files changed

+49
-60
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog.
100100
Make sure to call `.close()` on them explicitly or use them in a `with` statement.
101101
- Make `Summary.summary_notifications` a `tuple` instead of a `list` and type it with `Sequence` to signify that it
102102
should be treated as immutable.
103+
- Graph type sets (`neo4j.graph.EntitySetView`) can no longer by indexed by legacy `id` (`int`, e.g., `graph.nodes[0]`).
104+
Use the `element_id` instead (`str`, e.g., `graph.nodes["..."]`).
103105

104106

105107
## Version 5.28

src/neo4j/_codec/hydration/v1/hydration_handler.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ def hydrate_node(self, id_, labels=None, properties=None, element_id=None):
7474
except KeyError:
7575
inst = Node(self.graph, element_id, id_, labels, properties)
7676
self.graph._nodes[element_id] = inst
77-
self.graph._legacy_nodes[id_] = inst
7877
else:
7978
# If we have already hydrated this node as the endpoint of
8079
# a relationship, it won't have any labels or properties.
@@ -125,7 +124,6 @@ def hydrate_unbound_relationship(
125124
r = self.graph.relationship_type(type_)
126125
inst = r(self.graph, element_id, id_, properties)
127126
self.graph._relationships[element_id] = inst
128-
self.graph._legacy_relationships[id_] = inst
129127
return inst
130128

131129
def hydrate_path(self, nodes, relationships, sequence):

src/neo4j/graph/__init__.py

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@
2121
import typing as t
2222
from collections.abc import Mapping
2323

24-
from .._warnings import (
25-
deprecated,
26-
deprecation_warn,
27-
)
24+
25+
if t.TYPE_CHECKING:
26+
from typing_extensions import deprecated
27+
else:
28+
from .._warnings import deprecated
2829

2930

3031
__all__ = [
@@ -50,15 +51,10 @@ class Graph:
5051

5152
def __init__(self) -> None:
5253
self._nodes: dict[str, Node] = {}
53-
self._legacy_nodes: dict[int, Node] = {} # TODO: 6.0 - remove
5454
self._relationships: dict[str, Relationship] = {}
55-
# TODO: 6.0 - remove
56-
self._legacy_relationships: dict[int, Relationship] = {}
5755
self._relationship_types: dict[str, type[Relationship]] = {}
58-
self._node_set_view = EntitySetView(self._nodes, self._legacy_nodes)
59-
self._relationship_set_view = EntitySetView(
60-
self._relationships, self._legacy_relationships
61-
)
56+
self._node_set_view = EntitySetView(self._nodes)
57+
self._relationship_set_view = EntitySetView(self._relationships)
6258

6359
@property
6460
def nodes(self) -> EntitySetView[Node]:
@@ -209,19 +205,10 @@ class EntitySetView(Mapping, t.Generic[_T]):
209205
def __init__(
210206
self,
211207
entity_dict: dict[str, _T],
212-
legacy_entity_dict: dict[int, _T],
213208
) -> None:
214209
self._entity_dict = entity_dict
215-
self._legacy_entity_dict = legacy_entity_dict # TODO: 6.0 - remove
216-
217-
def __getitem__(self, e_id: int | str) -> _T:
218-
# TODO: 6.0 - remove this compatibility shim
219-
if isinstance(e_id, (int, float, complex)):
220-
deprecation_warn(
221-
"Accessing entities by an integer id is deprecated, "
222-
"use the new style element_id (str) instead"
223-
)
224-
return self._legacy_entity_dict[e_id]
210+
211+
def __getitem__(self, e_id: str) -> _T:
225212
return self._entity_dict[e_id]
226213

227214
def __len__(self) -> int:

tests/unit/async_/work/test_result.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -681,17 +681,9 @@ async def test_result_graph(records):
681681
nodes = graph.nodes
682682

683683
assert set(nodes._entity_dict) == {"0", "1"}
684-
for key in (
685-
"0",
686-
0,
687-
0.0,
688-
# I pray to god that no-one actually accessed nodes with complex
689-
# numbers, but theoretically it would have worked with the legacy
690-
# number IDs
691-
0 + 0j,
692-
):
684+
for key in ("0", 0, 0.0, 0 + 0j):
693685
if not isinstance(key, str):
694-
with pytest.warns(DeprecationWarning, match="element_id"):
686+
with pytest.raises(KeyError):
695687
alice = nodes[key]
696688
else:
697689
alice = nodes[key]
@@ -703,7 +695,7 @@ async def test_result_graph(records):
703695

704696
for key in ("1", 1, 1.0, 1 + 0j):
705697
if not isinstance(key, str):
706-
with pytest.warns(DeprecationWarning, match="element_id"):
698+
with pytest.raises(KeyError):
707699
bob = nodes[key]
708700
else:
709701
bob = nodes[key]
@@ -720,7 +712,7 @@ async def test_result_graph(records):
720712

721713
for key in ("0", 0, 0.0, 0 + 0j):
722714
if not isinstance(key, str):
723-
with pytest.warns(DeprecationWarning, match="element_id"):
715+
with pytest.raises(KeyError):
724716
rel = rels[key]
725717
else:
726718
rel = rels[key]

tests/unit/common/graph/test_graph.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,7 @@ def with_relationship(
5454
start_node_element_id = f"e{start_node_id}"
5555
end_node_element_id = f"e{end_node_id}"
5656
self._relationship_counter += 1
57-
with pytest.warns(DeprecationWarning):
58-
assert start_node_id in self._hydrator.graph.nodes
5957
assert start_node_element_id in self._hydrator.graph.nodes
60-
with pytest.warns(DeprecationWarning):
61-
assert end_node_id in self._hydrator.graph.nodes
6258
assert end_node_element_id in self._hydrator.graph.nodes
6359

6460
self._hydrator.hydrate_relationship(
@@ -363,3 +359,25 @@ def test_copy_path():
363359
graph1 = path1.graph
364360
graph2 = path2.graph
365361
assert graph1 is graph2
362+
363+
364+
def test_node_id_access() -> None:
365+
assert 0 not in GRAPH.nodes
366+
with pytest.raises(KeyError):
367+
_ = GRAPH.nodes[0] # type: ignore # expected to fail
368+
369+
370+
def test_node_element_id_access() -> None:
371+
assert "e0" in GRAPH.nodes
372+
_ = GRAPH.nodes["e0"]
373+
374+
375+
def test_relationship_id_access() -> None:
376+
assert 0 not in GRAPH.relationships
377+
with pytest.raises(KeyError):
378+
_ = GRAPH.relationships[0] # type: ignore # expected to fail
379+
380+
381+
def test_relationship_element_id_access() -> None:
382+
assert "e0" in GRAPH.relationships
383+
_ = GRAPH.relationships["e0"]

tests/unit/common/test_types.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -570,13 +570,13 @@ def test_graph_views_v1():
570570
g = hydration_scope.get_graph()
571571
assert len(g.nodes) == 3
572572
for id_, node in ((1, alice), (2, bob), (3, carol)):
573-
with pytest.warns(DeprecationWarning, match=r"element_id \(str\)"):
573+
with pytest.raises(KeyError):
574574
assert g.nodes[id_] == node
575575
assert g.nodes[str(id_)] == node
576576

577577
assert len(g.relationships) == 2
578578
for id_, rel in ((1, alice_knows_bob), (2, carol_dislikes_bob)):
579-
with pytest.warns(DeprecationWarning, match=r"element_id \(str\)"):
579+
with pytest.raises(KeyError):
580580
assert g.relationships[id_] == rel
581581
assert g.relationships[str(id_)] == rel
582582

@@ -668,24 +668,24 @@ def test_graph_views_v2_repr(example_graph_builder_v2, legacy_id):
668668
(2, g.bob.element_id, g.bob),
669669
(3, g.carol.element_id, g.carol),
670670
):
671-
with pytest.warns(DeprecationWarning, match=r"element_id \(str\)"):
672-
assert g.graph.nodes[id_] == node
671+
with pytest.raises(KeyError):
672+
assert g.graph.nodes[id_] == node # type: ignore # should fail
673673
assert g.graph.nodes[element_id] == node
674674
if not legacy_id:
675675
with pytest.raises(KeyError):
676-
g.graph.nodes[str(id_)]
676+
_ = g.graph.nodes[str(id_)]
677677

678678
assert len(g.graph.relationships) == 2
679679
for id_, element_id, rel in (
680680
(1, g.alice_knows_bob.element_id, g.alice_knows_bob),
681681
(2, g.carol_dislikes_bob.element_id, g.carol_dislikes_bob),
682682
):
683-
with pytest.warns(DeprecationWarning, match=r"element_id \(str\)"):
684-
assert g.graph.relationships[id_] == rel
683+
with pytest.raises(KeyError):
684+
assert g.graph.relationships[id_] == rel # type: ignore
685685
assert g.graph.relationships[element_id] == rel
686686
if not legacy_id:
687687
with pytest.raises(KeyError):
688-
g.graph.relationships[str(id_)]
688+
_ = g.graph.relationships[str(id_)]
689689

690690

691691
@pytest.mark.parametrize("legacy_id", (True, False))

tests/unit/sync/work/test_result.py

Lines changed: 4 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)