-
-
Notifications
You must be signed in to change notification settings - Fork 34.7k
bpo-44353: Refactor typing.NewType into callable class #27250
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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') | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes it rather slow but I guess
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It will be executed only once when |
||
| 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) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Refactor ``typing.NewType`` from function into callable class. Patch | ||
| provided by Yurii Karabas. |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this doesn't test for the bug the user is reporting. In fact without this PR, these tests should all work, just instead of being
typing.Union, it istypes.Union(becauseintimplements__or__). So the test won't be able to detect a regression.The bug reported is that
UserId1 | UserId2won't work, because they both don't implement__or__.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, we should add tests to cover case when there are two
NewType.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will open another PR with more tests. I was not expecting that it will be merged so fast)