Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions 19 Lib/test/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2414,6 +2414,25 @@ def test_basic(self):
self.assertIsInstance(UserName('Joe'), str)
self.assertEqual(UserId(5) + 1, 6)

def test_definitions(self):
UserId = NewType('UserId', int)
UserName = NewType('UserName', str)
self.assertEqual(UserId.__name__, 'UserId')
self.assertEqual(UserId.__qualname__, 'UserId')
self.assertIs(UserId.__supertype__, int)
self.assertIsInstance(UserId, NewType)
self.assertEqual(UserName.__name__, 'UserName')
self.assertEqual(UserName.__qualname__, 'UserName')
self.assertIs(UserName.__supertype__, str)
self.assertIsInstance(UserName, NewType)
self.assertNotEqual(hash(UserId), hash(UserName))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't guarantee this.


def test_repr(self):
UserId = NewType('UserId', int)
UserName = NewType('UserName', str)
self.assertEqual(repr(UserId), "NewType<UserId:int>")
self.assertEqual(repr(UserName), "NewType<UserName:str>")

def test_errors(self):
UserId = NewType('UserId', int)
UserName = NewType('UserName', str)
Expand Down
36 changes: 25 additions & 11 deletions 36 Lib/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1409,12 +1409,13 @@ def __new__(self, typename, fields=None, **kwargs):
" can be provided to NamedTuple, not both")
return _make_nmtuple(typename, fields)

class NewType:

def NewType(name, tp):
"""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
a dummy function that simply returns its argument. Usage::
"""NewType creates simple unique types with almost zero runtime
overhead. `NewType(name, tp)` is considered a subtype of `tp`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use backquotes in docstrings. They are not interpreted.

by static type checkers. At runtime, NewType(name, tp) creates
a callable instance that simply returns its argument when called.
Usage::

UserId = NewType('UserId', int)

Expand All @@ -1429,18 +1430,31 @@ def name_by_id(user_id: UserId) -> str:
num = UserId(5) + 1 # type: int
"""
Comment thread
fish2000 marked this conversation as resolved.
Outdated

def new_type(x):
return x
__slots__ = ('__name__', '__qualname__', '__supertype__')

def __init__(self, name, tp):
self.__name__ = self.__qualname__ = name

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting __qualname__ is not needed if it is not a function.

self.__supertype__ = tp

@staticmethod
def __call__(arg):
return arg

new_type.__name__ = name
new_type.__supertype__ = tp
return new_type
def __repr__(self):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make the repr in the form NewType("typename", supertype):

    def __repr__(self):
        return f"{type(self).__name__}({self.__name__!r}, {self.__supertype__})"

""" NewType reprs are in the form:
“NewTClassName<typename:supertypename>”, e.g.:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't use non-ASCII quotes. Also I am not sure this docstirng is actually needed, the code is self-explanatory.

`NewType<UserId:int>`
"""
return f"{type(self).__name__}<" \
f"{self.__qualname__}:" \
f"{self.__supertype__.__name__}>"

def __hash__(self):
return hash((self.__name__, self.__supertype__))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is needed?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same question.


# Python-version-specific alias (Python 2: unicode; Python 3: str)
Text = str


# Constant that's True when type checking, but False here.
TYPE_CHECKING = False

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Updated the `typing.NewType(…)` function to create real callable types –
This allows the generated types to furnish a real __repr__ function, while
retaining the same behavior (specifically, the near-zero runtime overhead).
Morty Proxy This is a proxified and sanitized view of the page, visit original site.