Skip to content

Commit d88235d

Browse files
authored
Deprecate bolt URI with routing context (#655)
Amend #645 to emit a deprecation warning instead of raising. Starting with 6.0 this will be turned into an error.
1 parent 342a9f5 commit d88235d

File tree

8 files changed

+67
-25
lines changed

8 files changed

+67
-25
lines changed

CHANGELOG.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@
4949
Use `hour_minute_second_nanosecond` instead.
5050
- The property `second` returns an `int` instead of a `float`.
5151
Use `nanosecond` to get the sub-second information.
52-
- Creation of a driver with `bolt[+s[sc]]://` scheme now raises an error if the
53-
URI contains a query part (a routing context). Previously, the routing context
54-
was silently ignored.
52+
- Creation of a driver with `bolt[+s[sc]]://` scheme has been deprecated and
53+
will raise an error in the Future. The routing context was and will be
54+
silently ignored until then.
5555
- `Result.single` now raises `ResultNotSingleError` if not exactly one result is
5656
available.
5757
- Bookmarks

neo4j/_async/driver.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,17 @@ def driver(cls, uri, *, auth=None, **config):
9494

9595
if driver_type == DRIVER_BOLT:
9696
if parse_routing_context(parsed.query):
97-
raise ValueError(
98-
'Routing parameters are not supported with scheme "bolt". '
99-
'Given URI "{}".'.format(uri)
97+
deprecation_warn(
98+
"Creating a direct driver (`bolt://` scheme) with routing "
99+
"context (URI parameters) is deprecated. They will be "
100+
"ignored. This will raise an error in a future release. "
101+
'Given URI "{}"'.format(uri)
100102
)
103+
# TODO: 6.0 - raise instead of warning
104+
# raise ValueError(
105+
# 'Routing parameters are not supported with scheme '
106+
# '"bolt". Given URI "{}".'.format(uri)
107+
# )
101108
return cls.bolt_driver(parsed.netloc, auth=auth, **config)
102109
elif driver_type == DRIVER_NEO4j:
103110
routing_context = parse_routing_context(parsed.query)

neo4j/_async/work/result.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818

1919
from collections import deque
20-
from warnings import warn
2120

2221
from ..._async_compat.util import AsyncUtil
2322
from ...data import DataDehydrator

neo4j/_sync/driver.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,17 @@ def driver(cls, uri, *, auth=None, **config):
9494

9595
if driver_type == DRIVER_BOLT:
9696
if parse_routing_context(parsed.query):
97-
raise ValueError(
98-
'Routing parameters are not supported with scheme "bolt". '
99-
'Given URI "{}".'.format(uri)
97+
deprecation_warn(
98+
"Creating a direct driver (`bolt://` scheme) with routing "
99+
"context (URI parameters) is deprecated. They will be "
100+
"ignored. This will raise an error in a future release. "
101+
'Given URI "{}"'.format(uri)
100102
)
103+
# TODO: 6.0 - raise instead of warning
104+
# raise ValueError(
105+
# 'Routing parameters are not supported with scheme '
106+
# '"bolt". Given URI "{}".'.format(uri)
107+
# )
101108
return cls.bolt_driver(parsed.netloc, auth=auth, **config)
102109
elif driver_type == DRIVER_NEO4j:
103110
routing_context = parse_routing_context(parsed.query)

neo4j/_sync/work/result.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818

1919
from collections import deque
20-
from warnings import warn
2120

2221
from ..._async_compat.util import Util
2322
from ...data import DataDehydrator

testkitbackend/test_config.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
"stub.authorization.test_authorization.TestAuthorizationV4x1.test_should_fail_on_token_expired_on_begin_using_tx_function":
2424
"Flaky: test requires the driver to contact servers in a specific order",
2525
"stub.session_run_parameters.test_session_run_parameters.TestSessionRunParameters.test_empty_query":
26-
"Driver rejects empty queries before sending it to the server"
26+
"Driver rejects empty queries before sending it to the server",
27+
"stub.server_side_routing.test_server_side_routing.TestServerSideRouting.test_direct_connection_with_url_params":
28+
"Driver emits deprecation warning. Behavior will be unified in 6.0."
2729
},
2830
"features": {
2931
"Feature:API:Driver.IsEncrypted": true,

tests/unit/async_/test_driver.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,32 @@
3636
@pytest.mark.parametrize("host", ("localhost", "127.0.0.1",
3737
"[::1]", "[0:0:0:0:0:0:0:1]"))
3838
@pytest.mark.parametrize("port", (":1234", "", ":7687"))
39+
@pytest.mark.parametrize("params", ("", "?routing_context=test"))
3940
@pytest.mark.parametrize("auth_token", (("test", "test"), None))
40-
def test_direct_driver_constructor(protocol, host, port, auth_token):
41-
uri = protocol + host + port
42-
driver = AsyncGraphDatabase.driver(uri, auth=auth_token)
41+
@mark_async_test
42+
async def test_direct_driver_constructor(protocol, host, port, params, auth_token):
43+
uri = protocol + host + port + params
44+
if params:
45+
with pytest.warns(DeprecationWarning, match="routing context"):
46+
driver = AsyncGraphDatabase.driver(uri, auth=auth_token)
47+
else:
48+
driver = AsyncGraphDatabase.driver(uri, auth=auth_token)
4349
assert isinstance(driver, AsyncBoltDriver)
50+
await driver.close()
4451

4552

4653
@pytest.mark.parametrize("protocol", ("neo4j://", "neo4j+s://", "neo4j+ssc://"))
4754
@pytest.mark.parametrize("host", ("localhost", "127.0.0.1",
4855
"[::1]", "[0:0:0:0:0:0:0:1]"))
4956
@pytest.mark.parametrize("port", (":1234", "", ":7687"))
57+
@pytest.mark.parametrize("params", ("", "?routing_context=test"))
5058
@pytest.mark.parametrize("auth_token", (("test", "test"), None))
51-
def test_routing_driver_constructor(protocol, host, port, auth_token):
52-
uri = protocol + host + port
59+
@mark_async_test
60+
async def test_routing_driver_constructor(protocol, host, port, params, auth_token):
61+
uri = protocol + host + port + params
5362
driver = AsyncGraphDatabase.driver(uri, auth=auth_token)
5463
assert isinstance(driver, AsyncNeo4jDriver)
64+
await driver.close()
5565

5666

5767
@pytest.mark.parametrize("test_uri", (
@@ -81,7 +91,8 @@ def test_routing_driver_constructor(protocol, host, port, auth_token):
8191
),
8292
)
8393
)
84-
def test_driver_config_error(
94+
@mark_async_test
95+
async def test_driver_config_error(
8596
test_uri, test_config, expected_failure, expected_failure_message
8697
):
8798
if "+" in test_uri:
@@ -90,7 +101,8 @@ def test_driver_config_error(
90101
with pytest.raises(expected_failure, match=expected_failure_message):
91102
AsyncGraphDatabase.driver(test_uri, **test_config)
92103
else:
93-
AsyncGraphDatabase.driver(test_uri, **test_config)
104+
driver = AsyncGraphDatabase.driver(test_uri, **test_config)
105+
await driver.close()
94106

95107

96108
@pytest.mark.parametrize("test_uri", (
@@ -138,3 +150,5 @@ async def test_driver_opens_write_session_by_default(uri, mocker):
138150
mocker.ANY,
139151
mocker.ANY
140152
)
153+
154+
await driver.close()

tests/unit/sync/test_driver.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,32 @@
3636
@pytest.mark.parametrize("host", ("localhost", "127.0.0.1",
3737
"[::1]", "[0:0:0:0:0:0:0:1]"))
3838
@pytest.mark.parametrize("port", (":1234", "", ":7687"))
39+
@pytest.mark.parametrize("params", ("", "?routing_context=test"))
3940
@pytest.mark.parametrize("auth_token", (("test", "test"), None))
40-
def test_direct_driver_constructor(protocol, host, port, auth_token):
41-
uri = protocol + host + port
42-
driver = GraphDatabase.driver(uri, auth=auth_token)
41+
@mark_sync_test
42+
def test_direct_driver_constructor(protocol, host, port, params, auth_token):
43+
uri = protocol + host + port + params
44+
if params:
45+
with pytest.warns(DeprecationWarning, match="routing context"):
46+
driver = GraphDatabase.driver(uri, auth=auth_token)
47+
else:
48+
driver = GraphDatabase.driver(uri, auth=auth_token)
4349
assert isinstance(driver, BoltDriver)
50+
driver.close()
4451

4552

4653
@pytest.mark.parametrize("protocol", ("neo4j://", "neo4j+s://", "neo4j+ssc://"))
4754
@pytest.mark.parametrize("host", ("localhost", "127.0.0.1",
4855
"[::1]", "[0:0:0:0:0:0:0:1]"))
4956
@pytest.mark.parametrize("port", (":1234", "", ":7687"))
57+
@pytest.mark.parametrize("params", ("", "?routing_context=test"))
5058
@pytest.mark.parametrize("auth_token", (("test", "test"), None))
51-
def test_routing_driver_constructor(protocol, host, port, auth_token):
52-
uri = protocol + host + port
59+
@mark_sync_test
60+
def test_routing_driver_constructor(protocol, host, port, params, auth_token):
61+
uri = protocol + host + port + params
5362
driver = GraphDatabase.driver(uri, auth=auth_token)
5463
assert isinstance(driver, Neo4jDriver)
64+
driver.close()
5565

5666

5767
@pytest.mark.parametrize("test_uri", (
@@ -81,6 +91,7 @@ def test_routing_driver_constructor(protocol, host, port, auth_token):
8191
),
8292
)
8393
)
94+
@mark_sync_test
8495
def test_driver_config_error(
8596
test_uri, test_config, expected_failure, expected_failure_message
8697
):
@@ -90,7 +101,8 @@ def test_driver_config_error(
90101
with pytest.raises(expected_failure, match=expected_failure_message):
91102
GraphDatabase.driver(test_uri, **test_config)
92103
else:
93-
GraphDatabase.driver(test_uri, **test_config)
104+
driver = GraphDatabase.driver(test_uri, **test_config)
105+
driver.close()
94106

95107

96108
@pytest.mark.parametrize("test_uri", (
@@ -138,3 +150,5 @@ def test_driver_opens_write_session_by_default(uri, mocker):
138150
mocker.ANY,
139151
mocker.ANY
140152
)
153+
154+
driver.close()

0 commit comments

Comments
 (0)