diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index cf719df6da1d7a0..64551e667fc920d 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -4868,6 +4868,18 @@ def test_valid_uses(self): self.assertEqual(C4.__args__, (Concatenate[int, T, P], T)) self.assertEqual(C4.__parameters__, (T, P)) + def test_semantically_invalid_uses_have_no_errors(self): + P = ParamSpec('P') + T = TypeVar('T') + + self.assertEqual(Concatenate[()].__args__, ()) + self.assertEqual(Concatenate[int].__args__, (int,)) + self.assertEqual(Concatenate[P, T].__args__, (P, T)) + + def test_invalid_uses_that_generate_errors(self): + with self.assertRaises(TypeError): + Concatenate[1, 2] + class TypeGuardTests(BaseTestCase): def test_basics(self): diff --git a/Lib/typing.py b/Lib/typing.py index 972b8ba24b27e83..250dc7959fae343 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -598,13 +598,8 @@ def Concatenate(self, parameters): See PEP 612 for detailed information. """ - if parameters == (): - raise TypeError("Cannot take a Concatenate of no types.") if not isinstance(parameters, tuple): parameters = (parameters,) - if not isinstance(parameters[-1], ParamSpec): - raise TypeError("The last parameter to Concatenate should be a " - "ParamSpec variable.") msg = "Concatenate[arg, ...]: each arg must be a type." parameters = tuple(_type_check(p, msg) for p in parameters) return _ConcatenateGenericAlias(self, parameters) diff --git a/Misc/NEWS.d/next/Library/2022-01-24-16-19-54.bpo-46396.qQYnUk.rst b/Misc/NEWS.d/next/Library/2022-01-24-16-19-54.bpo-46396.qQYnUk.rst new file mode 100644 index 000000000000000..b5a5ebf02e74422 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-01-24-16-19-54.bpo-46396.qQYnUk.rst @@ -0,0 +1,3 @@ +:class:`typing.Concatenate` does not raise semantic errors anymore. + +We leave type validation to type-checkers.