Skip to content

Commit 074bc6d

Browse files
Merge pull request #707 from neo4j-contrib/rc/5.0.1
Release 5.0.1
2 parents fb90198 + 9c8cf6c commit 074bc6d

23 files changed

+330
-361
lines changed

.github/workflows/integration-tests.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
push:
88
branches: [ "master" ]
99
pull_request:
10-
branches: [ "master" ]
10+
branches: [ "master", "rc/*" ]
1111

1212
jobs:
1313
build:
@@ -34,7 +34,11 @@ jobs:
3434
python -m pip install --upgrade pip
3535
pip install -e '.[dev]'
3636
- name: Test with pytest
37+
env:
38+
AURA_TEST_DB_USER: ${{ secrets.AURA_TEST_DB_USER }}
39+
AURA_TEST_DB_PASSWORD: ${{ secrets.AURA_TEST_DB_PASSWORD }}
40+
AURA_TEST_DB_HOSTNAME: ${{ secrets.AURA_TEST_DB_HOSTNAME }}
3741
run: |
38-
pytest
42+
pytest --cov=neomodel --cov-report=html:coverage_report
3943
- name: Upload coverage reports to Codecov
4044
uses: codecov/codecov-action@v3

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ lib
2020
.vscode
2121
pyvenv.cfg
2222
coverage_report/
23-
.coverage*
23+
.coverage*
24+
.DS_STORE
25+
cov.xml

Changelog

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
Version 5.0.1 2023-06
2+
* Removed deprecated methods StructuredRel.delete and RelationshipManager.search
3+
* Extended test coverage, fixed some typos, improve linting
4+
* Upcoming breaking change notice : Version 5.1.0 will introduce a breaking change for users targeting a Neo4j database in version 5. This release will introduce Neo4j's new element_id, which replaces id. The breaking change will happen if you have custom Cypher queries that do things like "WHERE id(n)=$id" => you will have to use Cypher's elementId() function instead starting from neomodel 5.1.0
5+
16
Version 5.0.0 2023-03
27
* Confirmed support of Neo4j versions 5.x and 4.4 (LTS)
38
* Dropped support of EOL Neo4j versions (4.3 and below)

README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ Setup a virtual environment, install neomodel for development and run the test s
9595
$ pip install -e '.[dev]'
9696
$ pytest
9797

98+
The tests in "test_connection.py" will fail locally if you don't specify the following environment variables::
99+
100+
$ export AURA_TEST_DB_USER=username
101+
$ export AURA_TEST_DB_PASSWORD=password
102+
$ export AURA_TEST_DB_HOSTNAME=url
103+
98104
If you are running a neo4j database for the first time the test suite will set the password to 'test'.
99105
If the database is already populated, the test suite will abort with an error message and ask you to re-run it with the
100106
``--resetdb`` switch. This is a safeguard to ensure that the test suite does not accidentally wipe out a database if you happen

doc/source/relationships.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ that are directly related to another ``Person``, through all relationships::
251251
definition)
252252
all_jims_relations = relations_traversal.all()
253253

254-
The ``defintion`` argument is a :term:`py3:mapping` with these items:
254+
The ``definition`` argument is a :term:`py3:mapping` with these items:
255255

