From d467f24d0f886b8a76944726eb46bf0e3bb667a8 Mon Sep 17 00:00:00 2001 From: yihong Date: Tue, 21 Oct 2025 03:43:10 +0800 Subject: [PATCH 1/4] gh-133656: Remove unused import and private global in `Lib/zipimport.py` (GH-140325) --- Lib/zipimport.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Lib/zipimport.py b/Lib/zipimport.py index 188c4bca97798d1..340a7e071125046 100644 --- a/Lib/zipimport.py +++ b/Lib/zipimport.py @@ -10,15 +10,12 @@ to Zip archives. """ -#from importlib import _bootstrap_external -#from importlib import _bootstrap # for _verbose_message import _frozen_importlib_external as _bootstrap_external from _frozen_importlib_external import _unpack_uint16, _unpack_uint32, _unpack_uint64 import _frozen_importlib as _bootstrap # for _verbose_message import _imp # for check_hash_based_pycs import _io # for open import marshal # for loads -import sys # for modules import time # for mktime __all__ = ['ZipImportError', 'zipimporter'] @@ -34,8 +31,6 @@ class ZipImportError(ImportError): # _read_directory() cache _zip_directory_cache = {} -_module_type = type(sys) - END_CENTRAL_DIR_SIZE = 22 END_CENTRAL_DIR_SIZE_64 = 56 END_CENTRAL_DIR_LOCATOR_SIZE_64 = 20 From c6be6e453730228053783f3444cb62e1425a3feb Mon Sep 17 00:00:00 2001 From: Christoph Walcher Date: Mon, 20 Oct 2025 21:55:08 +0200 Subject: [PATCH 2/4] gh-138891: fix star-unpack in get_annotations (#138951) --- Lib/annotationlib.py | 22 +++++++++++-------- Lib/test/test_annotationlib.py | 6 +++++ ...-09-15-21-03-11.gh-issue-138891.oZFdtR.rst | 2 ++ 3 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-09-15-21-03-11.gh-issue-138891.oZFdtR.rst diff --git a/Lib/annotationlib.py b/Lib/annotationlib.py index 43e1d51bc4b807b..544e069626d0d96 100644 --- a/Lib/annotationlib.py +++ b/Lib/annotationlib.py @@ -241,15 +241,8 @@ def __forward_code__(self): if self.__code__ is not None: return self.__code__ arg = self.__forward_arg__ - # If we do `def f(*args: *Ts)`, then we'll have `arg = '*Ts'`. - # Unfortunately, this isn't a valid expression on its own, so we - # do the unpacking manually. - if arg.startswith("*"): - arg_to_compile = f"({arg},)[0]" # E.g. (*Ts,)[0] or (*tuple[int, int],)[0] - else: - arg_to_compile = arg try: - self.__code__ = compile(arg_to_compile, "", "eval") + self.__code__ = compile(_rewrite_star_unpack(arg), "", "eval") except SyntaxError: raise SyntaxError(f"Forward reference must be an expression -- got {arg!r}") return self.__code__ @@ -1025,7 +1018,8 @@ def get_annotations( locals = {param.__name__: param for param in type_params} | locals return_value = { - key: value if not isinstance(value, str) else eval(value, globals, locals) + key: value if not isinstance(value, str) + else eval(_rewrite_star_unpack(value), globals, locals) for key, value in ann.items() } return return_value @@ -1062,6 +1056,16 @@ def annotations_to_string(annotations): } +def _rewrite_star_unpack(arg): + """If the given argument annotation expression is a star unpack e.g. `'*Ts'` + rewrite it to a valid expression. + """ + if arg.startswith("*"): + return f"({arg},)[0]" # E.g. (*Ts,)[0] or (*tuple[int, int],)[0] + else: + return arg + + def _get_and_call_annotate(obj, format): """Get the __annotate__ function and call it. diff --git a/Lib/test/test_annotationlib.py b/Lib/test/test_annotationlib.py index a8a8bcec76a4291..2c5bf2b3417344f 100644 --- a/Lib/test/test_annotationlib.py +++ b/Lib/test/test_annotationlib.py @@ -787,6 +787,12 @@ def test_stringized_annotations_in_empty_module(self): self.assertEqual(get_annotations(isa2, eval_str=True), {}) self.assertEqual(get_annotations(isa2, eval_str=False), {}) + def test_stringized_annotations_with_star_unpack(self): + def f(*args: *tuple[int, ...]): ... + self.assertEqual(get_annotations(f, eval_str=True), + {'args': (*tuple[int, ...],)[0]}) + + def test_stringized_annotations_on_wrapper(self): isa = inspect_stringized_annotations wrapped = times_three(isa.function) diff --git a/Misc/NEWS.d/next/Library/2025-09-15-21-03-11.gh-issue-138891.oZFdtR.rst b/Misc/NEWS.d/next/Library/2025-09-15-21-03-11.gh-issue-138891.oZFdtR.rst new file mode 100644 index 000000000000000..f7ecb05d20c241d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-09-15-21-03-11.gh-issue-138891.oZFdtR.rst @@ -0,0 +1,2 @@ +Fix ``SyntaxError`` when ``inspect.get_annotations(f, eval_str=True)`` is +called on a function annotated with a :pep:`646` ``star_expression`` From a752f58d6b628ab4fe6e4263137ec4cc244ff390 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Mon, 20 Oct 2025 21:09:33 +0100 Subject: [PATCH 3/4] [Docs] Add missing note about Required/NotRequired/ReadOnly in get_type_hints() (#139565) Co-authored-by: Jelle Zijlstra --- Doc/library/typing.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index 41f22aa72cdfaf0..e5d116c702ea2ed 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -3354,7 +3354,8 @@ Introspection helpers ``__annotations__`` dictionaries. Annotations on classes appearing earlier in the :term:`method resolution order` always take precedence over annotations on classes appearing later in the method resolution order. - * The function recursively replaces all occurrences of ``Annotated[T, ...]`` + * The function recursively replaces all occurrences of + ``Annotated[T, ...]``, ``Required[T]``, ``NotRequired[T]``, and ``ReadOnly[T]`` with ``T``, unless *include_extras* is set to ``True`` (see :class:`Annotated` for more information). From e09837fcbf39d07c0af51aa936e95c50aed4787c Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 21 Oct 2025 00:10:44 +0300 Subject: [PATCH 4/4] gh-133601: Remove deprecated `typing.no_type_check_decorator` (#133602) --- Doc/deprecations/pending-removal-in-3.15.rst | 2 +- Doc/library/typing.rst | 15 --------- Doc/whatsnew/3.13.rst | 2 +- Doc/whatsnew/3.15.rst | 3 ++ Lib/test/test_typing.py | 31 +------------------ Lib/typing.py | 18 ----------- Misc/NEWS.d/3.13.0a1.rst | 2 +- ...-05-07-22-09-28.gh-issue-133601.9kUL3P.rst | 1 + 8 files changed, 8 insertions(+), 66 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2025-05-07-22-09-28.gh-issue-133601.9kUL3P.rst diff --git a/Doc/deprecations/pending-removal-in-3.15.rst b/Doc/deprecations/pending-removal-in-3.15.rst index 076346be6215690..09cbd6f01a0580f 100644 --- a/Doc/deprecations/pending-removal-in-3.15.rst +++ b/Doc/deprecations/pending-removal-in-3.15.rst @@ -92,7 +92,7 @@ Pending removal in Python 3.15 Use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})`` to create a TypedDict with zero field. - * The :func:`typing.no_type_check_decorator` decorator function + * The :func:`!typing.no_type_check_decorator` decorator function has been deprecated since Python 3.13. After eight years in the :mod:`typing` module, it has yet to be supported by any major type checker. diff --git a/Doc/library/typing.rst b/Doc/library/typing.rst index e5d116c702ea2ed..58f3a8ecd7c2e0c 100644 --- a/Doc/library/typing.rst +++ b/Doc/library/typing.rst @@ -3258,17 +3258,6 @@ Functions and decorators ``@no_type_check`` mutates the decorated object in place. -.. decorator:: no_type_check_decorator - - Decorator to give another decorator the :func:`no_type_check` effect. - - This wraps the decorator with something that wraps the decorated - function in :func:`no_type_check`. - - .. deprecated-removed:: 3.13 3.15 - No type checker ever added support for ``@no_type_check_decorator``. It - is therefore deprecated, and will be removed in Python 3.15. - .. decorator:: override Decorator to indicate that a method in a subclass is intended to override a @@ -4114,10 +4103,6 @@ convenience. This is subject to change, and not all deprecations are listed. - 3.12 - Undecided - :pep:`695` - * - :func:`@typing.no_type_check_decorator ` - - 3.13 - - 3.15 - - :gh:`106309` * - :data:`typing.AnyStr` - 3.13 - 3.18 diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 499f6f0ff4eaca2..dc105156f33080d 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -1993,7 +1993,7 @@ New Deprecations use ``class TD(TypedDict): pass`` or ``TD = TypedDict("TD", {})``. (Contributed by Alex Waygood in :gh:`105566` and :gh:`105570`.) - * Deprecate the :func:`typing.no_type_check_decorator` decorator function, + * Deprecate the :func:`!typing.no_type_check_decorator` decorator function, to be removed in Python 3.15. After eight years in the :mod:`typing` module, it has yet to be supported by any major type checker. diff --git a/Doc/whatsnew/3.15.rst b/Doc/whatsnew/3.15.rst index 231ae565192efe6..d406b263f174e34 100644 --- a/Doc/whatsnew/3.15.rst +++ b/Doc/whatsnew/3.15.rst @@ -764,6 +764,9 @@ typing :func:`issubclass`, but warnings were not previously emitted if it was merely imported or accessed from the :mod:`!typing` module. +* Deprecated :func:`!typing.no_type_check_decorator` has been removed. + (Contributed by Nikita Sobolev in :gh:`133601`.) + unicodedata ----------- diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index db0501d70e3442a..4076004bc13c85f 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -33,7 +33,7 @@ from typing import is_typeddict, is_protocol from typing import reveal_type from typing import dataclass_transform -from typing import no_type_check, no_type_check_decorator +from typing import no_type_check from typing import Type from typing import NamedTuple, NotRequired, Required, ReadOnly, TypedDict, NoExtraItems from typing import IO, TextIO, BinaryIO @@ -6376,35 +6376,6 @@ class F: for clazz in [C, D, E, F]: self.assertEqual(get_type_hints(clazz), expected_result) - def test_meta_no_type_check(self): - depr_msg = ( - "'typing.no_type_check_decorator' is deprecated " - "and slated for removal in Python 3.15" - ) - with self.assertWarnsRegex(DeprecationWarning, depr_msg): - @no_type_check_decorator - def magic_decorator(func): - return func - - self.assertEqual(magic_decorator.__name__, 'magic_decorator') - - @magic_decorator - def foo(a: 'whatevers') -> {}: - pass - - @magic_decorator - class C: - def foo(a: 'whatevers') -> {}: - pass - - self.assertEqual(foo.__name__, 'foo') - th = get_type_hints(foo) - self.assertEqual(th, {}) - cth = get_type_hints(C.foo) - self.assertEqual(cth, {}) - ith = get_type_hints(C().foo) - self.assertEqual(ith, {}) - class InternalsTests(BaseTestCase): def test_collect_parameters(self): diff --git a/Lib/typing.py b/Lib/typing.py index 25234d2d707dd2d..eb0519986a89523 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -139,7 +139,6 @@ 'Never', 'NewType', 'no_type_check', - 'no_type_check_decorator', 'NoDefault', 'NoExtraItems', 'NoReturn', @@ -2623,23 +2622,6 @@ def no_type_check(arg): return arg -def no_type_check_decorator(decorator): - """Decorator to give another decorator the @no_type_check effect. - - This wraps the decorator with something that wraps the decorated - function in @no_type_check. - """ - import warnings - warnings._deprecated("typing.no_type_check_decorator", remove=(3, 15)) - @functools.wraps(decorator) - def wrapped_decorator(*args, **kwds): - func = decorator(*args, **kwds) - func = no_type_check(func) - return func - - return wrapped_decorator - - def _overload_dummy(*args, **kwds): """Helper for @overload to raise when called.""" raise NotImplementedError( diff --git a/Misc/NEWS.d/3.13.0a1.rst b/Misc/NEWS.d/3.13.0a1.rst index a5f0161e8f591e2..1391d6705757465 100644 --- a/Misc/NEWS.d/3.13.0a1.rst +++ b/Misc/NEWS.d/3.13.0a1.rst @@ -3426,7 +3426,7 @@ This bug was introduced in Python 3.12.0 beta 1. .. nonce: hSlB17 .. section: Library -Deprecate :func:`typing.no_type_check_decorator`. No major type checker ever +Deprecate :func:`!typing.no_type_check_decorator`. No major type checker ever added support for this decorator. Patch by Alex Waygood. .. diff --git a/Misc/NEWS.d/next/Library/2025-05-07-22-09-28.gh-issue-133601.9kUL3P.rst b/Misc/NEWS.d/next/Library/2025-05-07-22-09-28.gh-issue-133601.9kUL3P.rst new file mode 100644 index 000000000000000..62f40aee7aaa4fa --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-05-07-22-09-28.gh-issue-133601.9kUL3P.rst @@ -0,0 +1 @@ +Remove deprecated :func:`!typing.no_type_check_decorator`.