[Python-checkins] [3.10] bpo-44353: Expand NewType tests for complex __qualname__ (GH-27311) (GH-27326)

ambv webhook-mailer at python.org
Sat Jul 24 06:08:00 EDT 2021


https://github.com/python/cpython/commit/05f5d8e48c86c8025d3f82285666d93e52e360f9
commit: 05f5d8e48c86c8025d3f82285666d93e52e360f9
branch: 3.10
author: Łukasz Langa <lukasz at langa.pl>
committer: ambv <lukasz at langa.pl>
date: 2021-07-24T12:07:56+02:00
summary:

[3.10] bpo-44353: Expand NewType tests for complex __qualname__ (GH-27311) (GH-27326)

Make NewType pickleable by name.
(cherry picked from commit e89ef0ad2a299770a88ece8f7a316f7d3eb65c9f)

Co-authored-by: Serhiy Storchaka <storchaka at gmail.com>

files:
M Lib/test/test_typing.py
M Lib/typing.py

diff --git a/Lib/test/test_typing.py b/Lib/test/test_typing.py
index f5abbb29db641..5e3fba3a8687b 100644
--- a/Lib/test/test_typing.py
+++ b/Lib/test/test_typing.py
@@ -3673,28 +3673,35 @@ def foo(a: A) -> Optional[BaseException]:
 
 
 class NewTypeTests(BaseTestCase):
+    @classmethod
+    def setUpClass(cls):
+        global UserId
+        UserId = NewType('UserId', int)
+        cls.UserName = NewType(cls.__qualname__ + '.UserName', str)
+
+    @classmethod
+    def tearDownClass(cls):
+        global UserId
+        del UserId
+        del cls.UserName
+
+    def tearDown(self):
+        self.clear_caches()
 
     def test_basic(self):
-        UserId = NewType('UserId', int)
-        UserName = NewType('UserName', str)
         self.assertIsInstance(UserId(5), int)
-        self.assertIsInstance(UserName('Joe'), str)
+        self.assertIsInstance(self.UserName('Joe'), str)
         self.assertEqual(UserId(5) + 1, 6)
 
     def test_errors(self):
-        UserId = NewType('UserId', int)
-        UserName = NewType('UserName', str)
         with self.assertRaises(TypeError):
             issubclass(UserId, int)
         with self.assertRaises(TypeError):
-            class D(UserName):
+            class D(UserId):
                 pass
 
     def test_or(self):
-        UserId = NewType('UserId', int)
-        UserName = NewType('UserName', str)
-
-        for cls in (int, UserName):
+        for cls in (int, self.UserName):
             with self.subTest(cls=cls):
                 self.assertEqual(UserId | cls, Union[UserId, cls])
                 self.assertEqual(cls | UserId, Union[cls, UserId])
@@ -3703,16 +3710,37 @@ def test_or(self):
                 self.assertEqual(get_args(cls | UserId), (cls, UserId))
 
     def test_special_attrs(self):
-        UserId = NewType('UserId', int)
-
         self.assertEqual(UserId.__name__, 'UserId')
         self.assertEqual(UserId.__qualname__, 'UserId')
         self.assertEqual(UserId.__module__, __name__)
+        self.assertEqual(UserId.__supertype__, int)
 
-    def test_repr(self):
-        UserId = NewType('UserId', int)
+        UserName = self.UserName
+        self.assertEqual(UserName.__name__, 'UserName')
+        self.assertEqual(UserName.__qualname__,
+                         self.__class__.__qualname__ + '.UserName')
+        self.assertEqual(UserName.__module__, __name__)
+        self.assertEqual(UserName.__supertype__, str)
 
+    def test_repr(self):
         self.assertEqual(repr(UserId), f'{__name__}.UserId')
+        self.assertEqual(repr(self.UserName),
+                         f'{__name__}.{self.__class__.__qualname__}.UserName')
+
+    def test_pickle(self):
+        UserAge = NewType('UserAge', float)
+        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
+            pickled = pickle.dumps(UserId, proto)
+            loaded = pickle.loads(pickled)
+            self.assertIs(loaded, UserId)
+
+            pickled = pickle.dumps(self.UserName, proto)
+            loaded = pickle.loads(pickled)
+            self.assertIs(loaded, self.UserName)
+
+            with self.assertRaises(pickle.PicklingError):
+                pickle.dumps(UserAge, proto)
+
 
 class NamedTupleTests(BaseTestCase):
     class NestedEmployee(NamedTuple):
diff --git a/Lib/typing.py b/Lib/typing.py
index 1606de91ac668..ffd35e5b47751 100644
--- a/Lib/typing.py
+++ b/Lib/typing.py
@@ -2375,8 +2375,10 @@ def name_by_id(user_id: UserId) -> str:
     """
 
     def __init__(self, name, tp):
-        self.__name__ = name
         self.__qualname__ = name
+        if '.' in name:
+            name = name.rpartition('.')[-1]
+        self.__name__ = name
         self.__module__ = _callee(default='typing')
         self.__supertype__ = tp
 
@@ -2386,6 +2388,9 @@ def __repr__(self):
     def __call__(self, x):
         return x
 
+    def __reduce__(self):
+        return self.__qualname__
+
     def __or__(self, other):
         return Union[self, other]
 



More information about the Python-checkins mailing list