bpo-44353: Refactor typing.NewType into callable class (GH-27250)

This commit is contained in:
Yurii Karabas 2021-07-20 16:20:38 +03:00 committed by GitHub
parent 4c0deb25ac
commit 965dd76e90
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 5 deletions

View file

@ -3691,6 +3691,26 @@ def test_errors(self):
class D(UserName):
pass
def test_or(self):
UserId = NewType('UserId', int)
self.assertEqual(UserId | int, Union[UserId, int])
self.assertEqual(int | UserId, Union[int, UserId])
self.assertEqual(get_args(UserId | int), (UserId, int))
self.assertEqual(get_args(int | UserId), (int, 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__)
def test_repr(self):
UserId = NewType('UserId', int)
self.assertEqual(repr(UserId), f'{__name__}.UserId')
class NamedTupleTests(BaseTestCase):
class NestedEmployee(NamedTuple):

View file

@ -1374,6 +1374,12 @@ def _no_init(self, *args, **kwargs):
if type(self)._is_protocol:
raise TypeError('Protocols cannot be instantiated')
def _callee(depth=2, default=None):
try:
return sys._getframe(depth).f_globals['__name__']
except (AttributeError, ValueError): # For platforms without _getframe()
return default
def _allow_reckless_class_checks(depth=3):
"""Allow instance and class checks for special stdlib modules.
@ -2350,7 +2356,7 @@ class body be required.
TypedDict.__mro_entries__ = lambda bases: (_TypedDict,)
def NewType(name, tp):
class NewType:
"""NewType creates simple unique types with almost zero
runtime overhead. NewType(name, tp) is considered a subtype of tp
by static type checkers. At runtime, NewType(name, tp) returns
@ -2369,12 +2375,23 @@ def name_by_id(user_id: UserId) -> str:
num = UserId(5) + 1 # type: int
"""
def new_type(x):
def __init__(self, name, tp):
self.__name__ = name
self.__qualname__ = name
self.__module__ = _callee(default='typing')
self.__supertype__ = tp
def __repr__(self):
return f'{self.__module__}.{self.__qualname__}'
def __call__(self, x):
return x
new_type.__name__ = name
new_type.__supertype__ = tp
return new_type
def __or__(self, other):
return Union[self, other]
def __ror__(self, other):
return Union[other, self]
# Python-version-specific alias (Python 2: unicode; Python 3: str)

View file

@ -0,0 +1,2 @@
Refactor ``typing.NewType`` from function into callable class. Patch
provided by Yurii Karabas.