diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2024-12-31 08:02:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-31 08:02:58 (GMT) |
commit | b2ac70a62ad1be8e037ce45ccf5f1b753ea5e64b (patch) | |
tree | 899c95450277b7e7e8bb92c2953186c0a8308d7e /Lib | |
parent | 7c72c1f0dfff8950e3c6f656307099f1b0a4f8a3 (diff) | |
download | cpython-b2ac70a62ad1be8e037ce45ccf5f1b753ea5e64b.zip cpython-b2ac70a62ad1be8e037ce45ccf5f1b753ea5e64b.tar.gz cpython-b2ac70a62ad1be8e037ce45ccf5f1b753ea5e64b.tar.bz2 |
gh-88834: Unify the instance check for typing.Union and types.UnionType (GH-128363)
Union now uses the instance checks against its parameters instead of
the subclass checks.
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/test/test_typing.py | 75 | ||||
-rw-r--r-- | Lib/typing.py | 6 |
2 files changed, 78 insertions, 3 deletions
diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py index aa42bec..ef3cfc9 100644 --- a/Lib/test/test_typing.py +++ b/Lib/test/test_typing.py @@ -122,7 +122,7 @@ class AnyTests(BaseTestCase): def test_errors(self): with self.assertRaises(TypeError): - issubclass(42, Any) + isinstance(42, Any) with self.assertRaises(TypeError): Any[int] # Any is not a generic type. @@ -137,6 +137,9 @@ class AnyTests(BaseTestCase): class MockSomething(Something, Mock): pass self.assertTrue(issubclass(MockSomething, Any)) + self.assertTrue(issubclass(MockSomething, MockSomething)) + self.assertTrue(issubclass(MockSomething, Something)) + self.assertTrue(issubclass(MockSomething, Mock)) ms = MockSomething() self.assertIsInstance(ms, MockSomething) self.assertIsInstance(ms, Something) @@ -2010,13 +2013,81 @@ class UnionTests(BaseTestCase): u = Union[int, float] self.assertNotEqual(u, Union) - def test_subclass_error(self): + def test_union_isinstance(self): + self.assertTrue(isinstance(42, Union[int, str])) + self.assertTrue(isinstance('abc', Union[int, str])) + self.assertFalse(isinstance(3.14, Union[int, str])) + self.assertTrue(isinstance(42, Union[int, list[int]])) + self.assertTrue(isinstance(42, Union[int, Any])) + + def test_union_isinstance_type_error(self): + with self.assertRaises(TypeError): + isinstance(42, Union[str, list[int]]) + with self.assertRaises(TypeError): + isinstance(42, Union[list[int], int]) + with self.assertRaises(TypeError): + isinstance(42, Union[list[int], str]) + with self.assertRaises(TypeError): + isinstance(42, Union[str, Any]) + with self.assertRaises(TypeError): + isinstance(42, Union[Any, int]) + with self.assertRaises(TypeError): + isinstance(42, Union[Any, str]) + + def test_optional_isinstance(self): + self.assertTrue(isinstance(42, Optional[int])) + self.assertTrue(isinstance(None, Optional[int])) + self.assertFalse(isinstance('abc', Optional[int])) + + def test_optional_isinstance_type_error(self): + with self.assertRaises(TypeError): + isinstance(42, Optional[list[int]]) + with self.assertRaises(TypeError): + isinstance(None, Optional[list[int]]) + with self.assertRaises(TypeError): + isinstance(42, Optional[Any]) + with self.assertRaises(TypeError): + isinstance(None, Optional[Any]) + + def test_union_issubclass(self): + self.assertTrue(issubclass(int, Union[int, str])) + self.assertTrue(issubclass(str, Union[int, str])) + self.assertFalse(issubclass(float, Union[int, str])) + self.assertTrue(issubclass(int, Union[int, list[int]])) + self.assertTrue(issubclass(int, Union[int, Any])) + self.assertFalse(issubclass(int, Union[str, Any])) + self.assertTrue(issubclass(int, Union[Any, int])) + self.assertFalse(issubclass(int, Union[Any, str])) + + def test_union_issubclass_type_error(self): with self.assertRaises(TypeError): issubclass(int, Union) with self.assertRaises(TypeError): issubclass(Union, int) with self.assertRaises(TypeError): issubclass(Union[int, str], int) + with self.assertRaises(TypeError): + issubclass(int, Union[str, list[int]]) + with self.assertRaises(TypeError): + issubclass(int, Union[list[int], int]) + with self.assertRaises(TypeError): + issubclass(int, Union[list[int], str]) + + def test_optional_issubclass(self): + self.assertTrue(issubclass(int, Optional[int])) + self.assertTrue(issubclass(type(None), Optional[int])) + self.assertFalse(issubclass(str, Optional[int])) + self.assertTrue(issubclass(Any, Optional[Any])) + self.assertTrue(issubclass(type(None), Optional[Any])) + self.assertFalse(issubclass(int, Optional[Any])) + + def test_optional_issubclass_type_error(self): + with self.assertRaises(TypeError): + issubclass(list[int], Optional[list[int]]) + with self.assertRaises(TypeError): + issubclass(type(None), Optional[list[int]]) + with self.assertRaises(TypeError): + issubclass(int, Optional[list[int]]) def test_union_any(self): u = Union[Any] diff --git a/Lib/typing.py b/Lib/typing.py index 5f3aacd..e69b485 100644 --- a/Lib/typing.py +++ b/Lib/typing.py @@ -1733,12 +1733,16 @@ class _UnionGenericAlias(_NotIterable, _GenericAlias, _root=True): return super().__repr__() def __instancecheck__(self, obj): - return self.__subclasscheck__(type(obj)) + for arg in self.__args__: + if isinstance(obj, arg): + return True + return False def __subclasscheck__(self, cls): for arg in self.__args__: if issubclass(cls, arg): return True + return False def __reduce__(self): func, (origin, args) = super().__reduce__() |