Skip to content

Upgrading anyio 3 to 4

Breaking3.7.1 → 4.16.0Breaking10Security3Platform6Deprecated2New57Changed39Fixed157Other4

BreakingUpgrade verdict

9 breaking changes and 6 platform requirement changes and 3 security fixes.

  • Dropped sniffio as a direct dependency and added the get_available_backends() function (\).
  • Renamed the BrokenWorkerIntepreter exception to BrokenWorkerInterpreter.
  • The option for letting a thread keep running after cancellation has a new name; the old name still works but is deprecated.
  • Tasks can no longer be started from old-style coroutine functions.
Top 5 of 20 that need code or config changes

Python requirement changed in 4.13.0: >=3.7 → >=3.10.

Breaking9
Dropped sniffio as a direct dependency and added the get_available_backends() function (\).
sniffioget_available_backends()
Renamed the BrokenWorkerIntepreter exception to BrokenWorkerInterpreter.
BrokenWorkerIntepreterBrokenWorkerInterpreter
Renames the cancellable argument in anyio.to_thread.run_sync() to abandon_on_cancel and deprecates the old parameter name.
anyio.to_thread.run_sync()cancellableabandon_on_cancel
Drops support for spawning tasks from old-style coroutine functions decorated with @asyncio.coroutine.
@asyncio.coroutine
Renames the asyncio backend policy option to loop_factory to accommodate asyncio.Runner.
policyloop_factoryasyncio.Runner
Changes type annotations of TaskGroup.start_soon(), TaskGroup.start() and anyio.from_thread.run() to only accept callables returning coroutine-like objects.
TaskGroup.start_soon()TaskGroup.start()anyio.from_thread.run()
Changes cancellation semantics: exceptions from task groups are nested in ExceptionGroup, and several cancellation behaviors change.
ExceptionGroupBaseExceptionGroupTaskGroup
Changes anyio.Path.relative_to() and anyio.Path.is_relative_to() to only accept one argument.
anyio.Path.relative_to()anyio.Path.is_relative_to()
Changes the pytest plugin to run all tests and fixtures in the same task, allowing fixtures to set context variables.
Security3
AnyIO run_process/open_process ignores extra_groups and can retain parent supplementary groups
AnyIO: TLSStream IDNA 2003 host name encoding enables potential TLS certificate spoofing
AnyIO process-pool workers can block indefinitely on undrained stderr
Platform6
Adds support for Python 3.15.
Drops support for Python 3.9.
Added the ability to set the token count of a CapacityLimiter to zero (\; requires Python 3.10 or later when using Trio).
CapacityLimiter
Drops support for Python 3.8 because issue #698 cannot be resolved without cancel message support.
Drops support for Python 3.7.
Adds support for Python 3.12.
Deprecated2
Deprecates the item_type argument of create_memory_object_stream in favor of generic subscription.
item_typecreate_memory_object_streamcreate_memory_object_stream[T_Item]()
Re-adds the item_type argument to create_memory_object_stream(), which now raises a deprecation warning and has no effect on static types.
create_memory_object_stream()item_type

