Skip to content

Commit 54dc5db

Browse files
authored
Improve repr string representation of spatial types (#1231)
Instead of `POINT(1.0 2.0 3.0)` (regardless of the sub-type) the `repr` string representation is now `WGS84Point(1.0, 2.0, 3.0)` or similar. This is more in line with Python's recommendations: > If at all possible, this should look like a valid Python expression that > could be used to recreate an object with the same value (given an appropriate > environment). If this is not possible, a string of the form > <...some useful description...> should be returned. > > -- https://docs.python.org/3/reference/datamodel.html#object.__repr__
1 parent 9816ca0 commit 54dc5db

File tree

6 files changed

+55
-9
lines changed

6 files changed

+55
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ See also https://github.com/neo4j/neo4j-python-driver/wiki for a full changelog.
193193
- The driver incorrectly applied a timeout hint received from the server to both read and write I/O operations.
194194
It is now only applied to read I/O operations.
195195
In turn, a new configuration option `connection_write_timeout` with a default value of `30 seconds` is introduced.
196+
- Adjust `repr` string representation of spatial types to conform with Python's recommendations.
196197

197198

198199
## Version 5.28

src/neo4j/spatial/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def __new__(cls, iterable: _t.Iterable[float]) -> Point:
6969
return tuple.__new__(cls, map(float, iterable))
7070

7171
def __repr__(self) -> str:
72-
return f"POINT({' '.join(map(str, self))})"
72+
return f"{self.__class__.__name__}({', '.join(map(repr, self))})"
7373

7474
def __eq__(self, other: object) -> bool:
7575
try:

tests/integration/examples/test_geospatial_types_example.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ def test_cartesian_point(driver):
4949

5050
# Reading a 2D point from a record
5151
point2d: CartesianPoint = record_with_2d_point.get("fieldName")
52-
str(point2d) # POINT(1.0 5.1)
52+
str(point2d) # CartesianPoint(1.0, 5.1)
5353
_ = point2d.x # 1.0
5454
_ = point2d.y # 5.1
5555
# point2d.z raises AttributeError
@@ -58,15 +58,15 @@ def test_cartesian_point(driver):
5858

5959
# Reading a 3D point from a record
6060
point3d: CartesianPoint = record_with_3d_point.get("fieldName")
61-
str(point3d) # POINT(1.0 -2.0 3.1)
61+
str(point3d) # CartesianPoint(1.0, -2.0, 3.1)
6262
_ = point3d.x # 1.0
6363
_ = point3d.y # -2.0
6464
_ = point3d.z # 3.1
6565
_ = point3d.srid # 9157
6666
len(point2d) # 3
6767
# end::geospatial-types-cartesian[]
6868

69-
assert str(point2d) == "POINT(1.0 5.1)"
69+
assert str(point2d) == "CartesianPoint(1.0, 5.1)"
7070
assert isinstance(point2d.x, float) and point2d.x == 1.0
7171
assert isinstance(point2d.y, float) and point2d.y == 5.1
7272
with pytest.raises(AttributeError):
@@ -75,7 +75,7 @@ def test_cartesian_point(driver):
7575
assert len(point2d) == 2
7676
assert point2d == in_point2d
7777

78-
assert str(point3d) == "POINT(1.0 -2.0 3.1)"
78+
assert str(point3d) == "CartesianPoint(1.0, -2.0, 3.1)"
7979
assert isinstance(point3d.x, float) and point3d.x == 1.0
8080
assert isinstance(point3d.y, float) and point3d.y == -2.0
8181
assert isinstance(point3d.z, float) and point3d.z == 3.1
@@ -110,7 +110,7 @@ def test_wgs84_point(driver):
110110

111111
# Reading a 2D point from a record
112112
point2d: WGS84Point = record_with_2d_point.get("fieldName")
113-
str(point2d) # POINT(1.0 5.1)
113+
str(point2d) # WGS84Point(1.0, 5.1)
114114
_ = point2d.longitude # 1.0 (point2d.x is an alias for longitude)
115115
_ = point2d.latitude # 5.1 (point2d.y is an alias for latitude)
116116
# point2d.height raises AttributeError (same with point2d.z)
@@ -119,15 +119,15 @@ def test_wgs84_point(driver):
119119

120120
# Reading a 3D point from a record
121121
point3d = record_with_3d_point.get("fieldName") # type: WGS84Point
122-
str(point3d) # POINT(1.0 -2.0 3.1)
122+
str(point3d) # WGS84Point(1.0, -2.0, 3.1)
123123
_ = point3d.longitude # 1.0 (point3d.x is an alias for longitude)
124124
_ = point3d.latitude # -2.0 (point3d.y is an alias for latitude)
125125
_ = point3d.height # 3.1 (point3d.z is an alias for height)
126126
_ = point3d.srid # 4979
127127
len(point2d) # 3
128128
# end::geospatial-types-wgs84[]
129129

130-
assert str(point2d) == "POINT(1.0 5.1)"
130+
assert str(point2d) == "WGS84Point(1.0, 5.1)"
131131
assert isinstance(point2d.longitude, float) and point2d.longitude == 1.0
132132
assert isinstance(point2d.x, float) and point2d.x == 1.0
133133
assert isinstance(point2d.latitude, float) and point2d.latitude == 5.1
@@ -140,7 +140,7 @@ def test_wgs84_point(driver):
140140
assert len(point2d) == 2
141141
assert point2d == in_point2d
142142

143-
assert str(point3d) == "POINT(1.0 -2.0 3.1)"
143+
assert str(point3d) == "WGS84Point(1.0, -2.0, 3.1)"
144144
assert isinstance(point3d.longitude, float) and point3d.longitude == 1.0
145145
assert isinstance(point3d.x, float) and point3d.x == 1.0
146146
assert isinstance(point3d.latitude, float) and point3d.latitude == -2.0

tests/unit/common/spatial/test_cartesian_point.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,20 @@ def test_pickle(self, expected):
8080
assert expected is not actual
8181
assert expected.foo == actual.foo
8282
assert expected.foo is not actual.foo
83+
84+
@pytest.mark.parametrize(
85+
("args", "expected"),
86+
(
87+
((), "CartesianPoint()"),
88+
((0,), "CartesianPoint(0.0)"),
89+
((1, 2), "CartesianPoint(1.0, 2.0)"),
90+
((1, 2, 3), "CartesianPoint(1.0, 2.0, 3.0)"),
91+
(
92+
(1.23, 2.34, 3.45, 4.56),
93+
"CartesianPoint(1.23, 2.34, 3.45, 4.56)",
94+
),
95+
),
96+
)
97+
def test_repr(self, args, expected):
98+
p = CartesianPoint(args)
99+
assert repr(p) == expected

tests/unit/common/spatial/test_point.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,17 @@ def test_pickle(self, expected):
9393
assert expected is not actual
9494
assert expected.foo == actual.foo
9595
assert expected.foo is not actual.foo
96+
97+
@pytest.mark.parametrize(
98+
("args", "expected"),
99+
(
100+
((), "Point()"),
101+
((0,), "Point(0.0)"),
102+
((1, 2), "Point(1.0, 2.0)"),
103+
((1, 2, 3), "Point(1.0, 2.0, 3.0)"),
104+
((1.23, 2.34, 3.45, 4.56), "Point(1.23, 2.34, 3.45, 4.56)"),
105+
),
106+
)
107+
def test_repr(self, args, expected):
108+
p = Point(args)
109+
assert repr(p) == expected

tests/unit/common/spatial/test_wgs84_point.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,3 +98,17 @@ def test_pickle(self, expected):
9898
assert expected is not actual
9999
assert expected.foo == actual.foo
100100
assert expected.foo is not actual.foo
101+
102+
@pytest.mark.parametrize(
103+
("args", "expected"),
104+
(
105+
((), "WGS84Point()"),
106+
((0,), "WGS84Point(0.0)"),
107+
((1, 2), "WGS84Point(1.0, 2.0)"),
108+
((1, 2, 3), "WGS84Point(1.0, 2.0, 3.0)"),
109+
((1.23, 2.34, 3.45, 4.56), "WGS84Point(1.23, 2.34, 3.45, 4.56)"),
110+
),
111+
)
112+
def test_repr(self, args, expected):
113+
p = WGS84Point(args)
114+
assert repr(p) == expected

0 commit comments

Comments
 (0)