Skip to content

Commit ec9d12b

Browse files
Rename typing._collect_parameters (#118900)
Unfortunately, released versions of typing_extensions monkeypatch this function without the extra parameter, which makes it so things break badly if current main is used with typing_extensions. Fortunately, the monkeypatching is not needed on Python 3.13, because CPython now implements PEP 696. By renaming the function, we prevent the monkeypatch from breaking typing.py internals. We keep the old name (raising a DeprecationWarning) to help other external users who call it.
1 parent f5c6b99 commit ec9d12b

File tree

2 files changed

+29
-8
lines changed

2 files changed

+29
-8
lines changed

Lib/test/test_typing.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import weakref
4646
import types
4747

48-
from test.support import captured_stderr, cpython_only, infinite_recursion, requires_docstrings
48+
from test.support import captured_stderr, cpython_only, infinite_recursion, requires_docstrings, import_helper
4949
from test.typinganndata import ann_module695, mod_generics_cache, _typed_dict_helper
5050

5151

@@ -6325,6 +6325,8 @@ def test_or(self):
63256325
self.assertEqual(X | "x", Union[X, "x"])
63266326
self.assertEqual("x" | X, Union["x", X])
63276327

6328+
6329+
class InternalsTests(BaseTestCase):
63286330
def test_deprecation_for_no_type_params_passed_to__evaluate(self):
63296331
with self.assertWarnsRegex(
63306332
DeprecationWarning,
@@ -6350,6 +6352,15 @@ def test_deprecation_for_no_type_params_passed_to__evaluate(self):
63506352

63516353
self.assertEqual(cm.filename, __file__)
63526354

6355+
def test_collect_parameters(self):
6356+
typing = import_helper.import_fresh_module("typing")
6357+
with self.assertWarnsRegex(
6358+
DeprecationWarning,
6359+
"The private _collect_parameters function is deprecated"
6360+
) as cm:
6361+
typing._collect_parameters
6362+
self.assertEqual(cm.filename, __file__)
6363+
63536364

63546365
@lru_cache()
63556366
def cached_func(x, y):

Lib/typing.py

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,15 @@ def _type_repr(obj):
256256
return repr(obj)
257257

258258

259-
def _collect_parameters(args, *, enforce_default_ordering: bool = True):
260-
"""Collect all type variables and parameter specifications in args
259+
def _collect_type_parameters(args, *, enforce_default_ordering: bool = True):
260+
"""Collect all type parameters in args
261261
in order of first appearance (lexicographic order).
262262
263263
For example::
264264
265265
>>> P = ParamSpec('P')
266266
>>> T = TypeVar('T')
267-
>>> _collect_parameters((T, Callable[P, T]))
267+
>>> _collect_type_parameters((T, Callable[P, T]))
268268
(~T, ~P)
269269
"""
270270
# required type parameter cannot appear after parameter with default
@@ -280,7 +280,7 @@ def _collect_parameters(args, *, enforce_default_ordering: bool = True):
280280
# `t` might be a tuple, when `ParamSpec` is substituted with
281281
# `[T, int]`, or `[int, *Ts]`, etc.
282282
for x in t:
283-
for collected in _collect_parameters([x]):
283+
for collected in _collect_type_parameters([x]):
284284
if collected not in parameters:
285285
parameters.append(collected)
286286
elif hasattr(t, '__typing_subst__'):
@@ -320,7 +320,7 @@ def _check_generic_specialization(cls, arguments):
320320
if actual_len < expected_len:
321321
# If the parameter at index `actual_len` in the parameters list
322322
# has a default, then all parameters after it must also have
323-
# one, because we validated as much in _collect_parameters().
323+
# one, because we validated as much in _collect_type_parameters().
324324
# That means that no error needs to be raised here, despite
325325
# the number of arguments being passed not matching the number
326326
# of parameters: all parameters that aren't explicitly
@@ -1255,7 +1255,7 @@ def _generic_init_subclass(cls, *args, **kwargs):
12551255
if error:
12561256
raise TypeError("Cannot inherit from plain Generic")
12571257
if '__orig_bases__' in cls.__dict__:
1258-
tvars = _collect_parameters(cls.__orig_bases__)
1258+
tvars = _collect_type_parameters(cls.__orig_bases__)
12591259
# Look for Generic[T1, ..., Tn].
12601260
# If found, tvars must be a subset of it.
12611261
# If not found, tvars is it.
@@ -1417,7 +1417,7 @@ def __init__(self, origin, args, *, inst=True, name=None):
14171417
self.__args__ = tuple(... if a is _TypingEllipsis else
14181418
a for a in args)
14191419
enforce_default_ordering = origin in (Generic, Protocol)
1420-
self.__parameters__ = _collect_parameters(
1420+
self.__parameters__ = _collect_type_parameters(
14211421
args,
14221422
enforce_default_ordering=enforce_default_ordering,
14231423
)
@@ -3770,6 +3770,16 @@ def __getattr__(attr):
37703770
elif attr in {"ContextManager", "AsyncContextManager"}:
37713771
import contextlib
37723772
obj = _alias(getattr(contextlib, f"Abstract{attr}"), 2, name=attr, defaults=(bool | None,))
3773+
elif attr == "_collect_parameters":
3774+
import warnings
3775+
3776+
depr_message = (
3777+
"The private _collect_parameters function is deprecated and will be"
3778+
" removed in a future version of Python. Any use of private functions"
3779+
" is discouraged and may break in the future."
3780+
)
3781+
warnings.warn(depr_message, category=DeprecationWarning, stacklevel=2)
3782+
obj = _collect_type_parameters
37733783
else:
37743784
raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
37753785
globals()[attr] = obj

0 commit comments

Comments
 (0)