diff --git a/conformance/results/mypy/aliases_newtype.toml b/conformance/results/mypy/aliases_newtype.toml index e1c8c64a..f4c4bc85 100644 --- a/conformance/results/mypy/aliases_newtype.toml +++ b/conformance/results/mypy/aliases_newtype.toml @@ -1,6 +1,6 @@ conformant = "Partial" notes = """ -`NewType`s are considered classes, not functions. +`NewType`s are incorrectly considered to be classes. """ output = """ aliases_newtype.py:11: error: Argument 1 to "UserId" has incompatible type "str"; expected "int" [arg-type] diff --git a/conformance/results/results.html b/conformance/results/results.html index 151069d7..6cbe8f00 100644 --- a/conformance/results/results.html +++ b/conformance/results/results.html @@ -468,7 +468,7 @@

Python Type System Conformance Test Results

Pass      aliases_newtype -
Partial

`NewType`s are considered classes, not functions.

+
Partial

`NewType`s are incorrectly considered to be classes.

Pass
Partial

Does not reject use of NewType in `isinstance` call.

Does not reject use of NewType in class definition statement.

Does not report inconsistency between name of NewType and assigned identifier name.

Does not reject use of NewType with generic class with TypeVar.

Does not reject use of NewType with protocol class.

Does not reject use of NewType with TypedDict class.

Does not reject use of NewType with Any.

Pass diff --git a/conformance/tests/aliases_newtype.py b/conformance/tests/aliases_newtype.py index 713b0bf8..58baeb8a 100644 --- a/conformance/tests/aliases_newtype.py +++ b/conformance/tests/aliases_newtype.py @@ -1,5 +1,5 @@ """ -Tests the `typing.NewType` function. +Tests the `typing.NewType` type constructor. """ # Specification: https://typing.readthedocs.io/en/latest/spec/aliases.html#newtype @@ -14,12 +14,12 @@ assert_type(UserId(5) + 1, int) -# > NewType('Derived', Base) returns a dummy function -_: type = UserId # E: functions are not instances of `type` +# > NewType('Derived', Base) returns a dummy object +_: type = UserId # E: `NewType()` does not return an instance of `type` -# > Both isinstance and issubclass, as well as subclassing will fail for -# > NewType('Derived', Base) since function objects don’t support these -# > operations. +# > Both ``isinstance`` and ``issubclass``, as well as subclassing will fail +# > for ``NewType('Derived', Base)``, since the object returned by a call to +# > ``NewType`` is not a class. isinstance(u2, UserId) # E: not allowed in isinstance call diff --git a/docs/spec/aliases.rst b/docs/spec/aliases.rst index adf30344..a965eca4 100644 --- a/docs/spec/aliases.rst +++ b/docs/spec/aliases.rst @@ -156,9 +156,9 @@ to a definition:: def __init__(self, _x: Base) -> None: ... -While at runtime, ``NewType('Derived', Base)`` returns a dummy function -that simply returns its argument. Type checkers require explicit casts -from ``int`` where ``UserId`` is expected, while implicitly casting +While at runtime, ``NewType('Derived', Base)`` returns a dummy object +that simply returns its argument when called. Type checkers require explicit +casts from ``int`` where ``UserId`` is expected, while implicitly casting from ``UserId`` where ``int`` is expected. Examples:: UserId = NewType('UserId', int) @@ -176,7 +176,7 @@ from ``UserId`` where ``int`` is expected. Examples:: ``NewType`` accepts exactly two arguments: a name for the new unique type, and a base class. The latter should be a proper class (i.e., not a type construct like ``Union``, etc.), or another unique type created -by calling ``NewType``. The function returned by ``NewType`` +by calling ``NewType``. The callable returned by ``NewType`` accepts only one argument; this is equivalent to supporting only one constructor accepting an instance of the base class (see above). Example:: @@ -193,5 +193,8 @@ constructor accepting an instance of the base class (see above). Example:: tcp_packet = TcpPacketId(127, 0) # Fails in type checker and at runtime Both ``isinstance`` and ``issubclass``, as well as subclassing will fail -for ``NewType('Derived', Base)`` since function objects don't support -these operations. +for ``NewType('Derived', Base)``, since the object returned by a call to +``NewType`` is not a class. + +See also :ref:`protocol-newtype-aliases` for a discussion of how +``NewType`` interacts with protocol definitions. diff --git a/docs/spec/protocol.rst b/docs/spec/protocol.rst index 50b64f37..39e7a82a 100644 --- a/docs/spec/protocol.rst +++ b/docs/spec/protocol.rst @@ -514,6 +514,7 @@ For example:: a: ProtoA = C # Type check error, signatures don't match! b: ProtoB = C # OK +.. _`protocol-newtype-aliases`: ``NewType()`` and type aliases ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^