mirror of https://github.com/python/cpython
gh-102615: Use `list` instead of `tuple` in `repr` of paramspec (#102637)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
This commit is contained in:
parent
8647ba4b63
commit
2b5781d659
|
@ -3809,6 +3809,51 @@ class GenericTests(BaseTestCase):
|
|||
self.assertEqual(Y.__qualname__,
|
||||
'GenericTests.test_repr_2.<locals>.Y')
|
||||
|
||||
def test_repr_3(self):
|
||||
T = TypeVar('T')
|
||||
T1 = TypeVar('T1')
|
||||
P = ParamSpec('P')
|
||||
P2 = ParamSpec('P2')
|
||||
Ts = TypeVarTuple('Ts')
|
||||
|
||||
class MyCallable(Generic[P, T]):
|
||||
pass
|
||||
|
||||
class DoubleSpec(Generic[P, P2, T]):
|
||||
pass
|
||||
|
||||
class TsP(Generic[*Ts, P]):
|
||||
pass
|
||||
|
||||
object_to_expected_repr = {
|
||||
MyCallable[P, T]: "MyCallable[~P, ~T]",
|
||||
MyCallable[Concatenate[T1, P], T]: "MyCallable[typing.Concatenate[~T1, ~P], ~T]",
|
||||
MyCallable[[], bool]: "MyCallable[[], bool]",
|
||||
MyCallable[[int], bool]: "MyCallable[[int], bool]",
|
||||
MyCallable[[int, str], bool]: "MyCallable[[int, str], bool]",
|
||||
MyCallable[[int, list[int]], bool]: "MyCallable[[int, list[int]], bool]",
|
||||
MyCallable[Concatenate[*Ts, P], T]: "MyCallable[typing.Concatenate[*Ts, ~P], ~T]",
|
||||
|
||||
DoubleSpec[P2, P, T]: "DoubleSpec[~P2, ~P, ~T]",
|
||||
DoubleSpec[[int], [str], bool]: "DoubleSpec[[int], [str], bool]",
|
||||
DoubleSpec[[int, int], [str, str], bool]: "DoubleSpec[[int, int], [str, str], bool]",
|
||||
|
||||
TsP[*Ts, P]: "TsP[*Ts, ~P]",
|
||||
TsP[int, str, list[int], []]: "TsP[int, str, list[int], []]",
|
||||
TsP[int, [str, list[int]]]: "TsP[int, [str, list[int]]]",
|
||||
|
||||
# These lines are just too long to fit:
|
||||
MyCallable[Concatenate[*Ts, P], int][int, str, [bool, float]]:
|
||||
"MyCallable[[int, str, bool, float], int]",
|
||||
}
|
||||
|
||||
for obj, expected_repr in object_to_expected_repr.items():
|
||||
with self.subTest(obj=obj, expected_repr=expected_repr):
|
||||
self.assertRegex(
|
||||
repr(obj),
|
||||
fr"^{re.escape(MyCallable.__module__)}.*\.{re.escape(expected_repr)}$",
|
||||
)
|
||||
|
||||
def test_eq_1(self):
|
||||
self.assertEqual(Generic, Generic)
|
||||
self.assertEqual(Generic[T], Generic[T])
|
||||
|
|
|
@ -230,16 +230,17 @@ def _type_repr(obj):
|
|||
typically enough to uniquely identify a type. For everything
|
||||
else, we fall back on repr(obj).
|
||||
"""
|
||||
if isinstance(obj, types.GenericAlias):
|
||||
return repr(obj)
|
||||
if isinstance(obj, type):
|
||||
if obj.__module__ == 'builtins':
|
||||
return obj.__qualname__
|
||||
return f'{obj.__module__}.{obj.__qualname__}'
|
||||
if obj is ...:
|
||||
return('...')
|
||||
return '...'
|
||||
if isinstance(obj, types.FunctionType):
|
||||
return obj.__name__
|
||||
if isinstance(obj, tuple):
|
||||
# Special case for `repr` of types with `ParamSpec`:
|
||||
return '[' + ', '.join(_type_repr(t) for t in obj) + ']'
|
||||
return repr(obj)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
Typing: Improve the ``repr`` of generic aliases for classes generic over a
|
||||
:class:`~typing.ParamSpec`. (Use square brackets to represent a parameter
|
||||
list.)
|
Loading…
Reference in New Issue