Skip to content

Commit 34def64

Browse files
JelleZijlstramiss-islington
authored andcommitted
Rename typing._collect_parameters (pythonGH-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. (cherry picked from commit ec9d12b) Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent 6df4913 commit 34def64

2 files changed

Lines changed: 29 additions & 8 deletions

File tree

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
@@ -257,15 +257,15 @@ def _type_repr(obj):
257257
return repr(obj)
258258

259259

260-
def _collect_parameters(args, *, enforce_default_ordering: bool = True):
261-
"""Collect all type variables and parameter specifications in args
260+
def _collect_type_parameters(args, *, enforce_default_ordering: bool = True):
261+
"""Collect all type parameters in args
262262
in order of first appearance (lexicographic order).
263263
264264
For example::
265265
266266
>>> P = ParamSpec('P')
267267
>>> T = TypeVar('T')
268-
>>> _collect_parameters((T, Callable[P, T]))
268+
>>> _collect_type_parameters((T, Callable[P, T]))
269269
(~T, ~P)
270270
"""
271271
# required type parameter cannot appear after parameter with default
@@ -281,7 +281,7 @@ def _collect_parameters(args, *, enforce_default_ordering: bool = True):
281281
# `t` might be a tuple, when `ParamSpec` is substituted with
282282
# `[T, int]`, or `[int, *Ts]`, etc.
283283
for x in t:
284-
for collected in _collect_parameters([x]):
284+
for collected in _collect_type_parameters([x]):
285285
if collected not in parameters:
286286
parameters.append(collected)
287287
elif hasattr(t, '__typing_subst__'):
@@ -321,7 +321,7 @@ def _check_generic_specialization(cls, arguments):
321321
if actual_len < expected_len:
322322
# If the parameter at index `actual_len` in the parameters list
323323
# has a default, then all parameters after it must also have
324-
# one, because we validated as much in _collect_parameters().
324+
# one, because we validated as much in _collect_type_parameters().
325325
# That means that no error needs to be raised here, despite
326326
# the number of arguments being passed not matching the number
327327
# of parameters: all parameters that aren't explicitly
@@ -1256,7 +1256,7 @@ def _generic_init_subclass(cls, *args, **kwargs):
12561256
if error:
12571257
raise TypeError("Cannot inherit from plain Generic")
12581258
if '__orig_bases__' in cls.__dict__:
1259-
tvars = _collect_parameters(cls.__orig_bases__)
1259+
tvars = _collect_type_parameters(cls.__orig_bases__)
12601260
# Look for Generic[T1, ..., Tn].
12611261
# If found, tvars must be a subset of it.
12621262
# If not found, tvars is it.
@@ -1418,7 +1418,7 @@ def __init__(self, origin, args, *, inst=True, name=None):
14181418
self.__args__ = tuple(... if a is _TypingEllipsis else
14191419
a for a in args)
14201420
enforce_default_ordering = origin in (Generic, Protocol)
1421-
self.__parameters__ = _collect_parameters(
1421+
self.__parameters__ = _collect_type_parameters(
14221422
args,
14231423
enforce_default_ordering=enforce_default_ordering,
14241424
)
@@ -3789,6 +3789,16 @@ def __getattr__(attr):
37893789
elif attr in {"ContextManager", "AsyncContextManager"}:
37903790
import contextlib
37913791
obj = _alias(getattr(contextlib, f"Abstract{attr}"), 2, name=attr, defaults=(bool | None,))
3792+
elif attr == "_collect_parameters":
3793+
import warnings
3794+
3795+
depr_message = (
3796+
"The private _collect_parameters function is deprecated and will be"
3797+
" removed in a future version of Python. Any use of private functions"
3798+
" is discouraged and may break in the future."
3799+
)
3800+
warnings.warn(depr_message, category=DeprecationWarning, stacklevel=2)
3801+
obj = _collect_type_parameters
37923802
else:
37933803
raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
37943804
globals()[attr] = obj

0 commit comments

Comments
 (0)