Skip to content

Commit fa321dc

Browse files
Merge branch 'main' into sentinels
2 parents fe206a4 + f74a56a commit fa321dc

File tree

5 files changed

+91
-71
lines changed

5 files changed

+91
-71
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
# Unreleased
22

33
- Drop support for Python 3.8 (including PyPy-3.8). Patch by [Victorien Plot](https://github.com/Viicos).
4+
- Do not attempt to re-export names that have been removed from `typing`,
5+
anticipating the removal of `typing.no_type_check_decorator` in Python 3.15.
6+
Patch by Jelle Zijlstra.
7+
- Update `typing_extensions.Format` and `typing_extensions.evaluate_forward_ref` to align
8+
with changes in Python 3.14. Patch by Jelle Zijlstra.
9+
- Fix tests for Python 3.14. Patch by Jelle Zijlstra.
410

511
New features:
612

713
- Add support for inline typed dictionaries ([PEP 764](https://peps.python.org/pep-0764/)).
814
Patch by [Victorien Plot](https://github.com/Viicos).
915
- Add `typing_extensions.Reader` and `typing_extensions.Writer`. Patch by
1016
Sebastian Rittau.
11-
- Fix tests for Python 3.14. Patch by Jelle Zijlstra.
1217
- Add support for sentinels ([PEP 661](https://peps.python.org/pep-0661/)).
1318

1419
# Release 4.13.2 (April 10, 2025)

doc/index.rst

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ Functions
769769

770770
.. versionadded:: 4.2.0
771771

772-
.. function:: evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=Format.VALUE)
772+
.. function:: evaluate_forward_ref(forward_ref, *, owner=None, globals=None, locals=None, type_params=None, format=None)
773773

774774
Evaluate an :py:class:`typing.ForwardRef` as a :py:term:`type hint`.
775775

@@ -796,7 +796,7 @@ Functions
796796
This parameter must be provided (though it may be an empty tuple) if *owner*
797797
is not given and the forward reference does not already have an owner set.
798798
*format* specifies the format of the annotation and is a member of
799-
the :class:`Format` enum.
799+
the :class:`Format` enum, defaulting to :attr:`Format.VALUE`.
800800

801801
.. versionadded:: 4.13.0
802802

@@ -952,9 +952,19 @@ Enums
952952
for the annotations. This format is identical to the return value for
953953
the function under earlier versions of Python.
954954

955+
.. attribute:: VALUE_WITH_FAKE_GLOBALS
956+
957+
Equal to 2. Special value used to signal that an annotate function is being
958+
evaluated in a special environment with fake globals. When passed this
959+
value, annotate functions should either return the same value as for
960+
the :attr:`Format.VALUE` format, or raise :exc:`NotImplementedError`
961+
to signal that they do not support execution in this environment.
962+
This format is only used internally and should not be passed to
963+
the functions in this module.
964+
955965
.. attribute:: FORWARDREF
956966

957-
Equal to 2. When :pep:`649` is implemented, this format will attempt to return the
967+
Equal to 3. When :pep:`649` is implemented, this format will attempt to return the
958968
conventional Python values for the annotations. However, if it encounters
959969
an undefined name, it dynamically creates a proxy object (a ForwardRef)
960970
that substitutes for that value in the expression.
@@ -964,7 +974,7 @@ Enums
964974

965975
.. attribute:: STRING
966976

967-
Equal to 3. When :pep:`649` is implemented, this format will produce an annotation
977+
Equal to 4. When :pep:`649` is implemented, this format will produce an annotation
968978
dictionary where the values have been replaced by strings containing
969979
an approximation of the original source code for the annotation expressions.
970980

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ ignore = [
9494
"RUF012",
9595
"RUF022",
9696
"RUF023",
97+
# Ruff doesn't understand the globals() assignment; we test __all__
98+
# directly in test_all_names_in___all__.
99+
"F822",
97100
]
98101

99102
[tool.ruff.lint.per-file-ignores]

src/test_typing_extensions.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
from _typed_dict_test_helper import Foo, FooGeneric, VeryAnnotated
3030
from typing_extensions import (
3131
_FORWARD_REF_HAS_CLASS,
32-
_PEP_649_OR_749_IMPLEMENTED,
3332
Annotated,
3433
Any,
3534
AnyStr,
@@ -6828,6 +6827,15 @@ def test_typing_extensions_defers_when_possible(self):
68286827
getattr(typing_extensions, item),
68296828
getattr(typing, item))
68306829

6830+
def test_alias_names_still_exist(self):
6831+
for name in typing_extensions._typing_names:
6832+
# If this fails, change _typing_names to conditionally add the name
6833+
# depending on the Python version.
6834+
self.assertTrue(
6835+
hasattr(typing_extensions, name),
6836+
f"{name} no longer exists in typing",
6837+
)
6838+
68316839
def test_typing_extensions_compiles_with_opt(self):
68326840
file_path = typing_extensions.__file__
68336841
try:
@@ -8525,7 +8533,7 @@ def test_stock_annotations_in_module(self):
85258533
get_annotations(isa.MyClass, format=Format.STRING),
85268534
{"a": "int", "b": "str"},
85278535
)
8528-
mycls = "MyClass" if _PEP_649_OR_749_IMPLEMENTED else "inspect_stock_annotations.MyClass"
8536+
mycls = "MyClass" if sys.version_info >= (3, 14) else "inspect_stock_annotations.MyClass"
85298537
self.assertEqual(
85308538
get_annotations(isa.function, format=Format.STRING),
85318539
{"a": "int", "b": "str", "return": mycls},
@@ -8573,7 +8581,7 @@ def test_stock_annotations_on_wrapper(self):
85738581
get_annotations(wrapped, format=Format.FORWARDREF),
85748582
{"a": int, "b": str, "return": isa.MyClass},
85758583
)
8576-
mycls = "MyClass" if _PEP_649_OR_749_IMPLEMENTED else "inspect_stock_annotations.MyClass"
8584+
mycls = "MyClass" if sys.version_info >= (3, 14) else "inspect_stock_annotations.MyClass"
85778585
self.assertEqual(
85788586
get_annotations(wrapped, format=Format.STRING),
85798587
{"a": "int", "b": "str", "return": mycls},

src/typing_extensions.py

Lines changed: 57 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -3822,27 +3822,15 @@ def __eq__(self, other: object) -> bool:
38223822
__all__.append("CapsuleType")
38233823

38243824

3825-
# Using this convoluted approach so that this keeps working
3826-
# whether we end up using PEP 649 as written, PEP 749, or
3827-
# some other variation: in any case, inspect.get_annotations
3828-
# will continue to exist and will gain a `format` parameter.
3829-
_PEP_649_OR_749_IMPLEMENTED = (
3830-
hasattr(inspect, 'get_annotations')
3831-
and inspect.get_annotations.__kwdefaults__ is not None
3832-
and "format" in inspect.get_annotations.__kwdefaults__
3833-
)
3834-
3835-
3836-
class Format(enum.IntEnum):
3837-
VALUE = 1
3838-
VALUE_WITH_FAKE_GLOBALS = 2
3839-
FORWARDREF = 3
3840-
STRING = 4
3841-
3842-
3843-
if _PEP_649_OR_749_IMPLEMENTED:
3844-
get_annotations = inspect.get_annotations
3825+
if sys.version_info >= (3,14):
3826+
from annotationlib import Format, get_annotations
38453827
else:
3828+
class Format(enum.IntEnum):
3829+
VALUE = 1
3830+
VALUE_WITH_FAKE_GLOBALS = 2
3831+
FORWARDREF = 3
3832+
STRING = 4
3833+
38463834
def get_annotations(obj, *, globals=None, locals=None, eval_str=False,
38473835
format=Format.VALUE):
38483836
"""Compute the annotations dict for an object.
@@ -4123,7 +4111,7 @@ def evaluate_forward_ref(
41234111
globals=None,
41244112
locals=None,
41254113
type_params=None,
4126-
format=Format.VALUE,
4114+
format=None,
41274115
_recursive_guard=frozenset(),
41284116
):
41294117
"""Evaluate a forward reference as a type hint.
@@ -4260,46 +4248,52 @@ def __getstate__(self):
42604248

42614249

42624250
# Aliases for items that are in typing in all supported versions.
4263-
# Explicitly assign these (rather than using `from typing import *` at the top),
4264-
# so that we get a CI error if one of these is deleted from typing.py
4265-
# in a future version of Python
4266-
AbstractSet = typing.AbstractSet
4267-
Annotated = typing.Annotated
4268-
AnyStr = typing.AnyStr
4269-
BinaryIO = typing.BinaryIO
4270-
Callable = typing.Callable
4271-
Collection = typing.Collection
4272-
Container = typing.Container
4273-
Dict = typing.Dict
4274-
ForwardRef = typing.ForwardRef
4275-
FrozenSet = typing.FrozenSet
4251+
# We use hasattr() checks so this library will continue to import on
4252+
# future versions of Python that may remove these names.
4253+
_typing_names = [
4254+
"AbstractSet",
4255+
"AnyStr",
4256+
"BinaryIO",
4257+
"Callable",
4258+
"Collection",
4259+
"Container",
4260+
"Dict",
4261+
"FrozenSet",
4262+
"Hashable",
4263+
"IO",
4264+
"ItemsView",
4265+
"Iterable",
4266+
"Iterator",
4267+
"KeysView",
4268+
"List",
4269+
"Mapping",
4270+
"MappingView",
4271+
"Match",
4272+
"MutableMapping",
4273+
"MutableSequence",
4274+
"MutableSet",
4275+
"Optional",
4276+
"Pattern",
4277+
"Reversible",
4278+
"Sequence",
4279+
"Set",
4280+
"Sized",
4281+
"TextIO",
4282+
"Tuple",
4283+
"Union",
4284+
"ValuesView",
4285+
"cast",
4286+
"no_type_check",
4287+
"no_type_check_decorator",
4288+
# This is private, but it was defined by typing_extensions for a long time
4289+
# and some users rely on it.
4290+
"_AnnotatedAlias",
4291+
]
4292+
globals().update(
4293+
{name: getattr(typing, name) for name in _typing_names if hasattr(typing, name)}
4294+
)
4295+
# These are defined unconditionally because they are used in
4296+
# typing-extensions itself.
42764297
Generic = typing.Generic
4277-
Hashable = typing.Hashable
4278-
IO = typing.IO
4279-
ItemsView = typing.ItemsView
4280-
Iterable = typing.Iterable
4281-
Iterator = typing.Iterator
4282-
KeysView = typing.KeysView
4283-
List = typing.List
4284-
Mapping = typing.Mapping
4285-
MappingView = typing.MappingView
4286-
Match = typing.Match
4287-
MutableMapping = typing.MutableMapping
4288-
MutableSequence = typing.MutableSequence
4289-
MutableSet = typing.MutableSet
4290-
Optional = typing.Optional
4291-
Pattern = typing.Pattern
4292-
Reversible = typing.Reversible
4293-
Sequence = typing.Sequence
4294-
Set = typing.Set
4295-
Sized = typing.Sized
4296-
TextIO = typing.TextIO
4297-
Tuple = typing.Tuple
4298-
Union = typing.Union
4299-
ValuesView = typing.ValuesView
4300-
cast = typing.cast
4301-
no_type_check = typing.no_type_check
4302-
no_type_check_decorator = typing.no_type_check_decorator
4303-
# This is private, but it was defined by typing_extensions for a long time
4304-
# and some users rely on it.
4305-
_AnnotatedAlias = typing._AnnotatedAlias
4298+
ForwardRef = typing.ForwardRef
4299+
Annotated = typing.Annotated

0 commit comments

Comments
 (0)