| -- Checks NewType(...) |
| |
| -- Checks for basic functionality |
| |
| [case testNewTypePEP484Example1] |
| from typing import NewType |
| |
| UserId = NewType('UserId', int) |
| |
| def name_by_id(user_id: UserId) -> str: |
| return "foo" |
| |
| UserId('user') # E: Argument 1 to "UserId" has incompatible type "str"; expected "int" |
| name_by_id(42) # E: Argument 1 to "name_by_id" has incompatible type "int"; expected "UserId" |
| name_by_id(UserId(42)) |
| |
| id = UserId(5) |
| num = id + 1 |
| |
| reveal_type(id) # N: Revealed type is "__main__.UserId" |
| reveal_type(num) # N: Revealed type is "builtins.int" |
| |
| [targets __main__, __main__.UserId.__init__, __main__.name_by_id] |
| |
| [case testNewTypePEP484Example2] |
| from typing import NewType |
| |
| class PacketId: |
| def __init__(self, major: int, minor: int) -> None: |
| self._major = major |
| self._minor = minor |
| |
| TcpPacketId = NewType('TcpPacketId', PacketId) |
| |
| packet = PacketId(100, 100) |
| tcp_packet = TcpPacketId(packet) |
| tcp_packet = TcpPacketId(127, 0) |
| |
| [out] |
| main:12: error: Too many arguments for "TcpPacketId" |
| main:12: error: Argument 1 to "TcpPacketId" has incompatible type "int"; expected "PacketId" |
| |
| [case testNewTypeWithTuples] |
| from typing import NewType, Tuple |
| TwoTuple = NewType('TwoTuple', Tuple[int, str]) |
| a = TwoTuple((3, "a")) |
| b = TwoTuple(("a", 3)) # E: Argument 1 to "TwoTuple" has incompatible type "Tuple[str, int]"; expected "Tuple[int, str]" |
| |
| reveal_type(a[0]) # N: Revealed type is "builtins.int" |
| reveal_type(a[1]) # N: Revealed type is "builtins.str" |
| [builtins fixtures/tuple.pyi] |
| [out] |
| |
| [case testNewTypeWithLists] |
| from typing import NewType, List |
| UserId = NewType('UserId', int) |
| IdList = NewType('IdList', List[UserId]) |
| |
| bad1 = IdList([1]) # E: List item 0 has incompatible type "int"; expected "UserId" |
| |
| foo = IdList([]) |
| foo.append(3) # E: Argument 1 to "append" of "list" has incompatible type "int"; expected "UserId" |
| foo.append(UserId(3)) |
| foo.extend([UserId(1), UserId(2), UserId(3)]) |
| foo.extend(IdList([UserId(1), UserId(2), UserId(3)])) |
| bar = IdList([UserId(2)]) |
| |
| baz = foo + bar |
| reveal_type(foo) # N: Revealed type is "__main__.IdList" |
| reveal_type(bar) # N: Revealed type is "__main__.IdList" |
| reveal_type(baz) # N: Revealed type is "builtins.list[__main__.UserId]" |
| |
| [builtins fixtures/list.pyi] |
| [out] |
| |
| [case testNewTypeWithGenerics] |
| from typing import TypeVar, Generic, NewType, Any |
| |
| T = TypeVar('T') |
| |
| class Base(Generic[T]): |
| def __init__(self, item: T) -> None: |
| self.item = item |
| |
| def getter(self) -> T: |
| return self.item |
| |
| Derived1 = NewType('Derived1', Base[str]) |
| Derived2 = NewType('Derived2', Base) # Implicit 'Any' |
| Derived3 = NewType('Derived3', Base[Any]) # Explicit 'Any' |
| |
| Derived1(Base(1)) # E: Argument 1 to "Base" has incompatible type "int"; expected "str" |
| Derived1(Base('a')) |
| Derived2(Base(1)) |
| Derived2(Base('a')) |
| Derived3(Base(1)) |
| Derived3(Base('a')) |
| |
| reveal_type(Derived1(Base('a')).getter()) # N: Revealed type is "builtins.str" |
| reveal_type(Derived3(Base('a')).getter()) # N: Revealed type is "Any" |
| [out] |
| |
| [case testNewTypeWithNamedTuple] |
| from collections import namedtuple |
| from typing import NewType, NamedTuple |
| |
| Vector1 = namedtuple('Vector1', ['x', 'y']) |
| Point1 = NewType('Point1', Vector1) |
| p1 = Point1(Vector1(1, 2)) |
| reveal_type(p1.x) # N: Revealed type is "Any" |
| reveal_type(p1.y) # N: Revealed type is "Any" |
| |
| Vector2 = NamedTuple('Vector2', [('x', int), ('y', int)]) |
| Point2 = NewType('Point2', Vector2) |
| p2 = Point2(Vector2(1, 2)) |
| reveal_type(p2.x) # N: Revealed type is "builtins.int" |
| reveal_type(p2.y) # N: Revealed type is "builtins.int" |
| |
| class Vector3: |
| def __init__(self, x: int, y: int) -> None: |
| self.x = x |
| self.y = y |
| Point3 = NewType('Point3', Vector3) |
| p3 = Point3(Vector3(1, 3)) |
| reveal_type(p3.x) # N: Revealed type is "builtins.int" |
| reveal_type(p3.y) # N: Revealed type is "builtins.int" |
| |
| [builtins fixtures/list.pyi] |
| |
| [out] |
| |
| [case testNewTypeWithCasts] |
| from typing import NewType, cast |
| UserId = NewType('UserId', int) |
| foo = UserId(3) |
| foo = cast(UserId, 3) |
| foo = cast(UserId, "foo") |
| foo = cast(UserId, UserId(4)) |
| [out] |
| |
| [case testNewTypeWithTypeAliases] |
| from typing import NewType |
| Foo = int |
| Bar = NewType('Bar', Foo) |
| Bar2 = Bar |
| |
| def func1(x: Foo) -> Bar: |
| return Bar(x) |
| |
| def func2(x: int) -> Bar: |
| return Bar(x) |
| |
| def func3(x: Bar2) -> Bar: |
| return x |
| |
| x = Bar(42) |
| y = Bar2(42) |
| |
| y = func3(x) |
| [out] |
| |
| [case testNewTypeWithNewType] |
| from typing import NewType |
| A = NewType('A', int) |
| B = NewType('B', A) |
| C = A |
| D = C |
| E = NewType('E', D) |
| |
| a = A(1) |
| b = B(a) |
| e = E(a) |
| |
| def funca(a: A) -> None: ... |
| def funcb(b: B) -> None: ... |
| |
| funca(a) |
| funca(b) |
| funca(e) |
| funcb(a) # E: Argument 1 to "funcb" has incompatible type "A"; expected "B" |
| funcb(b) |
| funcb(e) # E: Argument 1 to "funcb" has incompatible type "E"; expected "B" |
| |
| [out] |
| |
| -- Make sure NewType works as expected in a variety of different scopes/across files |
| |
| [case testNewTypeInLocalScope] |
| from typing import NewType |
| A = NewType('A', int) |
| a = A(3) |
| |
| def func() -> None: |
| A = NewType('A', str) |
| B = NewType('B', str) |
| |
| a = A(3) # E: Argument 1 to "A@6" has incompatible type "int"; expected "str" |
| a = A('xyz') |
| b = B('xyz') |
| |
| class MyClass: |
| C = NewType('C', float) |
| |
| def foo(self) -> 'MyClass.C': |
| return MyClass.C(3.2) |
| |
| b = A(3) |
| c = MyClass.C(3.5) |
| [out] |
| |
| [case testNewTypeInMultipleFiles] |
| import a |
| import b |
| list1 = [a.UserId(1), a.UserId(2)] |
| list1.append(b.UserId(3)) # E: Argument 1 to "append" of "list" has incompatible type "b.UserId"; expected "a.UserId" |
| |
| [file a.py] |
| from typing import NewType |
| UserId = NewType('UserId', int) |
| |
| [file b.py] |
| from typing import NewType |
| UserId = NewType('UserId', int) |
| |
| [builtins fixtures/list.pyi] |
| [out] |
| |
| [case testNewTypeWithIncremental] |
| import m |
| |
| [file m.py] |
| from typing import NewType |
| |
| UserId = NewType('UserId', int) |
| |
| def name_by_id(user_id: UserId) -> str: |
| return "foo" |
| |
| name_by_id(UserId(42)) |
| |
| id = UserId(5) |
| num = id + 1 |
| |
| [file m.py.2] |
| from typing import NewType |
| |
| UserId = NewType('UserId', int) |
| |
| def name_by_id(user_id: UserId) -> str: |
| return "foo" |
| |
| name_by_id(UserId(42)) |
| |
| id = UserId(5) |
| num = id + 1 |
| |
| reveal_type(id) |
| reveal_type(num) |
| [rechecked m] |
| [stale] |
| [out1] |
| [out2] |
| tmp/m.py:13: note: Revealed type is "m.UserId" |
| tmp/m.py:14: note: Revealed type is "builtins.int" |
| |
| |
| -- Check misuses of NewType fail |
| |
| [case testNewTypeBadInitializationFails] |
| from typing import NewType |
| |
| a = NewType('b', int) # E: String argument 1 "b" to NewType(...) does not match variable name "a" |
| b = NewType('b', 3) # E: Argument 2 to NewType(...) must be a valid type |
| c = NewType(2, int) # E: Argument 1 to NewType(...) must be a string literal |
| foo = "d" |
| d = NewType(foo, int) # E: Argument 1 to NewType(...) must be a string literal |
| e = NewType(name='e', tp=int) # E: NewType(...) expects exactly two positional arguments |
| f = NewType('f', tp=int) # E: NewType(...) expects exactly two positional arguments |
| [out] |
| |
| [case testNewTypeWithAnyFails] |
| from typing import NewType, Any |
| A = NewType('A', Any) # E: Argument 2 to NewType(...) must be subclassable (got "Any") |
| [out] |
| |
| [case testNewTypeWithUnionsFails] |
| from typing import NewType, Union |
| Foo = NewType('Foo', Union[int, float]) # E: Argument 2 to NewType(...) must be subclassable (got "Union[int, float]") |
| [out] |
| |
| [case testNewTypeWithTypeTypeFails] |
| from typing import NewType, Type |
| Foo = NewType('Foo', Type[int]) # E: Argument 2 to NewType(...) must be subclassable (got "Type[int]") |
| a = Foo(type(3)) |
| [builtins fixtures/args.pyi] |
| [out] |
| |
| [case testNewTypeWithTypeVarsFails] |
| |
| from typing import NewType, TypeVar, List |
| T = TypeVar('T') |
| A = NewType('A', T) |
| B = NewType('B', List[T]) |
| [builtins fixtures/list.pyi] |
| [out] |
| main:4: error: Argument 2 to NewType(...) must be subclassable (got T?) |
| main:4: error: Type variable "__main__.T" is unbound |
| main:4: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) |
| main:4: note: (Hint: Use "T" in function signature to bind "T" inside a function) |
| main:5: error: Type variable "__main__.T" is unbound |
| main:5: note: (Hint: Use "Generic[T]" or "Protocol[T]" base class to bind "T" inside a class) |
| main:5: note: (Hint: Use "T" in function signature to bind "T" inside a function) |
| |
| [case testNewTypeRedefiningVariablesFails] |
| |
| from typing import NewType |
| |
| a = 3 |
| def f(): a |
| a = NewType('a', int) # E: Cannot redefine "a" as a NewType \ |
| # E: Name "a" already defined on line 4 |
| |
| b = NewType('b', int) |
| def g(): b |
| b = NewType('b', float) # E: Cannot redefine "b" as a NewType \ |
| # E: Name "b" already defined on line 8 |
| |
| c = NewType('c', str) # type: str # E: Cannot declare the type of a NewType declaration |
| |
| [case testNewTypeAddingExplicitTypesFails] |
| from typing import NewType |
| UserId = NewType('UserId', int) |
| |
| a = 3 # type: UserId # E: Incompatible types in assignment (expression has type "int", variable has type "UserId") |
| [out] |
| |
| [case testNewTypeTestSubclassingFails] |
| from typing import NewType |
| class A: pass |
| B = NewType('B', A) |
| class C(B): pass # E: Cannot subclass "NewType" |
| [out] |
| |
| [case testCannotUseNewTypeWithProtocols] |
| from typing import Protocol, NewType |
| |
| class P(Protocol): |
| attr: int = 0 |
| class D: |
| attr: int |
| |
| C = NewType('C', P) # E: NewType cannot be used with protocol classes |
| |
| x: C = C(D()) # We still accept this, treating 'C' as non-protocol subclass. |
| reveal_type(x.attr) # N: Revealed type is "builtins.int" |
| x.bad_attr # E: "C" has no attribute "bad_attr" |
| C(1) # E: Argument 1 to "C" has incompatible type "int"; expected "P" |
| [out] |
| |
| [case testNewTypeAny] |
| from typing import NewType |
| Any = NewType('Any', int) |
| Any(5) |
| |
| [case testNewTypeWithIsInstanceAndIsSubclass] |
| from typing import NewType |
| T = NewType('T', int) |
| d: object |
| if isinstance(d, T): # E: Cannot use isinstance() with NewType type |
| reveal_type(d) # N: Revealed type is "__main__.T" |
| issubclass(object, T) # E: Cannot use issubclass() with NewType type |
| [builtins fixtures/isinstancelist.pyi] |
| |
| [case testInvalidNewTypeCrash] |
| |
| from typing import List, NewType, Union |
| N = NewType('N', XXX) # E: Argument 2 to NewType(...) must be subclassable (got "Any") \ |
| # E: Name "XXX" is not defined |
| x: List[Union[N, int]] |
| [builtins fixtures/list.pyi] |