github agronholm/anyio 4.15.0

3 hours ago
  • Added support for the newer keyword-only arguments on anyio.Path methods to match the standard library pathlib.Path:

    • follow_symlinks on exists() (Python 3.12+)
    • follow_symlinks on is_dir() (Python 3.13+)
    • follow_symlinks on is_file() (Python 3.13+)
    • follow_symlinks on owner() (Python 3.13+)
    • follow_symlinks on group() (Python 3.13+)
    • newline on read_text() (Python 3.13+)

    (#1286, #1293; PR by @jaideeppyne)

  • Added amap, gather, and as_completed utility functions to simplify common patterns (#1173; PR by @Graeme22)

  • Added --anyio-mode command-line option as an alternative to the anyio_mode ini setting, and fix the pytest plugin's auto mode detection to recognize the mode when set via either mechanism(e.g: pytest_asyncio). (#1242; PR by @EmmanuelNiyonshuti)

  • Added the anyio.Future synchronization primitive which behaves similar to asyncio.Future, allowing tasks to wait for a value (or exception) from another task (#1146; PR by @Vizonex)

  • Added guidance for managing multiple memory object stream producers and consumers with cloned streams (#330; PR by @nightcityblade)

  • Added StapledObjectStream.send_nowait() that delegates to the underlying ObjectSendStream, if it implements it (#1241; PR by @davidbrochart)

  • Added the move_on_at() and fail_at() functions to complement move_on_after() and fail_after()

  • Changed the default name for a task spawned with TaskGroup.create_task(func()) to match the default task name for the analogous task spawned with TaskGroup.start_soon(func) or TaskGroup.start(func) in more situations. Previously, the default name of a TaskGroup.create_task task never included the module name. (The default name for a task spawned with TaskGroup.start_soon or TaskGroup.start typically includes the module name.) (#1234; PR by @gschaffner)

  • Changed the anyio and anyio.abc modules to lazily (much like 810) import the necessary submodules. This is done by parsing the AST of the module and building a lookup table from the if TYPE_CHECKING: block. A fallback mode has been provided for installations where the source code is unavailable (e.g. PyInstaller). (#1169)

  • Fixed free-threading compatibility issues arising from the fact that on Python 3.14 free-threading builds, newly created threads inherit the current context by default, causing AnyIO to behave erroneously in relation to start_blocking_portal() and anyio.to_thread.run_sync() (#1224; PR by @EmmanuelNiyonshuti)

  • Fixed SpooledTemporaryFile.readinto() and readinto1() reading twice before rollover, so the destination buffer was overwritten by the second read and the file position advanced twice, silently losing data (#1215; PR by @c-tonneslan)

  • Added a reason parameter to fail_after (and the new fail_at) allowing for added exception context when raising TimeoutError (#1227; PR by @Graeme22)

  • Fixed the default TaskHandle.name missing part of the task name for tasks started with TaskGroup.start on Trio (#1231; PR by @gschaffner)

  • Fixed anyio.run leaking, or at least, delaying collection of loop and root_task due to the root task being cached in a RunVar. (#1203; PR by @tapetersen)

  • Fixed anyio.Path.with_stem() silently producing a wrong path (e.g. Path(".txt")) instead of raising ValueError when given an empty stem on a path with a non-empty suffix, unlike pathlib.PurePath.with_stem (#1200; PR by @Sanjays2402)

  • Fixed UNIXSocketStream.aclose() raising asyncio.InvalidStateError when a concurrent receive or send operation had just been cancelled on the asyncio backend (#1267; PR by @alloutflo)

  • Fixed the pytest plugin importing the deprecated _pytest.python.CallSpec2 alias, which triggers PytestRemovedIn10Warning on pytest>=9.2 and crashes pytest at startup when filterwarnings = error is configured (#1271; PR by @matthewfeickert)

  • Fixed an asyncio worker thread race that could raise RuntimeError when the event loop closed between checking its state and scheduling the worker result (#1265; PR by @hansu650)

  • Fixed CapacityLimiter on the asyncio backend over-granting tokens when total_tokens was raised while the limiter was over-subscribed (#1223; PR by @zelinewang)

  • Fixed asyncio task groups leaking unawaited coroutines when a custom task constructor fails; default task creation is unaffected (#1274; PR by @dsfaccini)

  • Fixed inconsistencies between Trio and asyncio when target TaskGroup is cancelled before a task created with .start() calls TaskStatus.started()

    • The started task shouldn't get a CancelledError until the first checkpoint after the started() call.
    • A value passed to started() should be available on the TaskHandle and correctly passed back to the caller of start even if cancelled.
    • The CancelledError shouldn't leak out of the TaskGroup.start() call to the calling task.

    (#1197; PR by @tapetersen)

  • Fixed TemporaryDirectory not cleaning up when the host task was cancelled while exiting the context manager, as the cleanup now runs in a shielded cancel scope (#1304; PR by @smurfix)

Don't miss a new anyio release

NewReleases is sending notifications on new releases.