mirror of
https://github.com/python/cpython.git
synced 2025-09-19 07:00:59 +00:00
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.
This commit is contained in:
parent
f5c6b9977a
commit
ec9d12be96
2 changed files with 29 additions and 8 deletions
|
@ -45,7 +45,7 @@ import typing
|
||||||
import weakref
|
import weakref
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from test.support import captured_stderr, cpython_only, infinite_recursion, requires_docstrings
|
from test.support import captured_stderr, cpython_only, infinite_recursion, requires_docstrings, import_helper
|
||||||
from test.typinganndata import ann_module695, mod_generics_cache, _typed_dict_helper
|
from test.typinganndata import ann_module695, mod_generics_cache, _typed_dict_helper
|
||||||
|
|
||||||
|
|
||||||
|
@ -6325,6 +6325,8 @@ class ForwardRefTests(BaseTestCase):
|
||||||
self.assertEqual(X | "x", Union[X, "x"])
|
self.assertEqual(X | "x", Union[X, "x"])
|
||||||
self.assertEqual("x" | X, Union["x", X])
|
self.assertEqual("x" | X, Union["x", X])
|
||||||
|
|
||||||
|
|
||||||
|
class InternalsTests(BaseTestCase):
|
||||||
def test_deprecation_for_no_type_params_passed_to__evaluate(self):
|
def test_deprecation_for_no_type_params_passed_to__evaluate(self):
|
||||||
with self.assertWarnsRegex(
|
with self.assertWarnsRegex(
|
||||||
DeprecationWarning,
|
DeprecationWarning,
|
||||||
|
@ -6350,6 +6352,15 @@ class ForwardRefTests(BaseTestCase):
|
||||||
|
|
||||||
self.assertEqual(cm.filename, __file__)
|
self.assertEqual(cm.filename, __file__)
|
||||||
|
|
||||||
|
def test_collect_parameters(self):
|
||||||
|
typing = import_helper.import_fresh_module("typing")
|
||||||
|
with self.assertWarnsRegex(
|
||||||
|
DeprecationWarning,
|
||||||
|
"The private _collect_parameters function is deprecated"
|
||||||
|
) as cm:
|
||||||
|
typing._collect_parameters
|
||||||
|
self.assertEqual(cm.filename, __file__)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
def cached_func(x, y):
|
def cached_func(x, y):
|
||||||
|
|
|
@ -256,15 +256,15 @@ def _type_repr(obj):
|
||||||
return repr(obj)
|
return repr(obj)
|
||||||
|
|
||||||
|
|
||||||
def _collect_parameters(args, *, enforce_default_ordering: bool = True):
|
def _collect_type_parameters(args, *, enforce_default_ordering: bool = True):
|
||||||
"""Collect all type variables and parameter specifications in args
|
"""Collect all type parameters in args
|
||||||
in order of first appearance (lexicographic order).
|
in order of first appearance (lexicographic order).
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
>>> P = ParamSpec('P')
|
>>> P = ParamSpec('P')
|
||||||
>>> T = TypeVar('T')
|
>>> T = TypeVar('T')
|
||||||
>>> _collect_parameters((T, Callable[P, T]))
|
>>> _collect_type_parameters((T, Callable[P, T]))
|
||||||
(~T, ~P)
|
(~T, ~P)
|
||||||
"""
|
"""
|
||||||
# required type parameter cannot appear after parameter with default
|
# required type parameter cannot appear after parameter with default
|
||||||
|
@ -280,7 +280,7 @@ def _collect_parameters(args, *, enforce_default_ordering: bool = True):
|
||||||
# `t` might be a tuple, when `ParamSpec` is substituted with
|
# `t` might be a tuple, when `ParamSpec` is substituted with
|
||||||
# `[T, int]`, or `[int, *Ts]`, etc.
|
# `[T, int]`, or `[int, *Ts]`, etc.
|
||||||
for x in t:
|
for x in t:
|
||||||
for collected in _collect_parameters([x]):
|
for collected in _collect_type_parameters([x]):
|
||||||
if collected not in parameters:
|
if collected not in parameters:
|
||||||
parameters.append(collected)
|
parameters.append(collected)
|
||||||
elif hasattr(t, '__typing_subst__'):
|
elif hasattr(t, '__typing_subst__'):
|
||||||
|
@ -320,7 +320,7 @@ def _check_generic_specialization(cls, arguments):
|
||||||
if actual_len < expected_len:
|
if actual_len < expected_len:
|
||||||
# If the parameter at index `actual_len` in the parameters list
|
# If the parameter at index `actual_len` in the parameters list
|
||||||
# has a default, then all parameters after it must also have
|
# has a default, then all parameters after it must also have
|
||||||
# one, because we validated as much in _collect_parameters().
|
# one, because we validated as much in _collect_type_parameters().
|
||||||
# That means that no error needs to be raised here, despite
|
# That means that no error needs to be raised here, despite
|
||||||
# the number of arguments being passed not matching the number
|
# the number of arguments being passed not matching the number
|
||||||
# of parameters: all parameters that aren't explicitly
|
# of parameters: all parameters that aren't explicitly
|
||||||
|
@ -1255,7 +1255,7 @@ def _generic_init_subclass(cls, *args, **kwargs):
|
||||||
if error:
|
if error:
|
||||||
raise TypeError("Cannot inherit from plain Generic")
|
raise TypeError("Cannot inherit from plain Generic")
|
||||||
if '__orig_bases__' in cls.__dict__:
|
if '__orig_bases__' in cls.__dict__:
|
||||||
tvars = _collect_parameters(cls.__orig_bases__)
|
tvars = _collect_type_parameters(cls.__orig_bases__)
|
||||||
# Look for Generic[T1, ..., Tn].
|
# Look for Generic[T1, ..., Tn].
|
||||||
# If found, tvars must be a subset of it.
|
# If found, tvars must be a subset of it.
|
||||||
# If not found, tvars is it.
|
# If not found, tvars is it.
|
||||||
|
@ -1417,7 +1417,7 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
|
||||||
self.__args__ = tuple(... if a is _TypingEllipsis else
|
self.__args__ = tuple(... if a is _TypingEllipsis else
|
||||||
a for a in args)
|
a for a in args)
|
||||||
enforce_default_ordering = origin in (Generic, Protocol)
|
enforce_default_ordering = origin in (Generic, Protocol)
|
||||||
self.__parameters__ = _collect_parameters(
|
self.__parameters__ = _collect_type_parameters(
|
||||||
args,
|
args,
|
||||||
enforce_default_ordering=enforce_default_ordering,
|
enforce_default_ordering=enforce_default_ordering,
|
||||||
)
|
)
|
||||||
|
@ -3770,6 +3770,16 @@ def __getattr__(attr):
|
||||||
elif attr in {"ContextManager", "AsyncContextManager"}:
|
elif attr in {"ContextManager", "AsyncContextManager"}:
|
||||||
import contextlib
|
import contextlib
|
||||||
obj = _alias(getattr(contextlib, f"Abstract{attr}"), 2, name=attr, defaults=(bool | None,))
|
obj = _alias(getattr(contextlib, f"Abstract{attr}"), 2, name=attr, defaults=(bool | None,))
|
||||||
|
elif attr == "_collect_parameters":
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
depr_message = (
|
||||||
|
"The private _collect_parameters function is deprecated and will be"
|
||||||
|
" removed in a future version of Python. Any use of private functions"
|
||||||
|
" is discouraged and may break in the future."
|
||||||
|
)
|
||||||
|
warnings.warn(depr_message, category=DeprecationWarning, stacklevel=2)
|
||||||
|
obj = _collect_type_parameters
|
||||||
else:
|
else:
|
||||||
raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
|
raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
|
||||||
globals()[attr] = obj
|
globals()[attr] = obj
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue