From 7d2212bbf6a0770100eab3b94cc1dc455f53c0ec Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 8 Feb 2022 23:04:18 +0300 Subject: [PATCH 1/5] bpo-46685: improve test coverage of `Self` and `Never` in `typing` --- Lib/test/test_typing.py | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 78e58928332f08..dbb8d8675cb90a 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -127,6 +127,14 @@ def test_any_works_with_alias(self): class BottomTypeTestsMixin: bottom_type: ClassVar[Any] + def test_equality(self): + self.assertEqual(self.bottom_type, self.bottom_type) + self.assertIs(self.bottom_type, self.bottom_type) + self.assertNotEqual(self.bottom_type, None) + + def test_get_origin(self): + self.assertIs(get_origin(self.bottom_type), None) + def test_instance_type_error(self): with self.assertRaises(TypeError): isinstance(42, self.bottom_type) @@ -162,6 +170,18 @@ class NoReturnTests(BottomTypeTestsMixin, BaseTestCase): def test_repr(self): self.assertEqual(repr(NoReturn), 'typing.NoReturn') + def test_get_type_hints(self): + def some(arg: NoReturn) -> NoReturn: ... + + self.assertEqual( + get_type_hints(some), + {'arg': NoReturn, 'return': NoReturn}, + ) + + def test_not_equality(self): + self.assertNotEqual(NoReturn, Never) + self.assertNotEqual(Never, NoReturn) + class NeverTests(BottomTypeTestsMixin, BaseTestCase): bottom_type = Never @@ -169,6 +189,14 @@ class NeverTests(BottomTypeTestsMixin, BaseTestCase): def test_repr(self): self.assertEqual(repr(Never), 'typing.Never') + def test_get_type_hints(self): + def some(arg: Never) -> Never: ... + + self.assertEqual( + get_type_hints(some), + {'arg': Never, 'return': Never}, + ) + class AssertNeverTests(BaseTestCase): def test_exception(self): @@ -177,11 +205,17 @@ def test_exception(self): class SelfTests(BaseTestCase): + def test_equality(self): + self.assertEqual(Self, Self) + self.assertIs(Self, Self) + self.assertNotEqual(Self, None) + def test_basics(self): class Foo: def bar(self) -> Self: ... self.assertEqual(gth(Foo.bar), {'return': Self}) + self.assertIs(get_origin(Self), None) def test_repr(self): self.assertEqual(repr(Self), 'typing.Self') @@ -194,6 +228,9 @@ def test_cannot_subclass(self): with self.assertRaises(TypeError): class C(type(Self)): pass + with self.assertRaises(TypeError): + class C(Self): + pass def test_cannot_init(self): with self.assertRaises(TypeError): @@ -2792,6 +2829,10 @@ def test_forwardref_subclass_type_error(self): with self.assertRaises(TypeError): issubclass(int, fr) + def test_forwardref_only_str_arg(self): + with self.assertRaises(TypeError): + typing.ForwardRef(1) # only `str` type is allowed + def test_forward_equality(self): fr = typing.ForwardRef('int') self.assertEqual(fr, typing.ForwardRef('int')) From bb73e48935f6a3f5f1e40f57ad2191c10545fb3d Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 8 Feb 2022 23:07:41 +0300 Subject: [PATCH 2/5] AllTests -> DunderAllTests --- Lib/test/test_typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index dbb8d8675cb90a..2e434d936cc179 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -5441,7 +5441,7 @@ def test_reveal_type(self): self.assertEqual(stderr.getvalue(), "Runtime type is 'object'\n") -class AllTests(BaseTestCase): +class DunderAllTests(BaseTestCase): """Tests for __all__.""" def test_all(self): From 8e2fa5ddf33efe6a338cd03dfdd1809c57d0d660 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 8 Feb 2022 23:11:50 +0300 Subject: [PATCH 3/5] DunderAllTests -> AllTests --- Lib/test/test_typing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index 2e434d936cc179..dbb8d8675cb90a 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -5441,7 +5441,7 @@ def test_reveal_type(self): self.assertEqual(stderr.getvalue(), "Runtime type is 'object'\n") -class DunderAllTests(BaseTestCase): +class AllTests(BaseTestCase): """Tests for __all__.""" def test_all(self): From 9c67f0c74ef7bb76d754014a98cd13cf6e321107 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 8 Feb 2022 23:42:12 +0300 Subject: [PATCH 4/5] Move `ForwardRef(1)` test to a separate PR --- Lib/test/test_typing.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index dbb8d8675cb90a..f9055bfb5a4bc0 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -2829,10 +2829,6 @@ def test_forwardref_subclass_type_error(self): with self.assertRaises(TypeError): issubclass(int, fr) - def test_forwardref_only_str_arg(self): - with self.assertRaises(TypeError): - typing.ForwardRef(1) # only `str` type is allowed - def test_forward_equality(self): fr = typing.ForwardRef('int') self.assertEqual(fr, typing.ForwardRef('int')) From cc825ccf74b9aad3c56933a2ae10b6950b9a44d0 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 9 Feb 2022 00:21:06 +0300 Subject: [PATCH 5/5] Address review --- Lib/test/test_typing.py | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index f9055bfb5a4bc0..83a5fe65401461 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -172,11 +172,12 @@ def test_repr(self): def test_get_type_hints(self): def some(arg: NoReturn) -> NoReturn: ... + def some_str(arg: 'NoReturn') -> 'typing.NoReturn': ... - self.assertEqual( - get_type_hints(some), - {'arg': NoReturn, 'return': NoReturn}, - ) + expected = {'arg': NoReturn, 'return': NoReturn} + for target in [some, some_str]: + with self.subTest(target=target): + self.assertEqual(gth(target), expected) def test_not_equality(self): self.assertNotEqual(NoReturn, Never) @@ -191,11 +192,12 @@ def test_repr(self): def test_get_type_hints(self): def some(arg: Never) -> Never: ... + def some_str(arg: 'Never') -> 'typing.Never': ... - self.assertEqual( - get_type_hints(some), - {'arg': Never, 'return': Never}, - ) + expected = {'arg': Never, 'return': Never} + for target in [some, some_str]: + with self.subTest(target=target): + self.assertEqual(gth(target), expected) class AssertNeverTests(BaseTestCase): @@ -213,8 +215,14 @@ def test_equality(self): def test_basics(self): class Foo: def bar(self) -> Self: ... - - self.assertEqual(gth(Foo.bar), {'return': Self}) + class FooStr: + def bar(self) -> 'Self': ... + class FooStrTyping: + def bar(self) -> 'typing.Self': ... + + for target in [Foo, FooStr, FooStrTyping]: + with self.subTest(target=target): + self.assertEqual(gth(target.bar), {'return': Self}) self.assertIs(get_origin(Self), None) def test_repr(self): @@ -5332,11 +5340,13 @@ def test_special_attrs(self): typing.Literal: 'Literal', typing.NewType: 'NewType', typing.NoReturn: 'NoReturn', + typing.Never: 'Never', typing.Optional: 'Optional', typing.TypeAlias: 'TypeAlias', typing.TypeGuard: 'TypeGuard', typing.TypeVar: 'TypeVar', typing.Union: 'Union', + typing.Self: 'Self', # Subscribed special forms typing.Annotated[Any, "Annotation"]: 'Annotated', typing.ClassVar[Any]: 'ClassVar',