Skip to content

Commit d525f1d

Browse files
authored
Merge pull request #692 from FlorentinD/handle-neo4j-driver-forwarding-server-notifications
Skip GDS notification forwarding if driver configured
2 parents a1dff11 + f87c7c9 commit d525f1d

File tree

5 files changed

+78
-8
lines changed

5 files changed

+78
-8
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@
2828
## Other changes
2929

3030
* Updated required `neo4j` driver from `4.4.2` to the latest 4.4 path release (`4.4.12`) or later.
31+
* Avoid duplications or user-indepedent logs and warnings introduced by the driver option `warn_notification_severity` in `neo4j>=5.21.0`.

graphdatascience/query_runner/neo4j_query_runner.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,15 @@ def create(
6060
else:
6161
raise ValueError(f"Invalid endpoint type: {type(endpoint)}")
6262

63+
if Neo4jQueryRunner._NEO4J_DRIVER_VERSION >= ServerVersion(5, 21, 0):
64+
notifications_logger = logging.getLogger("neo4j.notifications")
65+
# the client does not expose YIELD fields so we just skip these warnings for now
66+
notifications_logger.addFilter(
67+
lambda record: (
68+
"The query used a deprecated field from a procedure" in record.msg and "by 'gds." in record.msg
69+
)
70+
)
71+
6372
return query_runner
6473

6574
@staticmethod
@@ -124,10 +133,19 @@ def run_cypher(
124133
else:
125134
self._last_bookmarks = session.last_bookmarks()
126135

127-
notifications = result.consume().notifications
128-
if notifications:
129-
for notification in notifications:
130-
self._forward_cypher_warnings(notification)
136+
if (
137+
Neo4jQueryRunner._NEO4J_DRIVER_VERSION >= ServerVersion(5, 21, 0)
138+
and result._warn_notification_severity == "WARNING"
139+
):
140+
# the client does not expose YIELD fields so we just skip these warnings for now
141+
warnings.filterwarnings(
142+
"ignore", message=r".*The query used a deprecated field from a procedure\. .* by 'gds.* "
143+
)
144+
else:
145+
notifications = result.consume().notifications
146+
if notifications:
147+
for notification in notifications:
148+
self._forward_cypher_warnings(notification)
131149

132150
return df
133151

graphdatascience/tests/integration/conftest.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def neo4j_driver() -> Generator[Driver, None, None]:
3838

3939
@pytest.fixture(scope="package")
4040
def runner(neo4j_driver: Driver) -> Generator[Neo4jQueryRunner, None, None]:
41-
_runner = Neo4jQueryRunner(neo4j_driver)
41+
_runner = Neo4jQueryRunner.create(neo4j_driver)
4242
_runner.set_database(DB)
4343

4444
yield _runner
@@ -194,10 +194,9 @@ def pytest_collection_modifyitems(config: Any, items: Any) -> None:
194194
server_version = gds._server_version
195195
except Exception as e:
196196
print("Could not derive GDS library server version")
197-
gds.close()
198197
raise e
199-
200-
gds.close()
198+
finally:
199+
gds.close()
201200

202201
skip_incompatible_versions = pytest.mark.skip(reason=f"incompatible with GDS server version {server_version}")
203202

@@ -211,3 +210,17 @@ def pytest_collection_modifyitems(config: Any, items: Any) -> None:
211210

212211
if "max_exclusive" in kwargs and kwargs["max_exclusive"] <= server_version:
213212
item.add_marker(skip_incompatible_versions)
213+
214+
db_driver_version = Neo4jQueryRunner._NEO4J_DRIVER_VERSION
215+
skip_incompatible_driver_version = pytest.mark.skip(reason=f"incompatible with driver version {db_driver_version}")
216+
217+
for item in items:
218+
for mark in item.iter_markers(name="compatible_with_db_driver"):
219+
kwargs = mark.kwargs
220+
221+
if "min_inclusive" in kwargs and kwargs["min_inclusive"] > db_driver_version:
222+
item.add_marker(skip_incompatible_driver_version)
223+
continue
224+
225+
if "max_exclusive" in kwargs and kwargs["max_exclusive"] <= db_driver_version:
226+
item.add_marker(skip_incompatible_driver_version)

graphdatascience/tests/integration/test_error_handling.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
from typing import Generator
22

33
import pytest
4+
from neo4j import Driver, GraphDatabase
45

56
from graphdatascience import GraphDataScience
7+
from graphdatascience.server_version.server_version import ServerVersion
8+
from graphdatascience.tests.integration.conftest import AUTH, URI
69

710
GRAPH_NAME = "g"
811

@@ -29,6 +32,15 @@ def run_around_tests(gds: GraphDataScience) -> Generator[None, None, None]:
2932
gds.graph.drop(GRAPH_NAME)
3033

3134

35+
@pytest.fixture
36+
def warning_driver() -> Generator[Driver, None, None]:
37+
driver = GraphDatabase.driver(URI, auth=AUTH, warn_notification_severity="WARNING")
38+
39+
yield driver
40+
41+
driver.close()
42+
43+
3244
def test_bogus_algo(gds: GraphDataScience) -> None:
3345
G, _ = gds.graph.project(GRAPH_NAME, "*", "*")
3446
with pytest.raises(SyntaxError, match="There is no 'gds.bogusAlgoWithLongName.stream' to call$"):
@@ -189,3 +201,28 @@ def test_auto_completion_false_positives(gds: GraphDataScience) -> None:
189201
# Without `graph` prefix
190202
with pytest.raises(SyntaxError, match="There is no 'gds.toUndirected' to call"):
191203
gds.toUndirected()
204+
205+
206+
def test_forward_server_side_warning(gds: GraphDataScience) -> None:
207+
with pytest.raises(Warning, match="The query used a deprecated function: `id`."):
208+
gds.run_cypher("MATCH (n) RETURN id(n)")
209+
210+
211+
@pytest.mark.filterwarnings("ignore: notification warnings are a preview feature")
212+
@pytest.mark.compatible_with_db_driver(min_inclusive=ServerVersion(5, 21, 0))
213+
def test_forward_driver_configured_warning(warning_driver: Driver) -> None:
214+
gds = GraphDataScience(warning_driver)
215+
216+
with pytest.raises(Warning, match="The query used a deprecated function: `id`."):
217+
gds.run_cypher("MATCH (n) RETURN id(n)")
218+
219+
220+
def test_filter_out_client_related__warning(gds: GraphDataScience) -> None:
221+
gds.graph.drop("g", failIfMissing=False)
222+
223+
224+
@pytest.mark.filterwarnings("ignore: notification warnings are a preview feature")
225+
@pytest.mark.compatible_with_db_driver(min_inclusive=ServerVersion(5, 21, 0))
226+
def test_filter_out_client_related__driver_configured_warning(warning_driver: Driver) -> None:
227+
gds = GraphDataScience(warning_driver)
228+
gds.graph.drop("g", failIfMissing=False)

graphdatascience/tests/pytest.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ markers =
44
encrypted_only: mark a test as requiring GDS with either bolt or https ssl.policy configured.
55
model_store_location: mark a test as a requiring neo4j config for gds.model.store_location
66
compatible_with: mark a test as only being compatible with certain GDS server versions
7+
compatible_with_db_driver: mark a test as only being compatible with a certain Neo4j driver version
78
skip_on_aura: mark a test to not be run when targeting an AuraDS instance
89
only_on_aura: mark a test to be run only when targeting an AuraDS instance
910
ogb: mark a test as requiring the ogb dependency

0 commit comments

Comments
 (0)