From 8658a0ee89ba548dd37f925945b1aab8cba1ffb0 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 9 Aug 2025 15:17:48 +0400 Subject: [PATCH 1/2] Refine version_info checks --- src/typing_extensions.py | 100 +++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 31 deletions(-) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index efa09d55..91c76817 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -14,7 +14,8 @@ import typing import warnings -if sys.version_info >= (3, 14): +# Breakpoint: https://github.com/python/cpython/pull/119891 +if sys.version_info >= (3, 14, 0, "alpha", 1): import annotationlib __all__ = [ @@ -151,6 +152,7 @@ # for backward compatibility PEP_560 = True GenericMeta = type +# Breakpoint: https://github.com/python/cpython/pull/116129 _PEP_696_IMPLEMENTED = sys.version_info >= (3, 13, 0, "beta") # Added with bpo-45166 to 3.10.1+ and some 3.9 versions @@ -168,7 +170,8 @@ def __repr__(self): _marker = _Sentinel() -if sys.version_info >= (3, 10): +# Breakpoint: https://github.com/python/cpython/pull/27342 +if sys.version_info >= (3, 10, 0, "candidate"): def _should_collect_from_parameters(t): return isinstance( t, (typing._GenericAlias, _types.GenericAlias, _types.UnionType) @@ -189,7 +192,8 @@ def _should_collect_from_parameters(t): T_contra = typing.TypeVar('T_contra', contravariant=True) # Ditto contravariant. -if sys.version_info >= (3, 11): +# Breakpoint: https://github.com/python/cpython/pull/31841 +if sys.version_info >= (3, 11, 0, "alpha", 7): from typing import Any else: @@ -277,7 +281,8 @@ def __repr__(self): Final = typing.Final -if sys.version_info >= (3, 11): +# Breakpoint: https://github.com/python/cpython/pull/30530 +if sys.version_info >= (3, 11, 0, "alpha", 4): final = typing.final else: # @final exists in 3.8+, but we backport it for all versions @@ -320,6 +325,7 @@ def IntVar(name): # A Literal bug was fixed in 3.11.0, 3.10.1 and 3.9.8 +# Breakpoint: https://github.com/python/cpython/pull/29334 if sys.version_info >= (3, 10, 1): Literal = typing.Literal else: @@ -480,6 +486,7 @@ def clear_overloads(): TYPE_CHECKING = typing.TYPE_CHECKING +# Breakpoint: https://github.com/python/cpython/pull/118681 if sys.version_info >= (3, 13, 0, "beta"): from typing import AsyncContextManager, AsyncGenerator, ContextManager, Generator else: @@ -590,7 +597,8 @@ def _caller(depth=1, default='__main__'): # `__match_args__` attribute was removed from protocol members in 3.13, # we want to backport this change to older Python versions. -if sys.version_info >= (3, 13): +# Breakpoint: https://github.com/python/cpython/pull/110683 +if sys.version_info >= (3, 13, 0, "alpha", 1): Protocol = typing.Protocol else: def _allow_reckless_class_checks(depth=2): @@ -770,7 +778,8 @@ def __init_subclass__(cls, *args, **kwargs): cls.__init__ = _no_init -if sys.version_info >= (3, 13): +# Breakpoint: https://github.com/python/cpython/pull/113401 +if sys.version_info >= (3, 13, 0, "alpha", 3): runtime_checkable = typing.runtime_checkable else: def runtime_checkable(cls): @@ -830,7 +839,8 @@ def close(self): ... # Our version of runtime-checkable protocols is faster on Python <=3.11 -if sys.version_info >= (3, 12): +# Breakpoint: https://github.com/python/cpython/pull/112717 +if sys.version_info >= (3, 12, 0, "alpha", 3): SupportsInt = typing.SupportsInt SupportsFloat = typing.SupportsFloat SupportsComplex = typing.SupportsComplex @@ -1159,7 +1169,8 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None, mutable_keys.add(annotation_key) readonly_keys.discard(annotation_key) - if sys.version_info >= (3, 14): + # Breakpoint: https://github.com/python/cpython/pull/119891 + if sys.version_info >= (3, 14, 0, "alpha", 1): def __annotate__(format): annos = {} for base in bases: @@ -1249,7 +1260,8 @@ def _create_typeddict( raise TypeError("TypedDict takes either a dict or keyword arguments," " but not both") if kwargs: - if sys.version_info >= (3, 13): + # Breakpoint: https://github.com/python/cpython/pull/104891 + if sys.version_info >= (3, 13, 0, "alpha", 1): raise TypeError("TypedDict takes no keyword arguments") warnings.warn( "The kwargs-based syntax for TypedDict definitions is deprecated " @@ -1458,7 +1470,8 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): hint = typing.get_type_hints( obj, globalns=globalns, localns=localns, include_extras=True ) - if sys.version_info < (3, 11): + # Breakpoint: https://github.com/python/cpython/pull/30304 + if sys.version_info < (3, 11, 0, "alpha", 6): _clean_optional(obj, hint, globalns, localns) if include_extras: return hint @@ -1530,7 +1543,8 @@ def _clean_optional(obj, hints, globalns=None, localns=None): # Python 3.9 has get_origin() and get_args() but those implementations don't support # ParamSpecArgs and ParamSpecKwargs, so only Python 3.10's versions will do. -if sys.version_info[:2] >= (3, 10): +# Breakpoint: https://github.com/python/cpython/pull/25298 +if sys.version_info >= (3, 10, 0, "beta"): get_origin = typing.get_origin get_args = typing.get_args # 3.9 @@ -2096,7 +2110,8 @@ def _concatenate_getitem(self, parameters): # 3.11+; Concatenate does not accept ellipsis in 3.10 -if sys.version_info >= (3, 11): +# Breakpoint: https://github.com/python/cpython/pull/30969 +if sys.version_info >= (3, 11, 0, "beta"): Concatenate = typing.Concatenate # <=3.10 else: @@ -2432,7 +2447,9 @@ def foo(**kwargs: Unpack[Movie]): ... """ -if sys.version_info >= (3, 12): # PEP 692 changed the repr of Unpack[] +# PEP 692 changed the repr of Unpack[] +# Breakpoint: https://github.com/python/cpython/pull/104048 +if sys.version_info >= (3, 12, 0, "beta"): Unpack = typing.Unpack def _is_unpack(obj): @@ -2695,8 +2712,9 @@ def int_or_str(arg: int | str) -> None: raise AssertionError(f"Expected code to be unreachable, but got: {value}") -if sys.version_info >= (3, 12): # 3.12+ - # dataclass_transform exists in 3.11 but lacks the frozen_default parameter +# dataclass_transform exists in 3.11 but lacks the frozen_default parameter +# Breakpoint: https://github.com/python/cpython/pull/99958 +if sys.version_info >= (3, 12, 0, "alpha", 3): # 3.12+ dataclass_transform = typing.dataclass_transform else: # <=3.11 def dataclass_transform( @@ -2827,6 +2845,7 @@ def method(self) -> None: # Python 3.13.3+ contains a fix for the wrapped __new__ +# Breakpoint: https://github.com/python/cpython/pull/132160 if sys.version_info >= (3, 13, 3): deprecated = warnings.deprecated else: @@ -2956,7 +2975,8 @@ def wrapper(*args, **kwargs): return arg(*args, **kwargs) if asyncio.coroutines.iscoroutinefunction(arg): - if sys.version_info >= (3, 12): + # Breakpoint: https://github.com/python/cpython/pull/99247 + if sys.version_info >= (3, 12, 0 , "alpha", 4): wrapper = inspect.markcoroutinefunction(wrapper) else: wrapper._is_coroutine = asyncio.coroutines._is_coroutine @@ -2969,12 +2989,8 @@ def wrapper(*args, **kwargs): f"a class or callable, not {arg!r}" ) -if sys.version_info < (3, 10): - def _is_param_expr(arg): - return arg is ... or isinstance( - arg, (tuple, list, ParamSpec, _ConcatenateGenericAlias) - ) -else: +# Breakpoint: https://github.com/python/cpython/pull/23702 +if sys.version_info >= (3, 10, 0, "alpha", 4): def _is_param_expr(arg): return arg is ... or isinstance( arg, @@ -2986,6 +3002,11 @@ def _is_param_expr(arg): typing._ConcatenateGenericAlias, ), ) +else: + def _is_param_expr(arg): + return arg is ... or isinstance( + arg, (tuple, list, ParamSpec, _ConcatenateGenericAlias) + ) # We have to do some monkey patching to deal with the dual nature of @@ -3045,7 +3066,12 @@ def _check_generic(cls, parameters, elen=_marker): expect_val = f"at least {elen}" - things = "arguments" if sys.version_info >= (3, 10) else "parameters" + # Breakpoint: https://github.com/python/cpython/pull/27515 + things = ( + "arguments" + if sys.version_info >= (3, 10, 0, "candidate") + else "parameters" + ) raise TypeError(f"Too {'many' if alen > elen else 'few'} {things}" f" for {cls}; actual {alen}, expected {expect_val}") else: @@ -3238,6 +3264,7 @@ def _collect_parameters(args): # This was explicitly disallowed in 3.9-3.10, and only half-worked in <=3.8. # On 3.12, we added __orig_bases__ to call-based NamedTuples # On 3.13, we deprecated kwargs-based NamedTuples +# Breakpoint: https://github.com/python/cpython/pull/105609 if sys.version_info >= (3, 13): NamedTuple = typing.NamedTuple else: @@ -3313,7 +3340,8 @@ def __new__(cls, typename, bases, ns): # using add_note() until py312. # Making sure exceptions are raised in the same way # as in "normal" classes seems most important here. - if sys.version_info >= (3, 12): + # Breakpoint: https://github.com/python/cpython/pull/95915 + if sys.version_info >= (3, 12, 0, "alpha", 1): e.add_note(msg) raise else: @@ -3461,7 +3489,8 @@ class Baz(list[str]): ... # NewType is a class on Python 3.10+, making it pickleable # The error message for subclassing instances of NewType was improved on 3.11+ -if sys.version_info >= (3, 11): +# Breakpoint: https://github.com/python/cpython/pull/30268 +if sys.version_info >= (3, 11, 0, "alpha", 7): NewType = typing.NewType else: class NewType: @@ -3513,7 +3542,8 @@ def __repr__(self): def __reduce__(self): return self.__qualname__ - if sys.version_info >= (3, 10): + # Breakpoint: https://github.com/python/cpython/pull/21515 + if sys.version_info >= (3, 10, 0, "alpha", 1): # PEP 604 methods # It doesn't make sense to have these methods on Python <3.10 @@ -3524,11 +3554,13 @@ def __ror__(self, other): return typing.Union[other, self] -if sys.version_info >= (3, 14): +# Breakpoint: https://github.com/python/cpython/pull/124795 +if sys.version_info >= (3, 14, 0, "alpha", 1): TypeAliasType = typing.TypeAliasType # <=3.13 else: - if sys.version_info >= (3, 12): + # Breakpoint: https://github.com/python/cpython/pull/103764 + if sys.version_info >= (3, 12, 0, "beta"): # 3.12-3.13 def _is_unionable(obj): """Corresponds to is_unionable() in unionobject.c in CPython.""" @@ -3723,7 +3755,8 @@ def __init_subclass__(cls, *args, **kwargs): def __call__(self): raise TypeError("Type alias is not callable") - if sys.version_info >= (3, 10): + # Breakpoint: https://github.com/python/cpython/pull/21515 + if sys.version_info >= (3, 10, 0, "alpha", 1): def __or__(self, right): # For forward compatibility with 3.12, reject Unions # that are not accepted by the built-in Union. @@ -3835,15 +3868,19 @@ def __eq__(self, other: object) -> bool: __all__.append("CapsuleType") -if sys.version_info >= (3,14): +if sys.version_info >= (3, 14, 0, "alpha", 3): from annotationlib import Format, get_annotations else: + # Available since Python 3.14.0a3 + # PR: https://github.com/python/cpython/pull/124415 class Format(enum.IntEnum): VALUE = 1 VALUE_WITH_FAKE_GLOBALS = 2 FORWARDREF = 3 STRING = 4 + # Available since Python 3.14.0a1 + # PR: https://github.com/python/cpython/pull/119891 def get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=Format.VALUE): """Compute the annotations dict for an object. @@ -4181,7 +4218,8 @@ def __repr__(self): def __call__(self, *args, **kwargs): raise TypeError(f"{type(self).__name__!r} object is not callable") - if sys.version_info >= (3, 10): + # Breakpoint: https://github.com/python/cpython/pull/21515 + if sys.version_info >= (3, 10, 0, "alpha", 1): def __or__(self, other): return typing.Union[self, other] From ad11dc916fad817962f219f05a0c62e9a3498ec7 Mon Sep 17 00:00:00 2001 From: donBarbos Date: Sat, 9 Aug 2025 20:40:19 +0400 Subject: [PATCH 2/2] leave conditions --- src/typing_extensions.py | 64 +++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 91c76817..435101f9 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -15,7 +15,7 @@ import warnings # Breakpoint: https://github.com/python/cpython/pull/119891 -if sys.version_info >= (3, 14, 0, "alpha", 1): +if sys.version_info >= (3, 14): import annotationlib __all__ = [ @@ -171,7 +171,7 @@ def __repr__(self): # Breakpoint: https://github.com/python/cpython/pull/27342 -if sys.version_info >= (3, 10, 0, "candidate"): +if sys.version_info >= (3, 10): def _should_collect_from_parameters(t): return isinstance( t, (typing._GenericAlias, _types.GenericAlias, _types.UnionType) @@ -193,7 +193,7 @@ def _should_collect_from_parameters(t): # Breakpoint: https://github.com/python/cpython/pull/31841 -if sys.version_info >= (3, 11, 0, "alpha", 7): +if sys.version_info >= (3, 11): from typing import Any else: @@ -282,7 +282,7 @@ def __repr__(self): Final = typing.Final # Breakpoint: https://github.com/python/cpython/pull/30530 -if sys.version_info >= (3, 11, 0, "alpha", 4): +if sys.version_info >= (3, 11): final = typing.final else: # @final exists in 3.8+, but we backport it for all versions @@ -598,7 +598,7 @@ def _caller(depth=1, default='__main__'): # `__match_args__` attribute was removed from protocol members in 3.13, # we want to backport this change to older Python versions. # Breakpoint: https://github.com/python/cpython/pull/110683 -if sys.version_info >= (3, 13, 0, "alpha", 1): +if sys.version_info >= (3, 13): Protocol = typing.Protocol else: def _allow_reckless_class_checks(depth=2): @@ -779,7 +779,7 @@ def __init_subclass__(cls, *args, **kwargs): # Breakpoint: https://github.com/python/cpython/pull/113401 -if sys.version_info >= (3, 13, 0, "alpha", 3): +if sys.version_info >= (3, 13): runtime_checkable = typing.runtime_checkable else: def runtime_checkable(cls): @@ -840,7 +840,7 @@ def close(self): ... # Our version of runtime-checkable protocols is faster on Python <=3.11 # Breakpoint: https://github.com/python/cpython/pull/112717 -if sys.version_info >= (3, 12, 0, "alpha", 3): +if sys.version_info >= (3, 12): SupportsInt = typing.SupportsInt SupportsFloat = typing.SupportsFloat SupportsComplex = typing.SupportsComplex @@ -1170,7 +1170,7 @@ def __new__(cls, name, bases, ns, *, total=True, closed=None, readonly_keys.discard(annotation_key) # Breakpoint: https://github.com/python/cpython/pull/119891 - if sys.version_info >= (3, 14, 0, "alpha", 1): + if sys.version_info >= (3, 14): def __annotate__(format): annos = {} for base in bases: @@ -1261,7 +1261,7 @@ def _create_typeddict( " but not both") if kwargs: # Breakpoint: https://github.com/python/cpython/pull/104891 - if sys.version_info >= (3, 13, 0, "alpha", 1): + if sys.version_info >= (3, 13): raise TypeError("TypedDict takes no keyword arguments") warnings.warn( "The kwargs-based syntax for TypedDict definitions is deprecated " @@ -1471,7 +1471,7 @@ def get_type_hints(obj, globalns=None, localns=None, include_extras=False): obj, globalns=globalns, localns=localns, include_extras=True ) # Breakpoint: https://github.com/python/cpython/pull/30304 - if sys.version_info < (3, 11, 0, "alpha", 6): + if sys.version_info < (3, 11): _clean_optional(obj, hint, globalns, localns) if include_extras: return hint @@ -1544,7 +1544,7 @@ def _clean_optional(obj, hints, globalns=None, localns=None): # Python 3.9 has get_origin() and get_args() but those implementations don't support # ParamSpecArgs and ParamSpecKwargs, so only Python 3.10's versions will do. # Breakpoint: https://github.com/python/cpython/pull/25298 -if sys.version_info >= (3, 10, 0, "beta"): +if sys.version_info >= (3, 10): get_origin = typing.get_origin get_args = typing.get_args # 3.9 @@ -2111,7 +2111,7 @@ def _concatenate_getitem(self, parameters): # 3.11+; Concatenate does not accept ellipsis in 3.10 # Breakpoint: https://github.com/python/cpython/pull/30969 -if sys.version_info >= (3, 11, 0, "beta"): +if sys.version_info >= (3, 11): Concatenate = typing.Concatenate # <=3.10 else: @@ -2449,7 +2449,7 @@ def foo(**kwargs: Unpack[Movie]): ... # PEP 692 changed the repr of Unpack[] # Breakpoint: https://github.com/python/cpython/pull/104048 -if sys.version_info >= (3, 12, 0, "beta"): +if sys.version_info >= (3, 12): Unpack = typing.Unpack def _is_unpack(obj): @@ -2714,7 +2714,7 @@ def int_or_str(arg: int | str) -> None: # dataclass_transform exists in 3.11 but lacks the frozen_default parameter # Breakpoint: https://github.com/python/cpython/pull/99958 -if sys.version_info >= (3, 12, 0, "alpha", 3): # 3.12+ +if sys.version_info >= (3, 12): # 3.12+ dataclass_transform = typing.dataclass_transform else: # <=3.11 def dataclass_transform( @@ -2976,7 +2976,7 @@ def wrapper(*args, **kwargs): if asyncio.coroutines.iscoroutinefunction(arg): # Breakpoint: https://github.com/python/cpython/pull/99247 - if sys.version_info >= (3, 12, 0 , "alpha", 4): + if sys.version_info >= (3, 12): wrapper = inspect.markcoroutinefunction(wrapper) else: wrapper._is_coroutine = asyncio.coroutines._is_coroutine @@ -2990,7 +2990,12 @@ def wrapper(*args, **kwargs): ) # Breakpoint: https://github.com/python/cpython/pull/23702 -if sys.version_info >= (3, 10, 0, "alpha", 4): +if sys.version_info < (3, 10): + def _is_param_expr(arg): + return arg is ... or isinstance( + arg, (tuple, list, ParamSpec, _ConcatenateGenericAlias) + ) +else: def _is_param_expr(arg): return arg is ... or isinstance( arg, @@ -3002,11 +3007,6 @@ def _is_param_expr(arg): typing._ConcatenateGenericAlias, ), ) -else: - def _is_param_expr(arg): - return arg is ... or isinstance( - arg, (tuple, list, ParamSpec, _ConcatenateGenericAlias) - ) # We have to do some monkey patching to deal with the dual nature of @@ -3067,11 +3067,7 @@ def _check_generic(cls, parameters, elen=_marker): expect_val = f"at least {elen}" # Breakpoint: https://github.com/python/cpython/pull/27515 - things = ( - "arguments" - if sys.version_info >= (3, 10, 0, "candidate") - else "parameters" - ) + things = "arguments" if sys.version_info >= (3, 10) else "parameters" raise TypeError(f"Too {'many' if alen > elen else 'few'} {things}" f" for {cls}; actual {alen}, expected {expect_val}") else: @@ -3341,7 +3337,7 @@ def __new__(cls, typename, bases, ns): # Making sure exceptions are raised in the same way # as in "normal" classes seems most important here. # Breakpoint: https://github.com/python/cpython/pull/95915 - if sys.version_info >= (3, 12, 0, "alpha", 1): + if sys.version_info >= (3, 12): e.add_note(msg) raise else: @@ -3490,7 +3486,7 @@ class Baz(list[str]): ... # NewType is a class on Python 3.10+, making it pickleable # The error message for subclassing instances of NewType was improved on 3.11+ # Breakpoint: https://github.com/python/cpython/pull/30268 -if sys.version_info >= (3, 11, 0, "alpha", 7): +if sys.version_info >= (3, 11): NewType = typing.NewType else: class NewType: @@ -3543,7 +3539,7 @@ def __reduce__(self): return self.__qualname__ # Breakpoint: https://github.com/python/cpython/pull/21515 - if sys.version_info >= (3, 10, 0, "alpha", 1): + if sys.version_info >= (3, 10): # PEP 604 methods # It doesn't make sense to have these methods on Python <3.10 @@ -3555,12 +3551,12 @@ def __ror__(self, other): # Breakpoint: https://github.com/python/cpython/pull/124795 -if sys.version_info >= (3, 14, 0, "alpha", 1): +if sys.version_info >= (3, 14): TypeAliasType = typing.TypeAliasType # <=3.13 else: # Breakpoint: https://github.com/python/cpython/pull/103764 - if sys.version_info >= (3, 12, 0, "beta"): + if sys.version_info >= (3, 12): # 3.12-3.13 def _is_unionable(obj): """Corresponds to is_unionable() in unionobject.c in CPython.""" @@ -3756,7 +3752,7 @@ def __call__(self): raise TypeError("Type alias is not callable") # Breakpoint: https://github.com/python/cpython/pull/21515 - if sys.version_info >= (3, 10, 0, "alpha", 1): + if sys.version_info >= (3, 10): def __or__(self, right): # For forward compatibility with 3.12, reject Unions # that are not accepted by the built-in Union. @@ -3868,7 +3864,7 @@ def __eq__(self, other: object) -> bool: __all__.append("CapsuleType") -if sys.version_info >= (3, 14, 0, "alpha", 3): +if sys.version_info >= (3, 14): from annotationlib import Format, get_annotations else: # Available since Python 3.14.0a3 @@ -4219,7 +4215,7 @@ def __call__(self, *args, **kwargs): raise TypeError(f"{type(self).__name__!r} object is not callable") # Breakpoint: https://github.com/python/cpython/pull/21515 - if sys.version_info >= (3, 10, 0, "alpha", 1): + if sys.version_info >= (3, 10): def __or__(self, other): return typing.Union[self, other]