- BACKWARDS INCOMPATIBLE Replaced AnyIO's own
ExceptionGroup
class with the PEP 654BaseExceptionGroup
andExceptionGroup
- BACKWARDS INCOMPATIBLE Changes to cancellation semantics:
- Any exceptions raising out of a task groups are now nested inside an
ExceptionGroup
(orBaseExceptionGroup
if one or moreBaseException
were included) - Fixed task group not raising a cancellation exception on asyncio at exit if no child tasks were spawned and an outer cancellation scope had been cancelled before
- Ensured that exiting a
TaskGroup
always hits a yield point, regardless of whether there are running child tasks to be waited on - On asyncio, cancel scopes will defer cancelling tasks that are scheduled to resume with a finished future
- On asyncio and Python 3.9/3.10, cancel scopes now only suppress cancellation exceptions if the cancel message matches the scope
- Task groups on all backends now raise a single cancellation exception when an outer cancel scope is cancelled, and no exceptions other than cancellation exceptions are raised in the group
- Any exceptions raising out of a task groups are now nested inside an
- BACKWARDS INCOMPATIBLE Changes the pytest plugin to run all tests and fixtures in the same task, allowing fixtures to set context variables for tests and other fixtures
- BACKWARDS INCOMPATIBLE Changed
anyio.Path.relative_to()
andanyio.Path.is_relative_to()
to only accept one argument, as passing multiple arguments is deprecated as of Python 3.12 - BACKWARDS INCOMPATIBLE Dropped support for spawning tasks from old-style coroutine functions (
@asyncio.coroutine
) - BACKWARDS INCOMPATIBLE The
policy
option on theasyncio
backend was changed toloop_factory
to accommodateasyncio.Runner
- Changed
anyio.run()
to useasyncio.Runner
(or a back-ported version of it on Pythons older than 3.11) on theasyncio
backend - Dropped support for Python 3.7
- Added support for Python 3.12
- Bumped minimum version of trio to v0.22
- Added the
anyio.Path.is_junction()
andanyio.Path.walk()
methods - Added
create_unix_datagram_socket
andcreate_connected_unix_datagram_socket
to create UNIX datagram sockets (PR by Jean Hominal) - Fixed
from_thread.run
andfrom_thread.run_sync
not setting sniffio on asyncio. As a result:- Fixed
from_thread.run_sync
failing when used to call sniffio-dependent functions on asyncio - Fixed
from_thread.run
failing when used to call sniffio-dependent functions on asyncio from a thread running trio or curio - Fixed deadlock when using
from_thread.start_blocking_portal(backend="asyncio")
in a thread running trio or curio (PR by Ganden Schaffner)
- Fixed
- Improved type annotations:
- The
item_type
argument ofcreate_memory_object_stream
was deprecated. To indicate the item type handled by the stream, usecreate_memory_object_stream[T_Item]()
instead. Type checking should no longer fail when annotating memory object streams with uninstantiable item types (PR by Ganden Schaffner)
- The
- Added the
CancelScope.cancelled_caught
property which tells users if the cancel scope suppressed a cancellation exception - Fixed
fail_after()
raising an unwarrantedTimeoutError
when the cancel scope was cancelled before reaching its deadline - Fixed
MemoryObjectReceiveStream.receive()
causing the receiving task on asyncio to remain in a cancelled state if the operation was cancelled after an item was queued to be received by the task (but before the task could actually receive the item) - Fixed
TaskGroup.start()
on asyncio not responding to cancellation from the outside - Fixed tasks started from
BlockingPortal
not notifying synchronous listeners (concurrent.futures.wait()
) when they're cancelled - Removed unnecessary extra waiting cycle in
Event.wait()
on asyncio in the case where the event was not yet set - Fixed processes spawned by
anyio.to_process()
being "lost" as unusable to the process pool when processes that have idled over 5 minutes are pruned at part of theto_process.run_sync()
call, leading to increased memory consumption (PR by Anael Gorfinkel)
Changes since 4.0.0rc1:
- Fixed the type annotation of
TaskGroup.start_soon()
to accept any awaitables (already in v3.7.0 but was missing from 4.0.0rc1) - Changed
CancelScope
to also consider the cancellation count (in addition to the cancel message) on asyncio to determine if a cancellation exception should be swallowed on scope exit, to combat issues where third party libraries catch theCancelledError
and raise another, thus erasing the original cancel message - Worked around a CPython bug that caused
TLSListener.handle_handshake_error()
on asyncio to log"NoneType: None"
instead of the error (PR by Ganden Schaffner) - Re-added the
item_type
argument tocreate_memory_object_stream()
(but using it raises a deprecation warning and does nothing with regards to the static types of the returned streams) - Fixed processes spawned by
anyio.to_process()
being "lost" as unusable to the process pool when processes that have idled over 5 minutes are pruned at part of theto_process.run_sync()
call, leading to increased memory consumption (PR by Anael Gorfinkel)