256256
================= ===============================================================
257257
``node_class`` The class of the traversal target node.
@@ -260,3 +260,8 @@ The ``defintion`` argument is a :term:`py3:mapping` with these items:
260260
or an explicit name of a relation type (the edge's label).
261261
``model`` The class of the relation model, ``None`` for such without one.
262262
================= ===============================================================
263+
264+
.. note::
265+
266+
The ``RelationshipTo`` and ``RelationshipFrom`` objects are simply a proxy
267+
for defining Traversal objects at the class level.

neomodel/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,4 @@
3838
__email__ = "[email protected]"
3939
__license__ = "MIT"
4040
__package__ = "neomodel"
41-
__version__ = "5.0.0"
41+
__version__ = "5.0.1"

neomodel/contrib/spatial_properties.py

Lines changed: 19 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,7 @@ def __init__(self, *args, **kwargs):
102102

103103
# CRS validity check is common to both types of constructors that follow
104104
if crs is not None and crs not in ACCEPTABLE_CRS:
105-
raise ValueError(
106-
"Invalid CRS({}). Expected one of {}".format(
107-
crs, ",".join(ACCEPTABLE_CRS)
108-
)
109-
)
105+
raise ValueError(f"Invalid CRS({crs}). Expected one of {','.join(ACCEPTABLE_CRS)}")
110106
self._crs = crs
111107

112108
# If positional arguments have been supplied, then this is a possible call to the copy constructor or
@@ -116,11 +112,7 @@ def __init__(self, *args, **kwargs):
116112
if isinstance(args[0], (tuple, list)):
117113
# Check dimensionality of tuple
118114
if len(args[0]) < 2 or len(args[0]) > 3:
119-
raise ValueError(
120-
"Invalid vector dimensions. Expected 2 or 3, received {}".format(
121-
len(args[0])
122-
)
123-
)
115+
raise ValueError(f"Invalid vector dimensions. Expected 2 or 3, received {len(args[0])}")
124116
x = args[0][0]
125117
y = args[0][1]
126118
if len(args[0]) == 3:
@@ -148,20 +140,10 @@ def __init__(self, *args, **kwargs):
148140
if crs is None:
149141
self._crs = "cartesian-3d"
150142
else:
151-
raise ValueError(
152-
"Invalid vector dimensions. "
153-
"Expected 2 or 3, received {}".format(
154-
len(args[0].coords[0])
155-
)
156-
)
143+
raise ValueError(f"Invalid vector dimensions. Expected 2 or 3, received {len(args[0].coords[0])}")
157144
return
158145
else:
159-
raise TypeError(
160-
"Invalid object passed to copy constructor. "
161-
"Expected NeomodelPoint or shapely Point, received {}".format(
162-
type(args[0])
163-
)
164-
)
146+
raise TypeError(f"Invalid object passed to copy constructor. Expected NeomodelPoint or shapely Point, received {type(args[0])}")
165147

166148
# Initialisation is either via x,y[,z] XOR longitude,latitude[,height]. Specifying both leads to an error.
167149
if any(i is not None for i in [x, y, z]) and any(
@@ -208,16 +190,12 @@ def __init__(self, *args, **kwargs):
208190
if "-3d" not in self._crs:
209191
super().__init__((float(_x), float(_y)), **kwargs)
210192
else:
211-
raise ValueError(
212-
"Invalid vector dimensions(2) for given CRS({}).".format(self._crs)
213-
)
193+
raise ValueError(f"Invalid vector dimensions(2) for given CRS({self._crs}).")
214194
else:
215195
if "-3d" in self._crs:
216196
super().__init__((float(_x), float(_y), float(_z)), **kwargs)
217197
else:
218-
raise ValueError(
219-
"Invalid vector dimensions(3) for given CRS({}).".format(self._crs)
220-
)
198+
raise ValueError(f"Invalid vector dimensions(3) for given CRS({self._crs}).")
221199

222200
@property
223201
def crs(self):
@@ -227,53 +205,47 @@ def crs(self):
227205
def x(self):
228206
if not self._crs.startswith("cartesian"):
229207
raise AttributeError(
230-
'Invalid coordinate ("x") for points defined over {}'.format(self.crs)
208+
f'Invalid coordinate ("x") for points defined over {self.crs}'
231209
)
232210
return super().x
233211

234212
@property
235213
def y(self):
236214
if not self._crs.startswith("cartesian"):
237215
raise AttributeError(
238-
'Invalid coordinate ("y") for points defined over {}'.format(self.crs)
216+
f'Invalid coordinate ("y") for points defined over {self.crs}'
239217
)
240218
return super().y
241219

242220
@property
243221
def z(self):
244222
if not self._crs == "cartesian-3d":
245223
raise AttributeError(
246-
'Invalid coordinate ("z") for points defined over {}'.format(self.crs)
224+
f'Invalid coordinate ("z") for points defined over {self.crs}'
247225
)
248226
return super().z
249227

250228
@property
251229
def latitude(self):
252230
if not self._crs.startswith("wgs-84"):
253231
raise AttributeError(
254-
'Invalid coordinate ("latitude") for points defined over {}'.format(
255-
self.crs
256-
)
232+
f'Invalid coordinate ("latitude") for points defined over {self.crs}'
257233
)
258234
return super().y
259235

260236
@property
261237
def longitude(self):
262238
if not self._crs.startswith("wgs-84"):
263239
raise AttributeError(
264-
'Invalid coordinate ("longitude") for points defined over {}'.format(
265-
self.crs
266-
)
240+
f'Invalid coordinate ("longitude") for points defined over {self.crs}'
267241
)
268242
return super().x
269243

270244
@property
271245
def height(self):
272246
if not self._crs == "wgs-84-3d":
273247
raise AttributeError(
274-
'Invalid coordinate ("height") for points defined over {}'.format(
275-
self.crs
276-
)
248+
f'Invalid coordinate ("height") for points defined over {self.crs}'
277249
)
278250
return super().z
279251

@@ -312,22 +284,13 @@ def __init__(self, *args, **kwargs):
312284
crs = None
313285

314286
if crs is None or (crs not in ACCEPTABLE_CRS):
315-
raise ValueError(
316-
"Invalid CRS({}). "
317-
"Point properties require CRS to be one of {}".format(
318-
crs, ",".join(ACCEPTABLE_CRS)
319-
)
320-
)
287+
raise ValueError(f"Invalid CRS({crs}). Point properties require CRS to be one of {','.join(ACCEPTABLE_CRS)}")
321288

322289
# If a default value is passed and it is not a callable, then make sure it is in the right type
323290
if "default" in kwargs:
324291
if not hasattr(kwargs["default"], "__call__"):
325292
if not isinstance(kwargs["default"], NeomodelPoint):
326-
raise TypeError(
327-
"Invalid default value. "
328-
"Expected NeomodelPoint, received {}".format(
329-
type(kwargs["default"])
330-
)
293+
raise TypeError(f"Invalid default value. Expected NeomodelPoint, received {type(kwargs['default'])}"
331294
)
332295

333296
super().__init__(*args, **kwargs)
@@ -344,26 +307,16 @@ def inflate(self, value):
344307
"""
345308
if not isinstance(value, neo4j.spatial.Point):
346309
raise TypeError(
347-
"Invalid datatype to inflate. Expected POINT datatype, received {}".format(
348-
type(value)
349-
)
310+
f"Invalid datatype to inflate. Expected POINT datatype, received {type(value)}"
350311
)
351312

352313
try:
353314
value_point_crs = SRID_TO_CRS[value.srid]
354315
except KeyError as e:
355-
raise ValueError(
356-
"Invalid SRID to inflate. "
357-
"Expected one of {}, received {}".format(SRID_TO_CRS.keys(), value.srid)
358-
) from e
316+
raise ValueError(f"Invalid SRID to inflate. Expected one of {SRID_TO_CRS.keys()}, received {value.srid}") from e
359317

360318
if self._crs != value_point_crs:
361-
raise ValueError(
362-
"Invalid CRS. "
363-
"Expected POINT defined over {}, received {}".format(
364-
self._crs, value_point_crs
365-
)
366-
)
319+
raise ValueError(f"Invalid CRS. Expected POINT defined over {self._crs}, received {value_point_crs}")
367320
# cartesian
368321
if value.srid == 7203:
369322
return NeomodelPoint(x=value.x, y=value.y)
@@ -393,17 +346,11 @@ def deflate(self, value):
393346
"""
394347
if not isinstance(value, NeomodelPoint):
395348
raise TypeError(
396-
"Invalid datatype to deflate. Expected NeomodelPoint, received {}".format(
397-
type(value)
398-
)
349+
f"Invalid datatype to deflate. Expected NeomodelPoint, received {type(value)}"
399350
)
400351

401352
if not value.crs == self._crs:
402-
raise ValueError(
403-
"Invalid CRS. "
404-
"Expected NeomodelPoint defined over {}, "
405-
"received NeomodelPoint defined over {}".format(self._crs, value.crs)
406-
)
353+
raise ValueError(f"Invalid CRS. Expected NeomodelPoint defined over {self._crs}, received NeomodelPoint defined over {value.crs}")
407354

408355
if value.crs == "cartesian-3d":
409356
return neo4j.spatial.CartesianPoint((value.x, value.y, value.z))

0 commit comments

Comments
 (0)