# anyio changelog > High-level concurrency and networking framework on top of asyncio or Trio - Vendor: agronholm - Category: Developer Tools - Official site: https://github.com/agronholm/anyio - Tracked by: What's New (https://whatsnew.fyi/product/anyio) - Harvested from: GitHub (agronholm/anyio) - Entries below: 10 (newest first) What's New is an index, not a publisher: every entry below links to the vendor's own release notes, which are the authoritative source. Entries are labelled where they are hand-curated sample data, pre-releases, or drawn from a secondary source such as a developer blog. ## Releases ### 4.14.2 - Date: 2026-07-12 - Version: 4.14.2 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.14.2 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.14.2 - **changed** — Changed ByteReceiveStream.receive() implementations to raise a ValueError when max_bytes is not a positive integer - **fixed** — Fixed CapacityLimiter.total_tokens rejecting float("inf") when the limiter was instantiated outside of an event loop - **fixed** — Fixed to_process.run_sync() deadlocking when the worker function writes enough data to sys.stderr to fill the pipe buffer - **fixed** — Fixed TLSStream.wrap() matching an internationalized host name against the peer certificate using IDNA 2003 instead of IDNA 2008 - **fixed** — Fixed anyio.open_process() and run_process() ignoring the extra_groups argument - **fixed** — Fixed CapacityLimiter.acquire_nowait() and CapacityLimiter.acquire_nowait_on_behalf_of() raising trio.WouldBlock instead of anyio.WouldBlock on the trio backend - **fixed** — Fixed CapacityLimiter on the asyncio backend over-granting tokens when a non-blocking acquire was made between a token being released and the notified waiter resuming - **fixed** — Fixed unnecessary CPU spin when delivering cancellation from CancelScope on asyncio under certain conditions - Changed `ByteReceiveStream.receive()` implementations to raise a `ValueError` when `max_bytes` is not a positive integer ([\#1191](https://github.com/agronholm/anyio/pull/1191)) - Fixed `CapacityLimiter.total_tokens` rejecting `float("inf")` when the limiter was instantiated outside of an event loop. The adapter setter checked for infinity by identity (`value is math.inf`), so only the exact `math.inf` singleton was accepted, while every backend setter (using `math.isinf()`) accepts any positive infinity ([\#1189](https://github.com/agronholm/anyio/pull/1189); PR by @greymoth-jp). - Fixed `to_process.run_sync()` deadlocking when the worker function writes enough data to `sys.stderr` to fill the (undrained) pipe buffer. The worker process now redirects `sys.stderr` to `os.devnull` as well, matching the documented behavior - Fixed `TLSStream.wrap()` matching an internationalized (unicode) host name against the peer certificate using IDNA 2003 (via the standard library) instead of IDNA 2008, which could cause the host name to be matched against the wrong certificate ([\#1208](https://github.com/agronholm/anyio/pull/1208)) - Fixed `anyio.open_process()` (and `run_process()`) ignoring the `extra_groups` argument, as it mistakenly passed the value of the `group` argument instead ([\#1209](https://github.com/agronholm/anyio/pull/1209)) - Fixed `CapacityLimiter.acquire_nowait()` and `CapacityLimiter.acquire_nowait_on_behalf_of()` raising `trio.WouldBlock` instead of `anyio.WouldBlock` on the `trio` backend when there are no tokens available ([\#1218](https://github.com/agronholm/anyio/pull/1218)) - Fixed `CapacityLimiter` on the asyncio backend over-granting tokens (`borrowed_tokens` exceeding `total_tokens` and `available_tokens` going negative) when a non-blocking acquire was made in the window between a token being released and the notified waiter resuming. The freed token is now reserved for the woken waiter right away, so the non-blocking acquire correctly raises `WouldBlock` ([\#1170](https://github.com/agronholm/anyio/issues/1170); PR by @gaoflow) - Fixed unnecessary CPU spin when delivering cancellation from `CancelScope` on asyncio under certain conditions, including improper cancel scope nesting ([\#1111](https://github.com/agronholm/anyio/issues/1111)) ### 4.14.1 - Date: 2026-06-24 - Version: 4.14.1 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.14.1 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.14.1 - **fixed** — Teardown of higher-scoped async fixtures failing on asyncio with RuntimeError when an async test raises an outcome exception such as pytest.skip(), pytest.xfail(), or pytest.fail() - **fixed** — CapacityLimiter.total_tokens rejecting a value of 0 when the limiter was instantiated outside of an event loop, contradicting the documented behavior - Fixed teardown of higher-scoped async fixtures failing on asyncio with `RuntimeError: Attempted to exit cancel scope in a different task than it was entered in` when an async test raise an outcome exception (e.g., `pytest.skip()`, `pytest.xfail()`, or `pytest.fail()`) ([\#1179](https://github.com/agronholm/anyio/issues/1179); PR by @EmmanuelNiyonshuti) - Fixed `CapacityLimiter.total_tokens` rejecting a value of `0` when the limiter was instantiated outside of an event loop, contradicting the documented behavior of allowing 0 total tokens ([\#1183](https://github.com/agronholm/anyio/pull/1183); PR by @nyxst4ck) ### 4.14.0 - Date: 2026-06-15 - Version: 4.14.0 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.14.0 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.14.0 - **added** — Support for Python 3.15 - **added** — Asynchronous implementation of the itertools module - **added** — Added the local_port parameter to connect_tcp() to allow binding to a specific local port before connecting - **added** — Support for custom capacity limiters in async path and file I/O functions and classes - **added** — Added the create_task() task group method for easier asyncio migration - **changed** — TaskGroup.start_soon() now returns a TaskHandle - **added** — Added an option for TaskGroup.start() to return a TaskHandle containing the start value in the start_value property - **added** — Added the cancel() convenience method to TaskGroup as a shortcut for cancelling the task group's cancel scope - **changed** — Improved error message when a known backend is not installed to suggest the install command - **changed** — Improved anyio.Path to preserve subclass types by returning Self in methods that return path objects - **changed** — Changed the parameter type annotation in anyio.Path.write_bytes() to accept any ReadableBuffer, allowing bytearray and memoryview - **changed** — Changed type annotations in TaskGroup.start_soon(), TaskGroup.start(), and anyio.from_thread.run() to only accept callables returning coroutine-like objects instead of arbitrary awaitables - **changed** — Changed anyio.run to support callables returning arbitrary awaitables at runtime on all backends - **changed** — Added __slots__ to CancelScope, CapacityLimiter, Condition, Event, Lock, ResourceGuard, and Semaphore - **fixed** — Fixed cancellation exception escaping a cancel scope when triggered via check_cancelled() in a worker thread - **fixed** — Fixed TaskGroup raising AttributeError instead of a clear error when entered more than once - **fixed** — Fixed lost type information when passing arguments to lru_cache - **fixed** — Fixed test resumption after KeyboardInterrupt in async generator fixtures on the asyncio backend - **fixed** — Fixed import of __main__ in to_process workers when entrypoint script doesn't end in .py - **fixed** — Fixed SocketListener.from_socket() returning a TCP listener for AF_UNIX listening sockets - Added support for Python 3.15 - Added an asynchronous implementation of the `itertools` module ([\#998](https://github.com/agronholm/anyio/issues/998); PR by @11kkw) - Added the `local_port` parameter to `connect_tcp()` to allow binding to a specific local port before connecting ([\#1067](https://github.com/agronholm/anyio/issues/1067); PR by @nullwiz) - Added support for custom capacity limiters in async path and file I/O functions and classes - Added the `create_task()` task group method for easier asyncio migration (returns a `TaskHandle`) ([\#1098](https://github.com/agronholm/anyio/pull/1098)) - Changed `TaskGroup.start_soon()` to return a `TaskHandle` - Added an option for `TaskGroup.start()` to return a `TaskHandle` (which then contains the start value in the `start_value` property) - Added the `cancel()` convenience method to `TaskGroup` as a shortcut for cancelling the task group's cancel scope - Improved the error message when a known backend is not installed to suggest the install command ([\#1115](https://github.com/agronholm/anyio/pull/1115); PR by @EmmanuelNiyonshuti) - Improved `anyio.Path` to preserve subclass types by returning `Self` in methods that return path objects ([\#1130](https://github.com/agronholm/anyio/issues/1130); PR by @EmmanuelNiyonshuti) - Changed the parameter type annotation in `anyio.Path.write_bytes()` to accept any `ReadableBuffer`, thus allowing it to accept `bytearray` and `memoryview` to match `pathlib.Path.write_bytes()` ([\#1135](https://github.com/agronholm/anyio/issues/1135); PR by @SAY-5) - Changed several type annotations to only accept callables returning coroutine-like objects instead of arbitrary awaitables: - `TaskGroup.start_soon()` - `TaskGroup.start()` - `anyio.from_thread.run()` This reverts an earlier change from v3.7.0 which was made in error. ([\#1153](https://github.com/agronholm/anyio/pull/1153)) - Changed `anyio.run` to support callables returning arbitrary awaitables at runtime on all backends. Previously, this only worked on asyncio ([\#1171](https://github.com/agronholm/anyio/pull/1171); PR by @gschaffner) - Changed several classes (and their subclasses) to have `__slots__` (with `__weakref__`): - `anyio.CancelScope` - `anyio.CapacityLimiter` - `anyio.Condition` - `anyio.Event` - `anyio.Lock` - `anyio.ResourceGuard` - `anyio.Semaphore` - Fixed cancellation exception escaping a cancel scope when triggered via `check_cancelled()` in a worker thread ([\#1113](https://github.com/agronholm/anyio/issues/1113)) - Fixed `TaskGroup` raising `AttributeError` instead of a clear error when entered more than once ([\#1109](https://github.com/agronholm/anyio/issues/1109); PR by @bahtya) - Fixed lost type information when passing arguments to `lru_cache` ([\#1104](https://github.com/agronholm/anyio/pull/1104); PR by @Graeme22) - Fixed test resumption after `KeyboardInterrupt` in async generator fixtures on the asyncio backend ([\#1060](https://github.com/agronholm/anyio/issues/1060); PR by @EmmanuelNiyonshuti) - Fixed import of `__main__` in `to_process` workers when entrypoint script doesn't end in `.py`, such as when using `console_script` entrypoints. ([\#1027](https://github.com/agronholm/anyio/issues/1027); PR by @tapetersen) - Fixed `SocketListener.from_socket()` returning a TCP listener for `AF_UNIX` listening sockets, causing `accept()` to fail with `ENOTSUP` ([\#1132](https://github.com/agronholm/anyio/issues/1132); PR by @kudato) - Fixed `UDPSocket.aclose()` and `ConnectedUDPSocket.aclose()` on asyncio returning before the underlying socket FD was actually released ([\#1147](https://github.com/agronholm/anyio/pull/1147); PR by @matias-arrelid) - Fixed trio backend test runner hanging indefinitely instead of raising an error when dynamically accessing an async fixture via `request.getfixturevalue` ([\#1148](https://github.com/agronholm/anyio/issues/1148); PR by @EmmanuelNiyonshuti) - Fixed cancelling tasks started throug _[Truncated at 4000 characters — full notes: https://github.com/agronholm/anyio/releases/tag/4.14.0]_ ### 4.13.0 - Date: 2026-03-24 - Version: 4.13.0 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.13.0 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.13.0 - **removed** — Dropped support for Python 3.9 - **added** — Added a ttl parameter to the anyio.functools.lru_cache wrapper - **changed** — Widened the type annotations of file I/O streams to accept IO[bytes] instead of just BinaryIO - **fixed** — Fixed anyio.Path not being compatible with Python 3.15 due to the removal of pathlib.Path.is_reserved() and the addition of pathlib.Path.__vfspath__() - **fixed** — Fixed the BrokenResourceError raised by the asyncio SocketStream not having the original exception as its cause - **fixed** — Fixed the TypeError raised when using "func" as a parameter name in pytest.mark.parametrize when using the pytest plugin - **fixed** — Fixed the pytest plugin not running tests that had the anyio marker added programmatically via pytest_collection_modifyitems - **fixed** — Fixed cancellation exceptions leaking from a CancelScope on asyncio when they are contained in an exception group alongside non-cancellation exceptions - **fixed** — Fixed Condition.wait() not passing on a notification when the task is cancelled but already received a notification - **fixed** — Fixed inverted condition in the process pool shutdown phase which would cause still-running pooled processes not to be terminated - Dropped support for Python 3.9 - Added a `ttl` parameter to the `anyio.functools.lru_cache` wrapper ([\#1073](https://github.com/agronholm/anyio/pull/1073); PR by @Graeme22) - Widened the type annotations of file I/O streams to accept `IO[bytes]` instead of just `BinaryIO` ([\#1078](https://github.com/agronholm/anyio/issues/1078)) - Fixed `anyio.Path` not being compatible with Python 3.15 due to the removal of `pathlib.Path.is_reserved()` and the addition of `pathlib.Path.__vfspath__()` ([\#1061](https://github.com/agronholm/anyio/issues/1061); PR by @veeceey) - Fixed the `BrokenResourceError` raised by the asyncio `SocketStream` not having the original exception as its cause ([\#1055](https://github.com/agronholm/anyio/issues/1055); PR by @veeceey) - Fixed the `TypeError` raised when using "func" as a parameter name in `pytest.mark.parametrize` when using the pytest plugin ([\#1068](https://github.com/agronholm/anyio/pull/1068); PR by @JohnnyDeuss) - Fixed the pytest plugin not running tests that had the `anyio` marker added programmatically via `pytest_collection_modifyitems` ([\#422](https://github.com/agronholm/anyio/issues/422); PR by @chbndrhnns) - Fixed cancellation exceptions leaking from a `CancelScope` on asyncio when they are contained in an exception group alongside non-cancellation exceptions ([\#1091](https://github.com/agronholm/anyio/issues/1091); PR by @gschaffner) - Fixed `Condition.wait()` not passing on a notification when the task is cancelled but already received a notification - Fixed inverted condition in the process pool shutdown phase which would cause still-running pooled processes not to be terminated ([\#1074](https://github.com/agronholm/anyio/pull/1074); PR by @bysiber) ### 4.12.1 - Date: 2026-01-06 - Version: 4.12.1 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.12.1 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.12.1 - **changed** — Changed all functions currently raising the private NoCurrentAsyncBackend exception to instead raise the public NoEventLoopError exception - **fixed** — Fixed anyio.functools.lru_cache not working with instance methods - Changed all functions currently raising the private `NoCurrentAsyncBackend` exception (since v4.12.0) to instead raise the public `NoEventLoopError` exception ([\#1048](https://github.com/agronholm/anyio/issues/1048)) - Fixed `anyio.functools.lru_cache` not working with instance methods ([\#1042](https://github.com/agronholm/anyio/issues/1042)) ### 4.12.0 - Date: 2025-11-30 - Version: 4.12.0 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.12.0 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.12.0 - **added** — Support for asyncio's task call graphs on Python 3.14 and later when using AnyIO's task groups - **added** — Asynchronous implementation of the functools module - **added** — Support for uvloop=True on Windows via the winloop implementation - **added** — Support for use as a context manager to anyio.lowlevel.RunVar - **added** — __all__ declarations to public submodules such as anyio.lowlevel - **added** — Ability to set the token count of a CapacityLimiter to zero - **added** — Parameters case_sensitive and recurse_symlinks along with support for path-like objects to anyio.Path.glob() and anyio.Path.rglob() - **changed** — Dropped sniffio as a direct dependency and added the get_available_backends() function - **fixed** — Process.stdin.send() not raising ClosedResourceError and BrokenResourceError on asyncio - **fixed** — Process.stdin.send() not checkpointing before writing data on asyncio - **fixed** — Race condition where cancelling a Future from BlockingPortal.start_task_soon() would sometimes not cancel the async function - **fixed** — Pytest plugin causing breakage with older versions of pytest - **fixed** — RuntimeError: Set changed size during iteration while shutting down the process pool when using the asyncio backend - Added support for asyncio's [task call graphs](https://docs.python.org/3/library/asyncio-graph.html) on Python 3.14 and later when using AnyIO's task groups ([\#1025](https://github.com/agronholm/anyio/pull/1025)) - Added an asynchronous implementation of the `functools` module ([\#1001](https://github.com/agronholm/anyio/pull/1001)) - Added support for `uvloop=True` on Windows via the [winloop](https://github.com/Vizonex/Winloop) implementation ([\#960](https://github.com/agronholm/anyio/pull/960); PR by @Vizonex) - Added support for use as a context manager to `anyio.lowlevel.RunVar` ([\#1003](https://github.com/agronholm/anyio/pull/1003)) - Added `__all__` declarations to public submodules (`anyio.lowlevel` etc.) ([\#1009](https://github.com/agronholm/anyio/pull/1009)) - Added the ability to set the token count of a `CapacityLimiter` to zero ([\#1019](https://github.com/agronholm/anyio/pull/1019); requires Python 3.10 or later when using Trio) - Added parameters `case_sensitive` and `recurse_symlinks` along with support for path-like objects to `anyio.Path.glob()` and `anyio.Path.rglob()` ([\#1033](https://github.com/agronholm/anyio/pull/1033); PR by @northisup) - Dropped `sniffio` as a direct dependency and added the `get_available_backends()` function ([\#1021](https://github.com/agronholm/anyio/pull/1021)) - Fixed `Process.stdin.send()` not raising `ClosedResourceError` and `BrokenResourceError` on asyncio. Previously, a non-AnyIO exception was raised in such cases ([\#671](https://github.com/agronholm/anyio/issues/671); PR by @gschaffner) - Fixed `Process.stdin.send()` not checkpointing before writing data on asyncio ([\#1002](https://github.com/agronholm/anyio/issues/1002); PR by @gschaffner) - Fixed a race condition where cancelling a `Future` from `BlockingPortal.start_task_soon()` would sometimes not cancel the async function ([\#1011](https://github.com/agronholm/anyio/issues/1011); PR by @gschaffner) - Fixed the presence of the pytest plugin causing breakage with older versions of pytest (\<= 6.1.2) ([\#1028](https://github.com/agronholm/anyio/issues/1028); PR by @saper) - Fixed a rarely occurring `RuntimeError: Set changed size during iteration` while shutting down the process pool when using the asyncio backend ([\#985](https://github.com/agronholm/anyio/issues/985)) ### 4.11.0 - Date: 2025-09-23 - Version: 4.11.0 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.11.0 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.11.0 - **added** — Support for cancellation reasons through the `reason` parameter to `CancelScope.cancel()` - **changed** — Minimum version of Trio bumped to v0.31.0 - **added** — Ability to enter the event loop from foreign threads by passing the return value of `anyio.lowlevel.current_token()` to `anyio.from_thread.run()` and `anyio.from_thread.run_sync()` as the `token` keyword argument - **added** — Pytest option `anyio_mode = "auto"` to make the pytest plugin automatically handle all async tests - **added** — The `anyio.Condition.wait_for()` method for feature parity with asyncio - **changed** — Default type argument of `anyio.abc.TaskStatus` changed from `Any` to `None` - **fixed** — TCP listener behavior to guarantee the same ephemeral port is used for all socket listeners when `local_port=0` - **fixed** — Inconsistency between Trio and asyncio where a closed TCP stream now raises `ClosedResourceError` instead of `BrokenResourceError` on both backends - Added support for cancellation reasons (the `reason` parameter to `CancelScope.cancel()`) ([\#975](https://github.com/agronholm/anyio/pull/975)) - Bumped the minimum version of Trio to v0.31.0 - Added the ability to enter the event loop from foreign (non-worker) threads by passing the return value of `anyio.lowlevel.current_token()` to `anyio.from_thread.run()` and `anyio.from_thread.run_sync()` as the `token` keyword argument ([\#256](https://github.com/agronholm/anyio/issues/256)) - Added pytest option (`anyio_mode = "auto"`) to make the pytest plugin automatically handle all async tests ([\#971](https://github.com/agronholm/anyio/pull/971)) - Added the `anyio.Condition.wait_for()` method for feature parity with asyncio ([\#974](https://github.com/agronholm/anyio/pull/974)) - Changed the default type argument of `anyio.abc.TaskStatus` from `Any` to `None` ([\#964](https://github.com/agronholm/anyio/pull/964)) - Fixed TCP listener behavior to guarantee the same ephemeral port is used for all socket listeners when `local_port=0` ([\#857](https://github.com/agronholm/anyio/issues/857); PR by @11kkw and @agronholm) - Fixed inconsistency between Trio and asyncio where a TCP stream that previously raised a `BrokenResourceError` on `send()` would still raise `BrokenResourceError` after the stream was closed on asyncio, but `ClosedResourceError` on Trio. They now both raise a `ClosedResourceError` in this scenario. ([\#671](https://github.com/agronholm/anyio/issues/671)) ### 4.10.0 - Date: 2025-08-04 - Version: 4.10.0 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.10.0 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.10.0 - **added** — Add the `feed_data()` method to the `BufferedByteReceiveStream` class to inject data directly into the buffer - **added** — Add class methods `from_socket()` to `SocketListener`, `SocketStream`, `UNIXSocketStream`, `UDPSocket`, `ConnectedUDPSocket`, `UNIXDatagramSocket`, and `ConnectedUNIXDatagramSocket` to wrap existing sockets - **added** — Add a hierarchy of connectable stream classes for transparently connecting to various remote or local endpoints for exchanging bytes or objects - **added** — Add context manager mix-in classes `anyio.ContextManagerMixin` and `anyio.AsyncContextManagerMixin` to help write classes that embed other context managers - **added** — Add the ability to specify the thread name in `start_blocking_portal()` - **added** — Add `anyio.notify_closing` to allow waking `anyio.wait_readable` and `anyio.wait_writable` before closing a socket - **added** — Add a documentation page explaining why one might want to use AnyIO's APIs instead of asyncio's - **changed** — Update the `to_interpreters` module to use the public `concurrent.interpreters` API on Python 3.14 or later - **fixed** — Fix `anyio.Path.copy()` and `anyio.Path.copy_into()` failing on Python 3.14.0a7 - **fixed** — Fix return annotation of `__aexit__` on async context managers to return `bool` when suppressing exceptions or `None` otherwise - **fixed** — Fix rollover boundary check in `SpooledTemporaryFile` so that rollover only occurs when the buffer size exceeds `max_size` - **fixed** — Fix compatibility of `anyio.to_interpreter` with Python 3.14.0b2 - **fixed** — Fix `SyntaxWarning` on Python 3.14 about `return` in `finally` - **fixed** — Fix RunVar name conflicts so that RunVar instances with the same name do not share storage - **deprecated** — Deprecate the `BrokenWorkerIntepreter` exception name in favor of `BrokenWorkerInterpreter` - **fixed** — Fix an edge case in `CapacityLimiter` on asyncio where a cancelled task is subsequently granted a token but fails to notify the next waiting task - Added the `feed_data()` method to the `BufferedByteReceiveStream` class, allowing users to inject data directly into the buffer - Added various class methods to wrap existing sockets as listeners or socket streams: - `SocketListener.from_socket()` - `SocketStream.from_socket()` - `UNIXSocketStream.from_socket()` - `UDPSocket.from_socket()` - `ConnectedUDPSocket.from_socket()` - `UNIXDatagramSocket.from_socket()` - `ConnectedUNIXDatagramSocket.from_socket()` - Added a hierarchy of connectable stream classes for transparently connecting to various remote or local endpoints for exchanging bytes or objects - Added context manager mix-in classes (`anyio.ContextManagerMixin` and `anyio.AsyncContextManagerMixin`) to help write classes that embed other context managers, particularly cancel scopes or task groups ([\#905](https://github.com/agronholm/anyio/pull/905); PR by @agronholm and @tapetersen) - Added the ability to specify the thread name in `start_blocking_portal()` ([\#818](https://github.com/agronholm/anyio/issues/818); PR by @davidbrochart) - Added `anyio.notify_closing` to allow waking `anyio.wait_readable` and `anyio.wait_writable` before closing a socket. Among other things, this prevents an OSError on the `ProactorEventLoop`. ([\#896](https://github.com/agronholm/anyio/pull/896); PR by @graingert) - Incorporated several documentation improvements from the EuroPython 2025 sprint (special thanks to the sprinters: Emmanuel Okedele, Jan Murre, Euxenia Miruna Goia and Christoffer Fjord) - Added a documentation page explaining why one might want to use AnyIO's APIs instead of asyncio's - Updated the `to_interpreters` module to use the public `concurrent.interpreters` API on Python 3.14 or later - Fixed `anyio.Path.copy()` and `anyio.Path.copy_into()` failing on Python 3.14.0a7 - Fixed return annotation of `__aexit__` on async context managers. CMs which can suppress exceptions should return `bool`, or `None` otherwise. ([\#913](https://github.com/agronholm/anyio/pull/913); PR by @Enegg) - Fixed rollover boundary check in `SpooledTemporaryFile` so that rollover only occurs when the buffer size exceeds `max_size` ([\#915](https://github.com/agronholm/anyio/pull/915); PR by @11kkw) - Migrated testing and documentation dependencies from extras to dependency groups - Fixed compatibility of `anyio.to_interpreter` with Python 3.14.0b2 ([\#926](https://github.com/agronholm/anyio/issues/926); PR by @hroncok) - Fixed `SyntaxWarning` on Python 3.14 about `return` in `finally` ([\#816](https://github.com/agronholm/anyio/issues/816)) - Fixed RunVar name conflicts. RunVar instances with the same name should not share storage ([\#880](https://github.com/agronholm/anyio/issues/880); PR by @vimfu) - Renamed the `BrokenWorkerIntepreter` exception to `BrokenWorkerInterpreter`. The old name is available as a deprecated alias. ([\#938](https://github.com/agronholm/anyio/pull/938); PR by @ayussh-verma) - Fixed an edge case in `CapacityLimiter` on asyncio where a task, waiting to acquire a limiter gets cancelled and is subsequently granted a token from the limiter, but before the cancellation is delivered, and then fails to notify the next waiting task ([\#947](https://github.com/agronholm/anyio/issues/947)) ### 4.9.0 - Date: 2025-03-17 - Version: 4.9.0 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.9.0 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.9.0 - **added** — Add async support for temporary file handling - **added** — Add free_tcp_port_factory fixture to the pytest plugin for session-scoped generation of unused TCP port numbers - **added** — Add free_udp_port_factory fixture to the pytest plugin for session-scoped generation of unused UDP port numbers - **added** — Add free_tcp_port fixture to the pytest plugin for function-scoped generation of a free TCP port number - **added** — Add free_udp_port fixture to the pytest plugin for function-scoped generation of a free UDP port number - **added** — Add stdin argument to anyio.run_process() - **added** — Add the info property to anyio.Path on Python 3.14 - **changed** — Change anyio.getaddrinfo() to ignore invalid IPv6 name resolution results when IPv6 support is disabled in Python - **changed** — Change EndOfStream raised from MemoryObjectReceiveStream.receive() to exclude the AttributeError from the exception chain - **fixed** — Fix traceback formatting growing quadratically with level of TaskGroup nesting on asyncio due to exception chaining when raising ExceptionGroups in TaskGroup.__aexit__ - **fixed** — Fix anyio.Path.iterdir() making a blocking call in Python 3.13 - **fixed** — Fix connect_tcp() producing cyclic references in tracebacks when raising exceptions - **fixed** — Fix anyio.to_thread.run_sync() needlessly holding on to references of the context, function, arguments and others until the next work item on asyncio - Added async support for temporary file handling ([\#344](https://github.com/agronholm/anyio/issues/344); PR by @11kkw) - Added 4 new fixtures for the AnyIO `pytest` plugin: - `free_tcp_port_factory`: session scoped fixture returning a callable that generates unused TCP port numbers - `free_udp_port_factory`: session scoped fixture returning a callable that generates unused UDP port numbers - `free_tcp_port`: function scoped fixture that invokes the `free_tcp_port_factory` fixture to generate a free TCP port number - `free_udp_port`: function scoped fixture that invokes the `free_udp_port_factory` fixture to generate a free UDP port number - Added `stdin` argument to `anyio.run_process()` akin to what `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 - Changed `EndOfStream` raised from `MemoryObjectReceiveStream.receive()` to leave out the `AttributeError` from the exception chain which was merely an implementation detail and caused some confusion - Fixed traceback formatting growing quadratically with level of `TaskGroup` nesting on asyncio due to exception chaining when raising `ExceptionGroups` in `TaskGroup.__aexit__` ([\#863](https://github.com/agronholm/anyio/issues/863); PR by @tapetersen) - Fixed `anyio.Path.iterdir()` making a blocking call in Python 3.13 ([\#873](https://github.com/agronholm/anyio/issues/873); PR by @cbornet and @agronholm) - Fixed `connect_tcp()` producing cyclic references in tracebacks when raising exceptions ([\#809](https://github.com/agronholm/anyio/pull/809); PR by @graingert) - Fixed `anyio.to_thread.run_sync()` needlessly holding on to references of the context, function, arguments and others until the next work item on asyncio (PR by @Wankupi) ### 4.8.0 - Date: 2025-01-05 - Version: 4.8.0 - Original notes: https://github.com/agronholm/anyio/releases/tag/4.8.0 - Permalink: https://whatsnew.fyi/product/anyio/releases/4.8.0 - **added** — Added experimental support for running functions in subinterpreters on Python 3.13 and later - **added** — Added support for the copy(), copy_into(), move() and move_into() methods in anyio.Path, available in Python 3.14 - **changed** — Changed TaskGroup on asyncio to always spawn tasks non-eagerly, even if using a task factory created via asyncio.create_eager_task_factory(), to preserve expected Trio-like task scheduling semantics - **changed** — Configure SO_RCVBUF, SO_SNDBUF and TCP_NODELAY on the selector thread waker socket pair to improve the performance of wait_readable() and wait_writable() when using the ProactorEventLoop - **fixed** — Fixed AssertionError when using nest-asyncio - **fixed** — Fixed return type annotation of various context managers' __exit__ method - Added **experimental** support for running functions in subinterpreters on Python 3.13 and later - Added support for the `copy()`, `copy_into()`, `move()` and `move_into()` methods in `anyio.Path`, available in Python 3.14 - Changed `TaskGroup` on asyncio to always spawn tasks non-eagerly, even if using a task factory created via `asyncio.create_eager_task_factory()`, to preserve expected Trio-like task scheduling semantics (PR by @agronholm and @graingert) - Configure `SO_RCVBUF`, `SO_SNDBUF` and `TCP_NODELAY` on the selector thread waker socket pair (this should improve the performance of `wait_readable()` and `wait_writable()` when using the `ProactorEventLoop`) ([\#836](https://github.com/agronholm/anyio/pull/836); PR by @graingert) - Fixed `AssertionError` when using `nest-asyncio` ([\#840](https://github.com/agronholm/anyio/issues/840)) - Fixed return type annotation of various context managers' `__exit__` method ([\#847](https://github.com/agronholm/anyio/issues/847); PR by @Enegg)