diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d0074b7b..cb46aaf3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -41,7 +41,7 @@ repos:
- id: mypy
additional_dependencies:
- pytest
- - trio >= 0.23
+ - trio >= 0.26
- packaging
- repo: https://github.com/pre-commit/pygrep-hooks
diff --git a/docs/versionhistory.rst b/docs/versionhistory.rst
index 37556166..0b4c8314 100644
--- a/docs/versionhistory.rst
+++ b/docs/versionhistory.rst
@@ -19,10 +19,15 @@ This library adheres to `Semantic Versioning 2.0 `_.
``anyio.open_process()``, ``asyncio.create_subprocess_…()``, ``trio.run_process()``,
and ``subprocess.run()`` already accept (PR by @jmehnle)
- Added the ``info`` property to ``anyio.Path`` on Python 3.14
+- Changed ``anyio.getaddrinfo()`` to ignore (invalid) IPv6 name resolution results when
+ IPv6 support is disabled in Python
- Fixed traceback formatting growing quadratically with level of ``TaskGroup``
nesting on asyncio due to exception chaining when raising ``ExceptionGroups``
in ``TaskGroup.__aexit__``
(`#863 `_; PR by @tapetersen)
+- Fixed ``anyio.Path.iterdir()`` making a blocking call in Python 3.13
+ (`#873 `_; PR by @cbornet and
+ @agronholm)
**4.8.0**
diff --git a/src/anyio/_backends/_asyncio.py b/src/anyio/_backends/_asyncio.py
index f1993307..1ef4ce18 100644
--- a/src/anyio/_backends/_asyncio.py
+++ b/src/anyio/_backends/_asyncio.py
@@ -2674,13 +2674,13 @@ async def getaddrinfo(
type: int | SocketKind = 0,
proto: int = 0,
flags: int = 0,
- ) -> list[
+ ) -> Sequence[
tuple[
AddressFamily,
SocketKind,
int,
str,
- tuple[str, int] | tuple[str, int, int, int],
+ tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
]
]:
return await get_running_loop().getaddrinfo(
diff --git a/src/anyio/_backends/_trio.py b/src/anyio/_backends/_trio.py
index 32ae8ace..b80cc04f 100644
--- a/src/anyio/_backends/_trio.py
+++ b/src/anyio/_backends/_trio.py
@@ -1246,13 +1246,13 @@ async def getaddrinfo(
type: int | SocketKind = 0,
proto: int = 0,
flags: int = 0,
- ) -> list[
+ ) -> Sequence[
tuple[
AddressFamily,
SocketKind,
int,
str,
- tuple[str, int] | tuple[str, int, int, int],
+ tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
]
]:
return await trio.socket.getaddrinfo(host, port, family, type, proto, flags)
diff --git a/src/anyio/_core/_fileio.py b/src/anyio/_core/_fileio.py
index 350a873a..a0d61984 100644
--- a/src/anyio/_core/_fileio.py
+++ b/src/anyio/_core/_fileio.py
@@ -544,9 +544,14 @@ async def is_socket(self) -> bool:
async def is_symlink(self) -> bool:
return await to_thread.run_sync(self._path.is_symlink, abandon_on_cancel=True)
- def iterdir(self) -> AsyncIterator[Path]:
- gen = self._path.iterdir()
- return _PathIterator(gen)
+ async def iterdir(self) -> AsyncIterator[Path]:
+ gen = (
+ self._path.iterdir()
+ if sys.version_info < (3, 13)
+ else await to_thread.run_sync(self._path.iterdir, abandon_on_cancel=True)
+ )
+ async for path in _PathIterator(gen):
+ yield path
def joinpath(self, *args: str | PathLike[str]) -> Path:
return Path(self._path.joinpath(*args))
diff --git a/src/anyio/_core/_sockets.py b/src/anyio/_core/_sockets.py
index a822d060..67b1da52 100644
--- a/src/anyio/_core/_sockets.py
+++ b/src/anyio/_core/_sockets.py
@@ -584,6 +584,8 @@ async def getaddrinfo(
return [
(family, type, proto, canonname, convert_ipv6_sockaddr(sockaddr))
for family, type, proto, canonname, sockaddr in gai_res
+ # filter out IPv6 results when IPv6 is disabled
+ if not isinstance(sockaddr[0], int)
]
diff --git a/src/anyio/abc/_eventloop.py b/src/anyio/abc/_eventloop.py
index 2bfdf286..4cfce836 100644
--- a/src/anyio/abc/_eventloop.py
+++ b/src/anyio/abc/_eventloop.py
@@ -315,13 +315,13 @@ async def getaddrinfo(
type: int | SocketKind = 0,
proto: int = 0,
flags: int = 0,
- ) -> list[
+ ) -> Sequence[
tuple[
AddressFamily,
SocketKind,
int,
str,
- tuple[str, int] | tuple[str, int, int, int],
+ tuple[str, int] | tuple[str, int, int, int] | tuple[int, bytes],
]
]:
pass
diff --git a/tests/test_sockets.py b/tests/test_sockets.py
index d6063875..9b420af9 100644
--- a/tests/test_sockets.py
+++ b/tests/test_sockets.py
@@ -18,6 +18,7 @@
from ssl import SSLContext, SSLError
from threading import Thread
from typing import TYPE_CHECKING, Any, Literal, NoReturn, TypeVar, cast
+from unittest import mock
import psutil
import pytest
@@ -52,6 +53,7 @@
wait_socket_writable,
wait_writable,
)
+from anyio._core._eventloop import get_async_backend
from anyio.abc import (
IPSockAddrType,
Listener,
@@ -1846,6 +1848,14 @@ async def test_getaddrinfo_ipv6addr(
]
+async def test_getaddrinfo_ipv6_disabled() -> None:
+ gai_result = [
+ (AddressFamily.AF_INET6, socket.SocketKind.SOCK_STREAM, 6, "", (1, b""))
+ ]
+ with mock.patch.object(get_async_backend(), "getaddrinfo", return_value=gai_result):
+ assert await getaddrinfo("::1", 0) == []
+
+
async def test_getnameinfo() -> None:
expected_result = socket.getnameinfo(("127.0.0.1", 6666), 0)
result = await getnameinfo(("127.0.0.1", 6666))