From f0fd37547abebdd057232a6b821291a17145a13b Mon Sep 17 00:00:00 2001 From: Daverball Date: Tue, 7 May 2024 17:20:18 +0200 Subject: [PATCH 1/3] [3.13] `typing.(Async)ContextManager` adds second type parameter This is in response to: https://github.com/python/cpython/pull/118681 --- stdlib/typing.pyi | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index 4b80397bdd7a..cfe5333ada32 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -428,17 +428,16 @@ class Generator(Iterator[_YieldT_co], Generic[_YieldT_co, _SendT_contra, _Return @property def gi_yieldfrom(self) -> Generator[Any, Any, Any] | None: ... -# NOTE: Technically we would like this to be able to accept a second parameter as well, just -# like it's counterpart in contextlib, however `typing._SpecialGenericAlias` enforces the -# correct number of arguments at runtime, so we would be hiding runtime errors. -@runtime_checkable -class ContextManager(AbstractContextManager[_T_co, bool | None], Protocol[_T_co]): ... +# NOTE: Prior to Python 3.13 these aliases are lacking the second _ExitT_co parameter +if sys.version_info >= (3, 13): + ContextManager = AbstractContextManager + AsyncContextManager = AbstractAsyncContextManager +else: + @runtime_checkable + class ContextManager(AbstractContextManager[_T_co, bool | None], Protocol[_T_co]): ... -# NOTE: Technically we would like this to be able to accept a second parameter as well, just -# like it's counterpart in contextlib, however `typing._SpecialGenericAlias` enforces the -# correct number of arguments at runtime, so we would be hiding runtime errors. -@runtime_checkable -class AsyncContextManager(AbstractAsyncContextManager[_T_co, bool | None], Protocol[_T_co]): ... + @runtime_checkable + class AsyncContextManager(AbstractAsyncContextManager[_T_co, bool | None], Protocol[_T_co]): ... @runtime_checkable class Awaitable(Protocol[_T_co]): From e0fbcdeae2f304b7920a5057a39afb4d2668c998 Mon Sep 17 00:00:00 2001 From: Daverball Date: Tue, 7 May 2024 18:11:21 +0200 Subject: [PATCH 2/3] Re-organizes things as re-exports according to review --- stdlib/typing.pyi | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index cfe5333ada32..e16bf3777b1f 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -8,7 +8,6 @@ import typing_extensions from _collections_abc import dict_items, dict_keys, dict_values from _typeshed import IdentityFunction, ReadableBuffer, SupportsKeysAndGetItem from abc import ABCMeta, abstractmethod -from contextlib import AbstractAsyncContextManager, AbstractContextManager from re import Match as Match, Pattern as Pattern from types import ( BuiltinFunctionType, @@ -24,10 +23,15 @@ from types import ( ) from typing_extensions import Never as _Never, ParamSpec as _ParamSpec -if sys.version_info >= (3, 10): - from types import UnionType if sys.version_info >= (3, 9): from types import GenericAlias +if sys.version_info >= (3, 10): + from types import UnionType +if sys.version_info >= (3, 13): + # NOTE: Starting with Python 3.13 we can just re-export these from contextlib + from contextlib import AbstractAsyncContextManager as AsyncContextManager, AbstractContextManager as ContextManager +else: + from contextlib import AbstractAsyncContextManager, AbstractContextManager __all__ = [ "AbstractSet", @@ -429,10 +433,7 @@ class Generator(Iterator[_YieldT_co], Generic[_YieldT_co, _SendT_contra, _Return def gi_yieldfrom(self) -> Generator[Any, Any, Any] | None: ... # NOTE: Prior to Python 3.13 these aliases are lacking the second _ExitT_co parameter -if sys.version_info >= (3, 13): - ContextManager = AbstractContextManager - AsyncContextManager = AbstractAsyncContextManager -else: +if sys.version_info < (3, 13): @runtime_checkable class ContextManager(AbstractContextManager[_T_co, bool | None], Protocol[_T_co]): ... From bd2c1613a166f533b8a5c0090de8894c6e246136 Mon Sep 17 00:00:00 2001 From: Daverball Date: Tue, 7 May 2024 18:17:49 +0200 Subject: [PATCH 3/3] Moves imports down to the protocol definitions --- stdlib/typing.pyi | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/stdlib/typing.pyi b/stdlib/typing.pyi index e16bf3777b1f..a25d1c3a196c 100644 --- a/stdlib/typing.pyi +++ b/stdlib/typing.pyi @@ -27,11 +27,6 @@ if sys.version_info >= (3, 9): from types import GenericAlias if sys.version_info >= (3, 10): from types import UnionType -if sys.version_info >= (3, 13): - # NOTE: Starting with Python 3.13 we can just re-export these from contextlib - from contextlib import AbstractAsyncContextManager as AsyncContextManager, AbstractContextManager as ContextManager -else: - from contextlib import AbstractAsyncContextManager, AbstractContextManager __all__ = [ "AbstractSet", @@ -433,7 +428,11 @@ class Generator(Iterator[_YieldT_co], Generic[_YieldT_co, _SendT_contra, _Return def gi_yieldfrom(self) -> Generator[Any, Any, Any] | None: ... # NOTE: Prior to Python 3.13 these aliases are lacking the second _ExitT_co parameter -if sys.version_info < (3, 13): +if sys.version_info >= (3, 13): + from contextlib import AbstractAsyncContextManager as AsyncContextManager, AbstractContextManager as ContextManager +else: + from contextlib import AbstractAsyncContextManager, AbstractContextManager + @runtime_checkable class ContextManager(AbstractContextManager[_T_co, bool | None], Protocol[_T_co]): ...