Skip to content

Commit 9b03010

Browse files
AlexWaygoodSonicField
authored andcommitted
pythongh-118418: Deprecate failing to pass a value to the *type_params* parameter of some private typing APIs (python#118695)
1 parent f4dc046 commit 9b03010

File tree

3 files changed

+61
-11
lines changed

3 files changed

+61
-11
lines changed

Lib/test/test_typing.py

+25
Original file line numberDiff line numberDiff line change
@@ -6308,6 +6308,31 @@ def test_or(self):
63086308
self.assertEqual(X | "x", Union[X, "x"])
63096309
self.assertEqual("x" | X, Union["x", X])
63106310

6311+
def test_deprecation_for_no_type_params_passed_to__evaluate(self):
6312+
with self.assertWarnsRegex(
6313+
DeprecationWarning,
6314+
(
6315+
"Failing to pass a value to the 'type_params' parameter "
6316+
"of 'typing._eval_type' is deprecated"
6317+
)
6318+
) as cm:
6319+
self.assertEqual(typing._eval_type(list["int"], globals(), {}), list[int])
6320+
6321+
self.assertEqual(cm.filename, __file__)
6322+
6323+
f = ForwardRef("int")
6324+
6325+
with self.assertWarnsRegex(
6326+
DeprecationWarning,
6327+
(
6328+
"Failing to pass a value to the 'type_params' parameter "
6329+
"of 'typing.ForwardRef._evaluate' is deprecated"
6330+
)
6331+
) as cm:
6332+
self.assertIs(f._evaluate(globals(), {}, recursive_guard=frozenset()), int)
6333+
6334+
self.assertEqual(cm.filename, __file__)
6335+
63116336

63126337
@lru_cache()
63136338
def cached_func(x, y):

Lib/typing.py

+30-11
Original file line numberDiff line numberDiff line change
@@ -437,13 +437,38 @@ def inner(*args, **kwds):
437437
return decorator
438438

439439

440-
def _eval_type(t, globalns, localns, type_params=None, *, recursive_guard=frozenset()):
440+
def _deprecation_warning_for_no_type_params_passed(funcname: str) -> None:
441+
import warnings
442+
443+
depr_message = (
444+
f"Failing to pass a value to the 'type_params' parameter "
445+
f"of {funcname!r} is deprecated, as it leads to incorrect behaviour "
446+
f"when calling {funcname} on a stringified annotation "
447+
f"that references a PEP 695 type parameter. "
448+
f"It will be disallowed in Python 3.15."
449+
)
450+
warnings.warn(depr_message, category=DeprecationWarning, stacklevel=3)
451+
452+
453+
class _Sentinel:
454+
__slots__ = ()
455+
def __repr__(self):
456+
return '<sentinel>'
457+
458+
459+
_sentinel = _Sentinel()
460+
461+
462+
def _eval_type(t, globalns, localns, type_params=_sentinel, *, recursive_guard=frozenset()):
441463
"""Evaluate all forward references in the given type t.
442464
443465
For use of globalns and localns see the docstring for get_type_hints().
444466
recursive_guard is used to prevent infinite recursion with a recursive
445467
ForwardRef.
446468
"""
469+
if type_params is _sentinel:
470+
_deprecation_warning_for_no_type_params_passed("typing._eval_type")
471+
type_params = ()
447472
if isinstance(t, ForwardRef):
448473
return t._evaluate(globalns, localns, type_params, recursive_guard=recursive_guard)
449474
if isinstance(t, (_GenericAlias, GenericAlias, types.UnionType)):
@@ -1018,7 +1043,10 @@ def __init__(self, arg, is_argument=True, module=None, *, is_class=False):
10181043
self.__forward_is_class__ = is_class
10191044
self.__forward_module__ = module
10201045

1021-
def _evaluate(self, globalns, localns, type_params=None, *, recursive_guard):
1046+
def _evaluate(self, globalns, localns, type_params=_sentinel, *, recursive_guard):
1047+
if type_params is _sentinel:
1048+
_deprecation_warning_for_no_type_params_passed("typing.ForwardRef._evaluate")
1049+
type_params = ()
10221050
if self.__forward_arg__ in recursive_guard:
10231051
return self
10241052
if not self.__forward_evaluated__ or localns is not globalns:
@@ -2998,15 +3026,6 @@ def __new__(cls, typename, bases, ns):
29983026
return nm_tpl
29993027

30003028

3001-
class _Sentinel:
3002-
__slots__ = ()
3003-
def __repr__(self):
3004-
return '<sentinel>'
3005-
3006-
3007-
_sentinel = _Sentinel()
3008-
3009-
30103029
def NamedTuple(typename, fields=_sentinel, /, **kwargs):
30113030
"""Typed version of namedtuple.
30123031
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
A :exc:`DeprecationWarning` is now emitted if you fail to pass a value to
2+
the new *type_params* parameter of ``typing._eval_type()`` or
3+
``typing.ForwardRef._evaluate()``. (Using either of these private and
4+
undocumented functions is discouraged to begin with, but failing to pass a
5+
value to the ``type_params`` parameter may lead to incorrect behaviour on
6+
Python 3.12 or newer.)

0 commit comments

Comments
 (0)