Skip to content

Commit 3ded645

Browse files
committed
Fix DNS error re-write on Windows
On windows only, the driver would re-write the DNS error when resolving `Address(None, None)` to be retryable, which it shouldn't.
1 parent 990c3f1 commit 3ded645

File tree

3 files changed

+54
-18
lines changed

3 files changed

+54
-18
lines changed

src/neo4j/_async_compat/network/_util.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
# limitations under the License.
1515

1616

17+
from __future__ import annotations
18+
1719
import asyncio
1820
import contextlib
1921
import logging
@@ -88,14 +90,17 @@ async def _dns_resolver(address, family=0):
8890
type=socket.SOCK_STREAM,
8991
)
9092
except OSError as e:
91-
if e.errno in _RETRYABLE_DNS_ERRNOS or (
92-
e.errno in _EAI_NONAME
93-
and (address.host is not None or address.port is not None)
93+
# note: on some systems like Windows, EAI_NONAME and EAI_NODATA
94+
# have the same error-code.
95+
if e.errno in _EAI_NONAME and (
96+
address.host is None and address.port is None
9497
):
95-
raise ServiceUnavailable(
96-
f"Failed to DNS resolve address {address}: {e}"
97-
) from e
98-
raise ValueError(
98+
err_cls = ValueError
99+
elif e.errno in _RETRYABLE_DNS_ERRNOS or e.errno in _EAI_NONAME:
100+
err_cls = ServiceUnavailable
101+
else:
102+
err_cls = ValueError
103+
raise err_cls(
99104
f"Failed to DNS resolve address {address}: {e}"
100105
) from e
101106
return list(_resolved_addresses_from_info(info, address._host_name))
@@ -179,14 +184,17 @@ def _dns_resolver(address, family=0):
179184
type=socket.SOCK_STREAM,
180185
)
181186
except OSError as e:
182-
if e.errno in _RETRYABLE_DNS_ERRNOS or (
183-
e.errno in _EAI_NONAME
184-
and (address.host is not None or address.port is not None)
187+
# note: on some systems like Windows, EAI_NONAME and EAI_NODATA
188+
# have the same error-code.
189+
if e.errno in _EAI_NONAME and (
190+
address.host is None and address.port is None
185191
):
186-
raise ServiceUnavailable(
187-
f"Failed to DNS resolve address {address}: {e}"
188-
) from e
189-
raise ValueError(
192+
err_cls = ValueError
193+
elif e.errno in _RETRYABLE_DNS_ERRNOS or e.errno in _EAI_NONAME:
194+
err_cls = ServiceUnavailable
195+
else:
196+
err_cls = ValueError
197+
raise err_cls(
190198
f"Failed to DNS resolve address {address}: {e}"
191199
) from e
192200
return _resolved_addresses_from_info(info, address._host_name)

tests/unit/async_/test_addressing.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ async def test_address_resolve_with_custom_resolver_none() -> None:
5656
[
5757
(Address(("example.invalid", "7687")), ServiceUnavailable),
5858
(Address(("example.invalid", 7687)), ServiceUnavailable),
59+
(Address(("example.invalid", None)), ServiceUnavailable),
5960
(Address(("127.0.0.1", "abcd")), ValueError),
6061
(Address((None, None)), ValueError),
6162
(Address((1234, "7687")), TypeError),
@@ -65,14 +66,27 @@ async def test_address_resolve_with_custom_resolver_none() -> None:
6566
async def test_address_resolve_with_unresolvable_address(
6667
test_input, expected
6768
) -> None:
68-
# import contextlib
69-
# with contextlib.suppress(Exception):
7069
with pytest.raises(expected):
7170
await AsyncUtil.list(
7271
AsyncNetworkUtil.resolve_address(test_input, resolver=None)
7372
)
7473

7574

75+
@pytest.mark.parametrize(
76+
"test_input",
77+
[
78+
Address((None, 7687)),
79+
Address(("example.com", None)),
80+
],
81+
)
82+
@mark_async_test
83+
async def test_address_resolves_with_none(test_input) -> None:
84+
resolved = await AsyncUtil.list(
85+
AsyncNetworkUtil.resolve_address(test_input, resolver=None)
86+
)
87+
assert resolved
88+
89+
7690
@mark_async_test
7791
@pytest.mark.parametrize("resolver_type", ("sync", "async"))
7892
async def test_address_resolve_with_custom_resolver(resolver_type) -> None:

tests/unit/sync/test_addressing.py

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

0 commit comments

Comments
 (0)