Generated by DepDelta from published Python source. Not mixed with prose notes.

  • removed: export ExceptionGroup
  • removed: export create_blocking_portal
  • removed: export create_capacity_limiter
  • removed: export create_condition
  • removed: export create_event
  • removed: export create_lock
  • removed: export create_semaphore
  • removed: export current_default_worker_thread_limiter
  • removed: export maybe_async
  • removed: export maybe_async_cm
  • removed: export open_cancel_scope
  • removed: export run_async_from_thread
  • removed: export run_sync_from_thread
  • removed: export run_sync_in_worker_thread
  • removed: export start_blocking_portal
  • added: export AsyncContextManagerMixin
  • added: export BrokenWorkerInterpreter
  • added: export ConnectionFailed
  • added: export ContextManagerMixin
  • added: export Future
  • added: export FutureAlreadyFinished
  • added: export FutureCancelled
  • added: export FutureFailed
  • added: export FutureNotFinished
  • added: export NamedTemporaryFile
  • added: export NoEventLoopError
  • added: export ResourceGuard
  • added: export RunFinishedError
  • added: export SpooledTemporaryFile
  • added: export TCPConnectable
  • added: export TaskCancelled
  • added: export TaskFailed
  • added: export TaskHandle
  • added: export TaskNotFinished
  • added: export TemporaryDirectory
  • added: export TemporaryFile
  • added: export UNIXConnectable
  • added: export abc
  • added: export amap
  • added: export as_completed
  • added: export as_connectable
  • added: export create_connected_unix_datagram_socket
  • added: export create_unix_datagram_socket
  • added: export fail_at
  • added: export fix_package_names
  • added: export from_thread
  • added: export functools
  • added: export gather
  • added: export get_available_backends
  • added: export gettempdir
  • added: export gettempdirb
  • added: export install_lazy_importer
  • added: export itertools
  • added: export lowlevel
  • added: export mkdtemp
  • added: export mkstemp
  • added: export move_on_at
  • added: export notify_closing
  • added: export set_deprecated_aliases
  • added: export to_interpreter
  • added: export to_process
  • added: export to_thread
  • added: export wait_readable
  • added: export wait_writable
  • removed: export BlockingPortal
  • removed: export CancelScope
  • removed: export CapacityLimiter
  • removed: export Condition
  • removed: export Event
  • removed: export Lock
  • removed: export Semaphore
  • added: export AnyByteStreamConnectable
  • added: export AsyncBackend
  • added: export ByteStreamConnectable
  • added: export ConnectedUNIXDatagramSocket
  • added: export ObjectStreamConnectable
  • added: export UNIXDatagramPacketType
  • added: export UNIXDatagramSocket
  • added: export fix_package_names
  • added: export install_lazy_importer
  • added: export set_deprecated_aliases
  • removed: function create_blocking_portal() -> BlockingPortal
  • removed: function run_async_from_thread(func: Callable[..., Awaitable[T_Retval]], *args: object) -> T_Retval
  • removed: function run_sync_from_thread(func: Callable[..., T_Retval], *args: object) -> T_Retval
  • removed: method BlockingPortal.spawn_task(func: Callable[..., Awaitable[T_Retval]], *args: object, name: object=…) -> Future[T_Retval] | (func: Callable[..., T_Retval], *args: object, name: object=…) -> Future[T_Retval]
  • removed: variable T_Retval
  • removed: variable T_co
  • changed: function run(func: Callable[..., Awaitable[T_Retval]], *args: object) -> T_Retval → function run(func: Callable[[Unpack[PosArgsT]], Coroutine[Any, Any, T_co]], *args: Unpack[PosArgsT], token: EventLoopToken | None=…) -> T_co
  • changed: function run_sync(func: Callable[..., T_Retval], *args: object) -> T_Retval → function run_sync(func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT], token: EventLoopToken | None=…) -> T_Retval
  • changed: function start_blocking_portal(backend: str=…, backend_options: dict[str, Any] | None=…) -> Generator[BlockingPortal, Any, None] → function start_blocking_portal(backend: str=…, backend_options: dict[str, Any] | None=…, *, name: str | None=…) -> Generator[BlockingPortal, Any, None]
  • changed: method BlockingPortal.call(func: Callable[..., Awaitable[T_Retval]], *args: object) -> T_Retval | (func: Callable[..., T_Retval], *args: object) -> T_Retval → method BlockingPortal.call(func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], *args: Unpack[PosArgsT]) -> T_Retval | (func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT]) -> T_Retval
  • changed: method BlockingPortal.start_task(func: Callable[..., Awaitable[Any]], *args: object, name: object=…) -> tuple[Future[Any], Any] → method BlockingPortal.start_task(func: Callable[..., Awaitable[T_Retval]], *args: object, name: object=…) -> tuple[Future[T_Retval], Any]
  • changed: method BlockingPortal.start_task_soon(func: Callable[..., Awaitable[T_Retval]], *args: object, name: object=…) -> Future[T_Retval] | (func: Callable[..., T_Retval], *args: object, name: object=…) -> Future[T_Retval] → method BlockingPortal.start_task_soon(func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], *args: Unpack[PosArgsT], name: object=…) -> Future[T_Retval] | (func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT], name: object=…) -> Future[T_Retval]
  • changed: method BlockingPortal.wrap_async_context_manager(cm: AsyncContextManager[T_co]) -> ContextManager[T_co] → method BlockingPortal.wrap_async_context_manager(cm: AbstractAsyncContextManager[T_co]) -> AbstractContextManager[T_co]
  • added: async method BlockingPortal.call_async(func: Callable[[Unpack[PosArgsT]], Awaitable[T_Retval]], *args: Unpack[PosArgsT], abandon_on_cancel: bool=…) -> T_Retval | (func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT], abandon_on_cancel: bool=…) -> T_Retval
  • added: class BlockingPortalProvider
  • added: field BlockingPortalProvider.backend: str
  • added: field BlockingPortalProvider.backend_options: dict[str, Any] | None
  • added: function check_cancelled() -> None
  • added: async function reduce(function: Callable[[T, S], Awaitable[T]], iterable: Iterable[S] | AsyncIterable[S], /, initial: T) -> T | (function: Callable[[T, T], Awaitable[T]], iterable: Iterable[T] | AsyncIterable[T], /) -> T
  • added: class AsyncCacheInfo(NamedTuple)
  • added: class AsyncCacheParameters(TypedDict)
  • added: class AsyncLRUCacheWrapper(Generic[P, T])
  • added: constructor AsyncLRUCacheWrapper(func: Callable[P, Awaitable[T]], maxsize: int | None, typed: bool, always_checkpoint: bool, ttl: int | None)
  • added: field AsyncCacheInfo.currsize: int
  • added: field AsyncCacheInfo.hits: int
  • added: field AsyncCacheInfo.maxsize: int | None
  • added: field AsyncCacheInfo.misses: int
  • added: field AsyncCacheInfo.ttl: int | None
  • added: field AsyncCacheParameters.always_checkpoint: bool
  • added: field AsyncCacheParameters.maxsize: int | None
  • added: field AsyncCacheParameters.ttl: int | None
  • added: field AsyncCacheParameters.typed: bool
  • added: function cache(func: Callable[P, Coroutine[Any, Any, T]], /) -> AsyncLRUCacheWrapper[P, T] | (func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]
  • added: function lru_cache(*, maxsize: int | None=…, typed: bool=…, always_checkpoint: bool=…, ttl: int | None=…) -> _LRUCacheWrapper | (func: Callable[P, Coroutine[Any, Any, T]], /) -> AsyncLRUCacheWrapper[P, T] | (func: Callable[..., T], /) -> functools._lru_cache_wrapper[T]
  • added: method AsyncLRUCacheWrapper.cache_clear() -> None
  • added: method AsyncLRUCacheWrapper.cache_info() -> AsyncCacheInfo
  • added: method AsyncLRUCacheWrapper.cache_parameters() -> AsyncCacheParameters
  • added: async function accumulate(iterable: Iterable[T] | AsyncIterable[T], function: Callable[[T, T], Awaitable[T]]=…, *, initial: T | None=…) -> AsyncGenerator[T, None]
  • added: async function batched(iterable: Iterable[T] | AsyncIterable[T], n: int, *, strict: bool=…) -> AsyncGenerator[tuple[T, ...], None]
  • added: async function combinations(iterable: Iterable[T] | AsyncIterable[T], r: int) -> AsyncGenerator[tuple[T, ...], None]
  • added: async function combinations_with_replacement(iterable: Iterable[T] | AsyncIterable[T], r: int) -> AsyncGenerator[tuple[T, ...], None]
  • added: async function compress(data: Iterable[T] | AsyncIterable[T], selectors: Iterable[object] | AsyncIterable[object]) -> AsyncGenerator[T, None]
  • added: async function count(start: int=…, step: int=…) -> AsyncGenerator[int, None]
  • added: async function cycle(iterable: Iterable[T] | AsyncIterable[T]) -> AsyncGenerator[T, None]
  • added: async function dropwhile(predicate: Callable[[T], Awaitable[object]], iterable: Iterable[T] | AsyncIterable[T]) -> AsyncGenerator[T, None]
  • added: async function filterfalse(predicate: Callable[[T], Awaitable[object]], iterable: Iterable[T] | AsyncIterable[T]) -> AsyncGenerator[T, None]
  • added: async function pairwise(iterable: Iterable[T] | AsyncIterable[T]) -> AsyncGenerator[tuple[T, T], None]
  • added: async function permutations(iterable: Iterable[T] | AsyncIterable[T], r: int | None=…) -> AsyncGenerator[tuple[T, ...], None]
  • added: async function product(*iterables: Iterable[T] | AsyncIterable[T], repeat: int=…) -> AsyncGenerator[tuple[T, ...], None]
  • added: async function repeat(element: T, times: int | None=…) -> AsyncGenerator[T, None]
  • added: async function starmap(function: Callable[..., Awaitable[R]], iterable: Iterable[Iterable[object] | AsyncIterable[object]] | AsyncIterable[Iterable[object] | AsyncIterable[object]]) -> AsyncGenerator[R, None]
  • added: async function takewhile(predicate: Callable[[T], Awaitable[object]], iterable: Iterable[T] | AsyncIterable[T]) -> AsyncGenerator[T, None]
  • added: async function zip_longest(*iterables: Iterable[object] | AsyncIterable[object], fillvalue: object=…) -> AsyncGenerator[tuple[object, ...], None]
  • added: async method Chain.from_iterable(iterables: Iterable[Iterable[T] | AsyncIterable[T]] | AsyncIterable[Iterable[T] | AsyncIterable[T]]) -> AsyncGenerator[T, None]
  • added: class Chain
  • added: function groupby(iterable: Iterable[T] | AsyncIterable[T]) -> AsyncGenerator[tuple[T, list[T]], None] | (iterable: Iterable[T] | AsyncIterable[T], key: Callable[[T], Awaitable[R]]) -> AsyncGenerator[tuple[R, list[T]], None]
  • added: function islice(iterable: Iterable[T] | AsyncIterable[T], stop: int | None, /) -> AsyncGenerator[T, None] | (iterable: Iterable[T] | AsyncIterable[T], start: int | None, stop: int | None, step: int | None=…, /) -> AsyncGenerator[T, None]
  • added: function tee(iterable: Iterable[T] | AsyncIterable[T], n: int=…) -> tuple[AsyncIterator[T], ...]
  • removed: variable D
  • removed: variable T
  • changed: function current_token() -> object → function current_token() -> EventLoopToken
  • added: class EventLoopToken
  • added: field EventLoopToken.backend_class: type[AsyncBackend]
  • added: field EventLoopToken.native_token: object
  • changed: function get_runner(backend_name: str, backend_options: dict[str, Any]) -> Generator[TestRunner, object, None] → function get_runner(backend_name: str, backend_options: dict[str, Any]) -> Iterator[TestRunner]
  • changed: function pytest_configure(config: Any) -> None → function pytest_configure(config: pytest.Config) -> None
  • changed: function pytest_fixture_setup(fixturedef: Any, request: Any) -> None → function pytest_fixture_setup(fixturedef: Any, request: Any) -> Generator[Any]
  • changed: function pytest_pycollect_makeitem(collector: Any, name: Any, obj: Any) -> None → function pytest_pycollect_makeitem(collector: pytest.Module | pytest.Class, name: str, obj: object) -> None
  • added: class FreePortFactory
  • added: constructor FreePortFactory(kind: socket.SocketKind) -> None
  • added: function free_tcp_port(free_tcp_port_factory: Callable[[], int]) -> int
  • added: function free_tcp_port_factory() -> FreePortFactory
  • added: function free_udp_port(free_udp_port_factory: Callable[[], int]) -> int
  • added: function free_udp_port_factory() -> FreePortFactory
  • added: function pytest_addoption(parser: pytest.Parser) -> None
  • added: function pytest_collection_finish(session: pytest.Session) -> None
  • added: property FreePortFactory.kind -> socket.SocketKind
  • added: async method BufferedByteStream.send(item: bytes) -> None
  • added: async method BufferedByteStream.send_eof() -> None
  • added: async method BufferedConnectable.connect() -> BufferedByteStream
  • added: class BufferedByteStream(BufferedByteReceiveStream, ByteStream)
  • added: class BufferedConnectable(ByteStreamConnectable)
  • added: constructor BufferedByteStream(stream: AnyByteStream)
  • added: constructor BufferedConnectable(connectable: AnyByteStreamConnectable)
  • added: method BufferedByteReceiveStream.feed_data(data: Iterable[SupportsIndex], /) -> None
  • changed: field FileStreamAttribute.file: BinaryIO → field FileStreamAttribute.file: IO[bytes]
  • removed: class MemoryObjectStreamState(Generic[T_Item])
  • removed: field MemoryObjectStreamState.buffer: deque[T_Item]
  • removed: field MemoryObjectStreamState.max_buffer_size: float
  • removed: field MemoryObjectStreamState.open_receive_channels: int
  • removed: field MemoryObjectStreamState.open_send_channels: int
  • removed: field MemoryObjectStreamState.waiting_receivers: OrderedDict[Event, list[T_Item]]
  • removed: field MemoryObjectStreamState.waiting_senders: OrderedDict[Event, T_Item]
  • removed: method MemoryObjectStreamState.statistics() -> MemoryObjectStreamStatistics
  • removed: variable T_Item
  • removed: variable T_co
  • removed: variable T_contra
  • changed: class MemoryObjectReceiveStream(Generic[T_co], ObjectReceiveStream[T_co]) → class MemoryObjectReceiveStream(ObjectReceiveStream[T_co], Generic[T_co])
  • changed: class MemoryObjectSendStream(Generic[T_contra], ObjectSendStream[T_contra]) → class MemoryObjectSendStream(ObjectSendStream[T_contra], Generic[T_contra])
  • changed: method MemoryObjectSendStream.send_nowait(item: T_contra) -> DeprecatedAwaitable → method MemoryObjectSendStream.send_nowait(item: T_contra) -> None
  • removed: variable T_Item
  • removed: variable T_Stream
  • changed: class MultiListener(Generic[T_Stream], Listener[T_Stream]) → class MultiListener(Listener[T_Stream], Generic[T_Stream])
  • changed: class StapledObjectStream(Generic[T_Item], ObjectStream[T_Item]) → class StapledObjectStream(ObjectStream[T_Item], Generic[T_Item])
  • added: method StapledObjectStream.send_nowait(item: T_Item) -> None
  • added: async method TextConnectable.connect() -> TextStream
  • added: class TextConnectable(ObjectStreamConnectable[str])
  • added: constructor TextConnectable(connectable: AnyByteStreamConnectable)
  • removed: variable T_Retval
  • changed: field TLSAttribute.peer_certificate: dict[str, str | _PCTRTTT | _PCTRTT] | None → field TLSAttribute.peer_certificate: None | dict[str, str | _PCTRTTT | _PCTRTT]
  • added: async method TLSConnectable.connect() -> TLSStream
  • added: class TLSConnectable(ByteStreamConnectable)
  • added: constructor TLSConnectable(connectable: AnyByteStreamConnectable, *, hostname: str | None=…, ssl_context: ssl.SSLContext | None=…, standard_compatible: bool=…) -> None
  • added: async function run_sync(func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT], limiter: CapacityLimiter | None=…) -> T_Retval
  • added: function current_default_interpreter_limiter() -> CapacityLimiter
  • removed: variable T_Retval
  • removed: variable WORKER_MAX_IDLE_TIME
  • changed: async function run_sync(func: Callable[..., T_Retval], *args: object, cancellable: bool=…, limiter: CapacityLimiter | None=…) -> T_Retval → async function run_sync(func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT], cancellable: bool=…, limiter: CapacityLimiter | None=…) -> T_Retval
  • removed: async function run_sync_in_worker_thread(func: Callable[..., T_Retval], *args: object, cancellable: bool=…, limiter: CapacityLimiter | None=…) -> T_Retval
  • removed: function current_default_worker_thread_limiter() -> CapacityLimiter
  • removed: variable T_Retval
  • changed: async function run_sync(func: Callable[..., T_Retval], *args: object, cancellable: bool=…, limiter: CapacityLimiter | None=…) -> T_Retval → async function run_sync(func: Callable[[Unpack[PosArgsT]], T_Retval], *args: Unpack[PosArgsT], abandon_on_cancel: bool=…, cancellable: bool | None=…, limiter: CapacityLimiter | None=…) -> T_Retval