summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2024-05-08 19:31:41 (GMT)
committerGitHub <noreply@github.com>2024-05-08 19:31:41 (GMT)
commitc6680cdc5a7bfe7684af4dba981383cc80c889a8 (patch)
tree14da0a0ae489a14ad30630bfe5380c7788d0a799
parent02d49af21929519f191af33856be53f0ab9e874b (diff)
downloadcpython-c6680cdc5a7bfe7684af4dba981383cc80c889a8.zip
cpython-c6680cdc5a7bfe7684af4dba981383cc80c889a8.tar.gz
cpython-c6680cdc5a7bfe7684af4dba981383cc80c889a8.tar.bz2
[3.13] gh-118772: Allow TypeVars without a default to follow those with a default when constructing aliases (GH-118774) (#118776)
(cherry picked from commit aac6b019fe91e2f9f7a955d4fc4db5d5efd968c9) Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
-rw-r--r--Lib/test/test_typing.py17
-rw-r--r--Lib/typing.py25
-rw-r--r--Misc/NEWS.d/next/Library/2024-05-08-09-21-49.gh-issue-118772.c16E8X.rst2
3 files changed, 34 insertions, 10 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index bd116bb..fff81f7 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -668,6 +668,23 @@ class TypeParameterDefaultsTests(BaseTestCase):
with self.assertRaises(TypeError):
class Y(Generic[*Ts_default, T]): ...
+ def test_allow_default_after_non_default_in_alias(self):
+ T_default = TypeVar('T_default', default=int)
+ T = TypeVar('T')
+ Ts = TypeVarTuple('Ts')
+
+ a1 = Callable[[T_default], T]
+ self.assertEqual(a1.__args__, (T_default, T))
+
+ a2 = dict[T_default, T]
+ self.assertEqual(a2.__args__, (T_default, T))
+
+ a3 = typing.Dict[T_default, T]
+ self.assertEqual(a3.__args__, (T_default, T))
+
+ a4 = Callable[*Ts, T]
+ self.assertEqual(a4.__args__, (*Ts, T))
+
def test_paramspec_specialization(self):
T = TypeVar("T")
P = ParamSpec('P', default=[str, int])
diff --git a/Lib/typing.py b/Lib/typing.py
index 8e61f50..c8649e3 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -257,7 +257,7 @@ def _type_repr(obj):
return repr(obj)
-def _collect_parameters(args):
+def _collect_parameters(args, *, enforce_default_ordering: bool = True):
"""Collect all type variables and parameter specifications in args
in order of first appearance (lexicographic order).
@@ -286,15 +286,16 @@ def _collect_parameters(args):
parameters.append(collected)
elif hasattr(t, '__typing_subst__'):
if t not in parameters:
- if type_var_tuple_encountered and t.has_default():
- raise TypeError('Type parameter with a default'
- ' follows TypeVarTuple')
+ if enforce_default_ordering:
+ if type_var_tuple_encountered and t.has_default():
+ raise TypeError('Type parameter with a default'
+ ' follows TypeVarTuple')
- if t.has_default():
- default_encountered = True
- elif default_encountered:
- raise TypeError(f'Type parameter {t!r} without a default'
- ' follows type parameter with a default')
+ if t.has_default():
+ default_encountered = True
+ elif default_encountered:
+ raise TypeError(f'Type parameter {t!r} without a default'
+ ' follows type parameter with a default')
parameters.append(t)
else:
@@ -1416,7 +1417,11 @@ class _GenericAlias(_BaseGenericAlias, _root=True):
args = (args,)
self.__args__ = tuple(... if a is _TypingEllipsis else
a for a in args)
- self.__parameters__ = _collect_parameters(args)
+ enforce_default_ordering = origin in (Generic, Protocol)
+ self.__parameters__ = _collect_parameters(
+ args,
+ enforce_default_ordering=enforce_default_ordering,
+ )
if not name:
self.__module__ = origin.__module__
diff --git a/Misc/NEWS.d/next/Library/2024-05-08-09-21-49.gh-issue-118772.c16E8X.rst b/Misc/NEWS.d/next/Library/2024-05-08-09-21-49.gh-issue-118772.c16E8X.rst
new file mode 100644
index 0000000..474454b
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-05-08-09-21-49.gh-issue-118772.c16E8X.rst
@@ -0,0 +1,2 @@
+Allow :class:`typing.TypeVar` instances without a default to follow
+instances without a default in some cases. Patch by Jelle Zijlstra.