**Full Changelog**: https://github.com/python-trio/trio/compare/v0.22.2...v0.23.0
Headline features
---
- Add type hints. (<https://github.com/python-trio/trio/issues/543>)
Features
---
- When exiting a nursery block, the parent task always waits for child tasks to exit. This wait cannot be cancelled. However, previously, if you tried to cancel it, it *would* inject a `Cancelled` exception, even though it wasn't cancelled. Most users probably never noticed either way, but injecting a `Cancelled` here is not really useful, and in some rare cases caused confusion or problems, so Trio no longer does that. (<https://github.com/python-trio/trio/issues/1457>)
- If called from a thread spawned by `trio.to_thread.run_sync`, `trio.from_thread.run` and `trio.from_thread.run_sync` now reuse the task and cancellation status of the host task; this means that context variables and cancel scopes naturally propagate 'through' threads spawned by Trio. You can also use `trio.from_thread.check_cancelled` to efficiently check for cancellation without reentering the Trio thread. (<https://github.com/python-trio/trio/issues/2392>)
- `trio.lowlevel.start_guest_run` now does a bit more setup of the guest run before it returns to its caller, so that the caller can immediately make calls to `trio.current_time`, `trio.lowlevel.spawn_system_task`, `trio.lowlevel.current_trio_token`, etc. (<https://github.com/python-trio/trio/issues/2696>)
Bugfixes
---
- When a starting function raises before calling `trio.TaskStatus.started`, `trio.Nursery.start` will no longer wrap the exception in an undocumented `ExceptionGroup`. Previously, `trio.Nursery.start` would incorrectly raise an `ExceptionGroup` containing it when using ``trio.run(..., strict_exception_groups=True)``. (<https://github.com/python-trio/trio/issues/2611>)
Deprecations and removals
---
- To better reflect the underlying thread handling semantics, the keyword argument for `trio.to_thread.run_sync` that was previously called ``cancellable`` is now named ``abandon_on_cancel``. It still does the same thing -- allow the thread to be abandoned if the call to `trio.to_thread.run_sync` is cancelled -- but since we now have other ways to propagate a cancellation without abandoning the thread, "cancellable" has become somewhat of a misnomer. The old ``cancellable`` name is now deprecated. (<https://github.com/python-trio/trio/issues/2841>)
- Deprecated support for ``math.inf`` for the ``backlog`` argument in ``open_tcp_listeners``, making its docstring correct in the fact that only ``TypeError`` is raised if invalid arguments are passed. (<https://github.com/python-trio/trio/issues/2842>)
Removals without deprecations
---
- Drop support for Python3.7 and PyPy3.7/3.8. (<https://github.com/python-trio/trio/issues/2668>)
- Removed special ``MultiError`` traceback handling for IPython. As of [version 8.15](https://ipython.readthedocs.io/en/stable/whatsnew/version8.html#ipython-8-15) `ExceptionGroup` is handled natively. (<https://github.com/python-trio/trio/issues/2702>)
Miscellaneous internal changes
---
- Trio now indicates its presence to `sniffio` using the ``sniffio.thread_local`` interface that is preferred since sniffio v1.3.0. This should be less likely than the previous approach to cause `sniffio.current_async_library` to return incorrect results due to unintended inheritance of contextvars. (<https://github.com/python-trio/trio/issues/2700>)
- On windows, if SIO_BASE_HANDLE failed and SIO_BSP_HANDLE_POLL didn't return a different socket, runtime error will now raise from the OSError that indicated the issue so that in the event it does happen it might help with debugging. (<https://github.com/python-trio/trio/issues/2807>)