From e9ee8a1ec27dd7578e26ddd05d8b48da3b3d0083 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 10 May 2025 08:30:10 -0700 Subject: [PATCH 1/5] Update PEP 649/749 implementation --- src/test_typing_extensions.py | 5 ++--- src/typing_extensions.py | 30 +++++++++--------------------- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/src/test_typing_extensions.py b/src/test_typing_extensions.py index 333b4867..a7953dc5 100644 --- a/src/test_typing_extensions.py +++ b/src/test_typing_extensions.py @@ -29,7 +29,6 @@ from _typed_dict_test_helper import Foo, FooGeneric, VeryAnnotated from typing_extensions import ( _FORWARD_REF_HAS_CLASS, - _PEP_649_OR_749_IMPLEMENTED, Annotated, Any, AnyStr, @@ -8533,7 +8532,7 @@ def test_stock_annotations_in_module(self): get_annotations(isa.MyClass, format=Format.STRING), {"a": "int", "b": "str"}, ) - mycls = "MyClass" if _PEP_649_OR_749_IMPLEMENTED else "inspect_stock_annotations.MyClass" + mycls = "MyClass" if sys.version_info >= (3, 14) else "inspect_stock_annotations.MyClass" self.assertEqual( get_annotations(isa.function, format=Format.STRING), {"a": "int", "b": "str", "return": mycls}, @@ -8581,7 +8580,7 @@ def test_stock_annotations_on_wrapper(self): get_annotations(wrapped, format=Format.FORWARDREF), {"a": int, "b": str, "return": isa.MyClass}, ) - mycls = "MyClass" if _PEP_649_OR_749_IMPLEMENTED else "inspect_stock_annotations.MyClass" + mycls = "MyClass" if sys.version_info >= (3, 14) else "inspect_stock_annotations.MyClass" self.assertEqual( get_annotations(wrapped, format=Format.STRING), {"a": "int", "b": "str", "return": mycls}, diff --git a/src/typing_extensions.py b/src/typing_extensions.py index cf0427f3..06ee70be 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -3821,27 +3821,15 @@ def __eq__(self, other: object) -> bool: __all__.append("CapsuleType") -# Using this convoluted approach so that this keeps working -# whether we end up using PEP 649 as written, PEP 749, or -# some other variation: in any case, inspect.get_annotations -# will continue to exist and will gain a `format` parameter. -_PEP_649_OR_749_IMPLEMENTED = ( - hasattr(inspect, 'get_annotations') - and inspect.get_annotations.__kwdefaults__ is not None - and "format" in inspect.get_annotations.__kwdefaults__ -) - - -class Format(enum.IntEnum): - VALUE = 1 - VALUE_WITH_FAKE_GLOBALS = 2 - FORWARDREF = 3 - STRING = 4 - - -if _PEP_649_OR_749_IMPLEMENTED: - get_annotations = inspect.get_annotations +if sys.version_info >= (3,14): + from annotationlib import get_annotations, Format else: + class Format(enum.IntEnum): + VALUE = 1 + VALUE_WITH_FAKE_GLOBALS = 2 + FORWARDREF = 3 + STRING = 4 + def get_annotations(obj, *, globals=None, locals=None, eval_str=False, format=Format.VALUE): """Compute the annotations dict for an object. @@ -4122,7 +4110,7 @@ def evaluate_forward_ref( globals=None, locals=None, type_params=None, - format=Format.VALUE, + format=None, _recursive_guard=frozenset(), ): """Evaluate a forward reference as a type hint. From 7d316c7921df128192b50dcaf5a8452d6d88866c Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 10 May 2025 08:39:48 -0700 Subject: [PATCH 2/5] sort annotations --- src/typing_extensions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/typing_extensions.py b/src/typing_extensions.py index 06ee70be..1ab6220d 100644 --- a/src/typing_extensions.py +++ b/src/typing_extensions.py @@ -3822,7 +3822,7 @@ def __eq__(self, other: object) -> bool: if sys.version_info >= (3,14): - from annotationlib import get_annotations, Format + from annotationlib import Format, get_annotations else: class Format(enum.IntEnum): VALUE = 1 From e5ac9abeb554916c6d66d194226469209c5b6916 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 10 May 2025 08:56:29 -0700 Subject: [PATCH 3/5] update docs --- CHANGELOG.md | 5 ++++- doc/index.rst | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfb45718..ba1a6d78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ - Drop support for Python 3.8 (including PyPy-3.8). Patch by [Victorien Plot](https://github.com/Viicos). - Do not attempt to re-export names that have been removed from `typing`, anticipating the removal of `typing.no_type_check_decorator` in Python 3.15. + Patch by Jelle Zijlstra. +- Update `typing_extensions.Format` and `typing_extensions.evaluate_forward_ref` to align + with changes in Python 3.14. Patch by Jelle Zijlstra. +- Fix tests for Python 3.14. Patch by Jelle Zijlstra. New features: @@ -10,7 +14,6 @@ New features: Patch by [Victorien Plot](https://github.com/Viicos). - Add `typing_extensions.Reader` and `typing_extensions.Writer`. Patch by Sebastian Rittau. -- Fix tests for Python 3.14. Patch by Jelle Zijlstra. # Release 4.13.2 (April 10, 2025) diff --git a/doc/index.rst b/doc/index.rst index 325182eb..3fa4349a 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -952,9 +952,19 @@ Enums for the annotations. This format is identical to the return value for the function under earlier versions of Python. + .. attribute:: VALUE_WITH_FAKE_GLOBALS + + Equal to 2. Special value used to signal that an annotate function is being + evaluated in a special environment with fake globals. When passed this + value, annotate functions should either return the same value as for + the :attr:`Format.VALUE` format, or raise :exc:`NotImplementedError` + to signal that they do not support execution in this environment. + This format is only used internally and should not be passed to + the functions in this module. + .. attribute:: FORWARDREF - Equal to 2. When :pep:`649` is implemented, this format will attempt to return the + Equal to 3. When :pep:`649` is implemented, this format will attempt to return the conventional Python values for the annotations. However, if it encounters an undefined name, it dynamically creates a proxy object (a ForwardRef) that substitutes for that value in the expression. @@ -964,7 +974,7 @@ Enums .. attribute:: STRING - Equal to 3. When :pep:`649` is implemented, this format will produce an annotation + Equal to 4. When :pep:`649` is implemented, this format will produce an annotation dictionary where the values have been replaced by strings containing an approximation of the original source code for the annotation expressions. From 1af039ec4d7fc33df79c605fd8d1e7f96187cda3 Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 10 May 2025 08:57:26 -0700 Subject: [PATCH 4/5] update docs --- doc/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/index.rst b/doc/index.rst index 3fa4349a..9a28f9a3 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -769,7 +769,7 @@ Functions .. versionadded:: 4.2.0 -.. function:: evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=Format.VALUE) +.. function:: evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=None) Evaluate an :py:class:`typing.ForwardRef` as a :py:term:`type hint`. @@ -796,7 +796,7 @@ Functions This parameter must be provided (though it may be an empty tuple) if *owner* is not given and the forward reference does not already have an owner set. *format* specifies the format of the annotation and is a member of - the :class:`Format` enum. + the :class:`Format` enum, defaulting :attr:`Format.VALUE`. .. versionadded:: 4.13.0 From 673fdf54c8e753a28e9dbb6d0fa87f2dc1ed572c Mon Sep 17 00:00:00 2001 From: Jelle Zijlstra Date: Sat, 10 May 2025 12:21:13 -0700 Subject: [PATCH 5/5] Update doc/index.rst Co-authored-by: Alex Waygood --- doc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/index.rst b/doc/index.rst index 9a28f9a3..68402faf 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -796,7 +796,7 @@ Functions This parameter must be provided (though it may be an empty tuple) if *owner* is not given and the forward reference does not already have an owner set. *format* specifies the format of the annotation and is a member of - the :class:`Format` enum, defaulting :attr:`Format.VALUE`. + the :class:`Format` enum, defaulting to :attr:`Format.VALUE`. .. versionadded:: 4.13.0