diff --git a/docs/source/basics.rst b/docs/source/basics.rst index 572364d9a771..257aaf872222 100644 --- a/docs/source/basics.rst +++ b/docs/source/basics.rst @@ -37,7 +37,7 @@ context results in a type check error: def p() -> None: print('hello') - a = p() # Type check error: p has None return value + a = p() # error: "p" does not return a value Arguments with default values can be annotated as follows: @@ -63,7 +63,8 @@ more stable. 1 + 'x' # No static type error (dynamically typed) def g() -> None: - 1 + 'x' # Type check error (statically typed) + 1 + 'x' # Statically typed, resulting in + # error: Unsupported operand types for + ("int" and "str") .. note:: diff --git a/docs/source/casts.rst b/docs/source/casts.rst index 900ee0ce4220..52f0aa6594d0 100644 --- a/docs/source/casts.rst +++ b/docs/source/casts.rst @@ -34,6 +34,6 @@ any operations on the result. For example: from typing import cast, Any x = 1 - x + 'x' # Type check error + x + 'x' # error: Unsupported operand types for + ("int" and "str") y = cast(Any, x) y + 'x' # Type check OK (runtime error) diff --git a/docs/source/cheat_sheet.rst b/docs/source/cheat_sheet.rst index 49919a56831c..016795772072 100644 --- a/docs/source/cheat_sheet.rst +++ b/docs/source/cheat_sheet.rst @@ -83,7 +83,7 @@ Functions # type: (int) -> None pass quux(3) # Fine - quux(__x=3) # Error + quux(__x=3) # error: Unexpected keyword argument "__x" for "quux" # This is how you annotate a function value. x = f # type: Callable[[int, float], float] @@ -106,7 +106,7 @@ Functions body=None # type: List[str] ): # type: (...) -> bool - + pass When you're puzzled or when things are complicated @@ -119,7 +119,7 @@ When you're puzzled or when things are complicated # To find out what type mypy infers for an expression anywhere in # your program, wrap it in reveal_type. Mypy will print an error # message with the type; remove it again before running the code. - reveal_type(1) # -> error: Revealed type is 'builtins.int' + reveal_type(1) # error: Revealed type is 'builtins.int' # Use Union when something could be one of a few types. x = [3, 5, "test", "fun"] # type: List[Union[int, str]] @@ -146,8 +146,8 @@ When you're puzzled or when things are complicated a = [4] b = cast(List[int], a) # passes fine c = cast(List[str], a) # passes fine (no runtime check) - reveal_type(c) # -> error: Revealed type is 'builtins.list[builtins.str]' - print(c) # -> [4] the object is not cast + reveal_type(c) # error: Revealed type is 'builtins.list[builtins.str]' + print(c) # [4] the object is not cast # TODO: explain "Need type annotation for variable" when # initializing with None or an empty container diff --git a/docs/source/cheat_sheet_py3.rst b/docs/source/cheat_sheet_py3.rst index adeab7d734d4..60925698279b 100644 --- a/docs/source/cheat_sheet_py3.rst +++ b/docs/source/cheat_sheet_py3.rst @@ -78,7 +78,7 @@ Python 3 introduces an annotation syntax for function declarations in `PEP 3107 def quux(__x: int) -> None: pass quux(3) # Fine - quux(__x=3) # Error + quux(__x=3) # error: Unexpected keyword argument "__x" for "quux" # This is how you annotate a function value. x = f # type: Callable[[int, float], float] @@ -113,7 +113,7 @@ When you're puzzled or when things are complicated # To find out what type mypy infers for an expression anywhere in # your program, wrap it in reveal_type. Mypy will print an error # message with the type; remove it again before running the code. - reveal_type(1) # -> error: Revealed type is 'builtins.int' + reveal_type(1) # error: Revealed type is 'builtins.int' # Use Union when something could be one of a few types. x = [3, 5, "test", "fun"] # type: List[Union[int, str]] @@ -139,8 +139,8 @@ When you're puzzled or when things are complicated a = [4] b = cast(List[int], a) # passes fine c = cast(List[str], a) # passes fine (no runtime check) - reveal_type(c) # -> error: Revealed type is 'builtins.list[builtins.str]' - print(c) # -> [4] the object is not cast + reveal_type(c) # error: Revealed type is 'builtins.list[builtins.str]' + print(c) # [4] the object is not cast # TODO: explain "Need type annotation for variable" when # initializing with None or an empty container @@ -190,8 +190,6 @@ Classes def my_method(self, num: int, str1: str) -> str: return num * str1 - - # User-defined classes are written with just their own names. x = MyClass() # type: MyClass @@ -228,7 +226,7 @@ Other stuff # forward references are useful if you want to referemce a class before it is designed - def f(foo: A) -> int: # this will fail + def f(foo: A) -> int: # this will fail at runtime ... class A: @@ -253,7 +251,7 @@ Mypy brings limited support for PEP 526 annotations. name: str = "Eric Idle" # class instances can be annotated as follows - mc : MyClass = MyClass() + mc: MyClass = MyClass() # tuple packing can be done as follows tu: Tuple[str, ...] = ('a', 'b', 'c') diff --git a/docs/source/class_basics.rst b/docs/source/class_basics.rst index dc778d39424f..8fbff272d6da 100644 --- a/docs/source/class_basics.rst +++ b/docs/source/class_basics.rst @@ -17,19 +17,19 @@ initialized within the class. Mypy infers the types of attributes: a = A(1) a.x = 2 # OK - a.y = 3 # Error: A has no attribute y + a.y = 3 # error: "A" has no attribute "y" This is a bit like each class having an implicitly defined ``__slots__`` attribute. This is only enforced during type checking and not when your program is running. -You can declare types of variables in the class body explicitly using -a type comment: +You can declare types of variables in the class body explicitly in the same way +as variables outside of a class body by using a type comment: .. code-block:: python class A: - x = None # type: List[int] # Declare attribute x of type List[int] + x = None # type: List[int] a = A() a.x = [1] # OK @@ -58,7 +58,7 @@ to it explicitly using ``self``: def __init__(self) -> None: self.y = 1 # Define y a = self - a.x = 1 # Error: x not defined + a.x = 1 # error: "A" has no attribute "x" Overriding statically typed methods *********************************** @@ -68,16 +68,19 @@ override has a compatible signature: .. code-block:: python + + + class A: def f(self, x: int) -> None: ... class B(A): - def f(self, x: str) -> None: # Error: type of x incompatible + def f(self, x: str) -> None: # error: Argument 1 of "f" incompatible with supertype "A" ... class C(A): - def f(self, x: int, y: int) -> None: # Error: too many arguments + def f(self, x: int, y: int) -> None: # error: Signature of "f" incompatible with supertype "A" ... class D(A): diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst index 2501acd28fc0..5093eaab2492 100644 --- a/docs/source/common_issues.rst +++ b/docs/source/common_issues.rst @@ -46,8 +46,8 @@ flagged as an error. .. code-block:: python def foo(a: str) -> str: - return '(' + a.split() + ')' - # error: Unsupported operand types for + ("str" and List[str]) + return '(' + a.split() + ')' # error: Unsupported operand types + # for + ("str" and List[str]) If you don't know what types to add, you can use ``Any``, but beware: @@ -98,7 +98,7 @@ module: .. code-block:: python - import frobnicate # Error: No module "frobnicate" + import frobnicate # error: No module "frobnicate" frobnicate.start() You can add a ``# type: ignore`` comment to tell mypy to ignore this @@ -123,14 +123,17 @@ Types of empty collections -------------------------- You often need to specify the type when you assign an empty list or -dict to a new variable, as mentioned earlier: +dict to a new variable: .. code-block:: python - a = [] # type: List[int] + a = [] # error: Need type annotation for variable -Without the annotation mypy can't always figure out the -precise type of ``a``. +Without an annotation mypy can't always figure out the precise type of ``a``. + +.. code-block:: python + + a = [] # type: List[int] You can use a simple empty list literal in a dynamically typed function (as the type of ``a`` would be implicitly ``Any`` and need not be inferred), if type @@ -161,7 +164,8 @@ with the ``Any`` type. def f() -> None: n = 1 ... - n = 'x' # Type error: n has type int + n = 'x' # error: Incompatible types in assignment (expression + # has type "str", variable has type "int") .. note:: @@ -197,7 +201,8 @@ unexpected errors when combined with type inference. For example: lst = [A(), A()] # Inferred type is List[A] new_lst = [B(), B()] # inferred type is List[B] - lst = new_lst # mypy will complain about this, because List is invariant + lst = new_lst # error: Incompatible types in assignment (expression + # has type List[B], variable has type List[A]) Possible strategies in such situations are: @@ -205,7 +210,7 @@ Possible strategies in such situations are: .. code-block:: python - new_lst: List[A] = [B(), B()] + new_lst = [B(), B()] # type: List[A] lst = new_lst # OK * Make a copy of the right hand side: @@ -220,7 +225,8 @@ Possible strategies in such situations are: def f_bad(x: List[A]) -> A: return x[0] - f_bad(new_lst) # Fails + f_bad(new_lst) # error: Argument 1 to "f_bad" has incompatible + # type List[B]; expected List[A] def f_good(x: Sequence[A]) -> A: return x[0] @@ -238,17 +244,18 @@ of a name (assume here that ``Shape`` is the base class of both shape = Circle() # Infer shape to be Circle ... - shape = Triangle() # Type error: Triangle is not a Circle + shape = Triangle() # error: Incompatible types in assignment + # (expression has type "Triangle", variable has + # type "Circle") -You can just give an explicit type for the variable in cases such the -above example: +You can give an explicit type for the variable in cases such the above example: .. code-block:: python - shape = Circle() # type: Shape # The variable s can be any Shape, - # not just Circle + shape = Circle() # type: Shape # The variable s can be any Shape, + # not just Circle ... - shape = Triangle() # OK + shape = Triangle() # OK Complex type tests ------------------ @@ -262,7 +269,8 @@ explicit type cast: def f(o: object) -> None: if type(o) is int: o = cast(int, o) - g(o + 1) # This would be an error without the cast + g(o + 1) # This would be an error without the cast: + # error: Unsupported operand types for + ("object" and "int") ... else: ... @@ -285,11 +293,11 @@ style anyway). We can write the above code without a cast by using def f(o: object) -> None: if isinstance(o, int): # Mypy understands isinstance checks - g(o + 1) # Okay; type of o is inferred as int here + g(o + 1) # Okay; type of o is inferred as int here ... Type inference in mypy is designed to work well in common cases, to be -predictable and to let the type checker give useful error +predictable, and to let the type checker give useful error messages. More powerful type inference strategies often have complex and difficult-to-predict failure modes and could result in very confusing error messages. The tradeoff is that you as a programmer @@ -368,9 +376,9 @@ understand how mypy handles a particular piece of code. Example: .. note:: ``reveal_type`` is only understood by mypy and doesn't exist - in Python, if you try to run your program. You'll have to remove - any ``reveal_type`` calls before you can run your code. - ``reveal_type`` is always available and you don't need to import it. + in Python. You'll have to remove any ``reveal_type`` calls before you run + your code. ``reveal_type`` is always available and you don't need to import + it. .. _import-cycles: diff --git a/docs/source/dynamic_typing.rst b/docs/source/dynamic_typing.rst index ba76442eb0f5..b978bafaa390 100644 --- a/docs/source/dynamic_typing.rst +++ b/docs/source/dynamic_typing.rst @@ -17,7 +17,8 @@ dynamically typed by defining it explicitly with the type ``Any``: s = 1 # Statically typed (type int) d = 1 # type: Any # Dynamically typed (type Any) - s = 'x' # Type check error + s = 'x' # error: Incompatible types in assignment + # (expression has type "str", variable has type "int") d = 'x' # OK Operations on Any values @@ -74,11 +75,13 @@ operations: .. code-block:: python def f(o: object) -> None: - o.foo() # Error! - o + 2 # Error! - open(o) # Error! - n = 1 # type: int - n = o # Error! + o.foo() # error: "object" has no attribute "foo" + o + 2 # error: Unsupported operand types for + ("object" and "int") + open(o) # error: Argument 1 to "open" has incompatible type "object"; + # expected "Union[str, bytes, int, _PathLike[Any]]" + n = 1 # type: int + n = o # error: Incompatible types in assignment + # (expression has type "object", variable has type "int") You can use ``cast()`` (see chapter :ref:`casts`) or ``isinstance`` to go from a general type such as ``object`` to a more specific diff --git a/docs/source/generics.rst b/docs/source/generics.rst index bd0e0549fd1a..3c3507adcc22 100644 --- a/docs/source/generics.rst +++ b/docs/source/generics.rst @@ -43,7 +43,7 @@ Using ``Stack`` is similar to built-in container types: stack = Stack[int]() stack.push(2) stack.pop() - stack.push('x') # Type error + stack.push('x') # error: Argument 1 to "push" of "Stack" has incompatible type "str"; expected "int" Type inference works for user-defined generic types as well: @@ -335,7 +335,8 @@ Let us illustrate this by few simple examples: .. code-block:: python class Shape: - pass + ... + class Circle(Shape): def rotate(self): ... @@ -345,7 +346,7 @@ Let us illustrate this by few simple examples: my_things: List[Circle] = [] add_one(my_things) # This may appear safe, but... - my_things[0].rotate() # ...this will fail + my_things[0].rotate() # error: Argument 1 to "add_one" has incompatible type List[Circle]; expected List[Shape] Another example of invariant type is ``Dict``, most mutable containers are invariant. @@ -402,14 +403,14 @@ argument types: concat('a', 'b') # Okay concat(b'a', b'b') # Okay - concat(1, 2) # Error! + concat(1, 2) # error: Type argument 1 of "concat" has incompatible value "int" Note that this is different from a union type, since combinations of ``str`` and ``bytes`` are not accepted: .. code-block:: python - concat('string', b'bytes') # Error! + concat('string', b'bytes') # error: Type argument 1 of "concat" has incompatible value "object" In this case, this is exactly what we want, since it's not possible to concatenate a string and a bytes object! The type checker @@ -418,7 +419,7 @@ will reject this function: .. code-block:: python def union_concat(x: Union[str, bytes], y: Union[str, bytes]) -> Union[str, bytes]: - return x + y # Error: can't concatenate str and bytes + return x + y # error: Unsupported operand types for + (likely involving Union) Another interesting special case is calling ``concat()`` with a subtype of ``str``: @@ -481,7 +482,8 @@ above, largest_in_absolute_value(-3.5, 2) # Okay, has type float. largest_in_absolute_value(5+6j, 7) # Okay, has type complex. - largest_in_absolute_value('a', 'b') # Error: 'str' is not a subtype of SupportsAbs[float]. + largest_in_absolute_value('a', 'b') # error: Type argument 1 of "largest_in_absolute_value" has + # incompatible value "str" Type parameters of generic classes may also have upper bounds, which restrict the valid values for the type parameter in the same way. @@ -526,7 +528,7 @@ regardless of that signature. Here's a complete example: reveal_type(a) # str b = bar(3.14, 0) reveal_type(b) # Tuple[float, float, bool] - foo('x') # Type check error: incompatible type "str"; expected "int" + foo('x') # error: Argument 1 to "foo" has incompatible type "str"; expected "int" From the final block we see that the signatures of the decorated functions ``foo()`` and ``bar()`` are the same as those of the original diff --git a/docs/source/kinds_of_types.rst b/docs/source/kinds_of_types.rst index 7b9b54203be3..125499d90e3f 100644 --- a/docs/source/kinds_of_types.rst +++ b/docs/source/kinds_of_types.rst @@ -22,7 +22,7 @@ compatible with all superclasses. All values are compatible with the a = B() # type: A # OK (explicit type for a; override type inference) print(a.f()) # 3 - a.g() # Type check error: A has no method g + a.g() # error: "A" has no attribute "g" The Any type ************ @@ -81,7 +81,7 @@ the error: print('Waiting...') time.sleep(t) - if wait(2) > 1: # Error: can't compare None and int + if wait(2) > 1: # error: "wait" does not return a value ... The ``Any`` type is discussed in more detail in section :ref:`dynamic_typing`. @@ -104,8 +104,9 @@ The type ``Tuple[T1, ..., Tn]`` represents a tuple with the item types ``T1``, . .. code-block:: python def f(t: Tuple[int, str]) -> None: - t = 1, 'foo' # OK - t = 'foo', 1 # Type check error + t = 1, 'foo' # OK + t = 'foo', 1 # error: Incompatible types in assignment + # (expression has type "Tuple[str, int]", variable has type "Tuple[int, str]") A tuple type of this kind has exactly a specific number of items (2 in the above example). Tuples can also be used as immutable, @@ -119,9 +120,10 @@ purpose. Example: for n in t: print(n, n ** 2) - print_squared(()) # OK - print_squared((1, 3, 5)) # OK - print_squared([1, 2]) # Error: only a tuple is valid + print_squared(()) # OK + print_squared((1, 3, 5)) # OK + print_squared([1, 2]) # error: Argument 1 to "print_squared" has incompatible type List[int]; + # expected Tuple[int, ...] .. note:: @@ -173,9 +175,11 @@ Any)`` function signature. Example: def arbitrary_call(f: Callable[..., int]) -> int: return f('x') + f(y=2) # OK - arbitrary_call(ord) # No static error, but fails at runtime - arbitrary_call(open) # Error: does not return an int - arbitrary_call(1) # Error: 'int' is not callable + arbitrary_call(ord) # No static error, but fails at runtime + arbitrary_call(chr) # error: Argument 1 to "arbitrary_call" has incompatible type + # Callable[[int], str]; expected Callable[..., int] + arbitrary_call(1) # error: Argument 1 to "arbitrary_call" has incompatible type "int"; + # expected Callable[..., int] Lambdas are also supported. The lambda argument and return value types cannot be given explicitly; they are always inferred based on context @@ -228,7 +232,7 @@ corresponding ``Callable``: KwArg(int)], int] - f: F = func + f = func # type: F Argument specifiers are special function calls that can specify the following aspects of an argument: @@ -333,7 +337,7 @@ narrow down the type to a specific type: from typing import Union def f(x: Union[int, str]) -> None: - x + 1 # Error: str + int is not valid + x + 1 # error: Unsupported operand types for + ("Union[int, str]" and "int") if isinstance(x, int): # Here type of x is int. x + 1 # OK @@ -343,7 +347,7 @@ narrow down the type to a specific type: f(1) # OK f('x') # OK - f(1.1) # Error + f(1.1) # error: Argument 1 to "f" has incompatible type "float"; expected "Union[int, str]" .. _optional: @@ -352,9 +356,8 @@ The type of None and optional types Mypy treats the type of ``None`` as special. ``None`` is a valid value for every type, which resembles ``null`` in Java. Unlike Java, mypy -doesn't treat primitives types -specially: ``None`` is also valid for primitive types such as ``int`` -and ``float``. +doesn't treat primitives types specially: ``None`` is also valid for primitive +types such as ``int`` and ``float``. .. note:: @@ -426,9 +429,9 @@ idiomatic. ``None`` is also used as the return type for functions that don't return a value, i.e. that implicitly return ``None``. Mypy doesn't - use ``NoneType`` for this, since it would - look awkward, even though that is the real name of the type of ``None`` - (try ``type(None)`` in the interactive interpreter to see for yourself). + use ``NoneType`` for this, since it would look awkward, even though that is + the real name of the type of ``None`` (try ``type(None)`` in the interactive + interpreter to see for yourself). .. _strict_optional: @@ -438,9 +441,9 @@ Experimental strict optional type and None checking Currently, ``None`` is a valid value for each type, similar to ``null`` or ``NULL`` in many languages. However, you can use the experimental ``--strict-optional`` command line option to tell mypy -that types should not include ``None`` -by default. The ``Optional`` type modifier is then used to define -a type variant that includes ``None``, such as ``Optional[int]``: +that types should not include ``None`` by default. The ``Optional`` type +modifier is then used to define a type variant that includes ``None``, such as +``Optional[int]``: .. code-block:: python @@ -451,7 +454,7 @@ a type variant that includes ``None``, such as ``Optional[int]``: def g() -> int: ... - return None # Error: None not compatible with int + return None # error: Incompatible return value type (got None, expected "int") Also, most operations will not be allowed on unguarded ``None`` or ``Optional`` values: @@ -459,7 +462,7 @@ or ``Optional`` values: .. code-block:: python def f(x: Optional[int]) -> int: - return x + 1 # Error: Cannot add None and int + return x + 1 # error: Unsupported operand types for + ("Optional[int]" and "int") Instead, an explicit ``None`` check is required. Mypy has powerful type inference that lets you use regular Python @@ -528,11 +531,11 @@ Class name forward references ***************************** Python does not allow references to a class object before the class is -defined. Thus this code does not work as expected: +defined. Thus this code does not work as expected when executed: .. code-block:: python - def f(x: A) -> None: # Error: Name A not defined + def f(x: A) -> None: # NameError: name 'A' not defined .... class A: @@ -624,9 +627,9 @@ variables replaced with ``Any``. Examples (following `PEP 484 def dilate(v: Vec[T], scale: T) -> Vec[T]: return ((x * scale, y * scale) for x, y in v) - v1: Vec[int] = [] # Same as Iterable[Tuple[int, int]] - v2: Vec = [] # Same as Iterable[Tuple[Any, Any]] - v3: Vec[int, int] = [] # Error: Invalid alias, too many type arguments! + v1 = [] # type: Vec[int] # Same as Iterable[Tuple[int, int]] + v2 = [] # type: Vec # Same as Iterable[Tuple[Any, Any]] + v3 = [] # type: Vec[int, int] # error: Bad number of arguments for type alias, expected: 1, given: 2 Type aliases can be imported from modules like any names. Aliases can target another aliases (although building complex chains of aliases is not recommended, this @@ -709,12 +712,12 @@ implicitly casting from ``UserId`` where ``int`` is expected. Examples: def name_by_id(user_id: UserId) -> str: ... - UserId('user') # Fails type check + UserId('user') # error: Argument 1 to "UserId" has incompatible type "str"; expected "int" - name_by_id(42) # Fails type check - name_by_id(UserId(42)) # OK + name_by_id(42) # error: Argument 1 to "name_by_id" has incompatible type "int"; expected "UserId" + name_by_id(UserId(42)) # OK - num = UserId(5) + 1 # type: int + num = UserId(5) + 1 # type: int ``NewType`` accepts exactly two arguments. The first argument must be a string literal containing the name of the new type and must equal the name of the variable to which the new @@ -739,7 +742,9 @@ Example: packet = PacketId(100, 100) tcp_packet = TcpPacketId(packet) # OK - tcp_packet = TcpPacketId(127, 0) # Fails in type checker and at runtime + tcp_packet = TcpPacketId(127, 0) # error: Too many arguments for "TcpPacketId" + # error: Argument 1 to "TcpPacketId" has incompatible type "int"; + # expected "PacketId" Both ``isinstance`` and ``issubclass``, as well as subclassing will fail for ``NewType('Derived', Base)`` since function objects don't support these operations. @@ -774,7 +779,8 @@ Both ``isinstance`` and ``issubclass``, as well as subclassing will fail for def name_by_id(user_id: UserId) -> str: ... - name_by_id(3) # int is not the same as UserId + name_by_id(3) # error: Argument 1 to "name_by_id" has incompatible type "int"; + # expected "UserId" .. _named-tuples: @@ -787,9 +793,11 @@ missing attribute: .. code-block:: python + from collections import namedtuple + Point = namedtuple('Point', ['x', 'y']) p = Point(x=1, y=2) - print(p.z) # Error: Point has no attribute 'z' + print(p.z) # error: "Point" has no attribute "z" If you use ``namedtuple`` to define your named tuple, all the items are assumed to have ``Any`` types. That is, mypy doesn't know anything @@ -802,10 +810,10 @@ item types: Point = NamedTuple('Point', [('x', int), ('y', int)]) - p = Point(x=1, y='x') # Argument has incompatible type "str"; expected "int" + p = Point(x=1, y='x') # error: Argument 2 to "Point" has incompatible type "str"; expected "int" -Python 3.6 will have an alternative, class-based syntax for named tuples with types. -Mypy supports it already: +Python 3.6 has an alternative, class-based syntax for named tuples with types, +which Mypy supports: .. code-block:: python @@ -815,7 +823,7 @@ Mypy supports it already: x: int y: int - p = Point(x=1, y='x') # Argument has incompatible type "str"; expected "int" + p = Point(x=1, y='x') # error: Argument 2 to "Point" has incompatible type "str"; expected "int" .. _type-of-class: @@ -839,14 +847,17 @@ For example, assume the following classes: class User: # Defines fields like name, email + ... class BasicUser(User): def upgrade(self): """Upgrade to Pro""" + ... class ProUser(User): def pay(self): """Pay bill""" + ... Note that ``ProUser`` doesn't inherit from ``BasicUser``. @@ -867,6 +878,7 @@ could do would be: def new_user(user_class: type) -> User: # Same implementation as before + ... This seems reasonable, except that in the following example, mypy doesn't see that the ``buyer`` variable has type ``ProUser``: @@ -874,7 +886,7 @@ doesn't see that the ``buyer`` variable has type ``ProUser``: .. code-block:: python buyer = new_user(ProUser) - buyer.pay() # Rejected, not a method on User + buyer.pay() # error: "User" has no attribute "pay" However, using ``Type[]`` and a type variable with an upper bound (see :ref:`type-variable-upper-bound`) we can do better: @@ -885,6 +897,7 @@ However, using ``Type[]`` and a type variable with an upper bound (see def new_user(user_class: Type[U]) -> U: # Same implementation as before + ... Now mypy will infer the correct type of the result when we call ``new_user()`` with a specific subclass of ``User``: @@ -939,7 +952,7 @@ so use ``typing.AnyStr``: concat('a', 'b') # Okay concat(b'a', b'b') # Okay - concat('a', b'b') # Error: cannot mix bytes and unicode + concat('a', b'b') # error: Type argument 1 of "concat" has incompatible value "object" For more details, see :ref:`type-variable-value-restriction`. diff --git a/docs/source/python36.rst b/docs/source/python36.rst index f1f73220cb7b..057b0ac94021 100644 --- a/docs/source/python36.rst +++ b/docs/source/python36.rst @@ -45,7 +45,7 @@ Example: def foo(self) -> None: self.x = 0 # OK - self.y = 0 # Error: Cannot assign to class variable "y" via instance + self.y = 0 # error: Cannot assign to class variable "y" via instance C.y = 0 # This is OK @@ -88,7 +88,7 @@ asynchronous comprehensions. Mypy fully supports these features, for example: async def gen() -> AsyncIterator[bytes]: lst = [b async for b in gen()] # Inferred type is "List[bytes]" - yield 'no way' # Error: Incompatible types (got "str", expected "bytes") + yield 'no way' # error: Incompatible types in yield (actual type "str", expected type "bytes") New named tuple syntax ---------------------- diff --git a/docs/source/type_inference_and_annotations.rst b/docs/source/type_inference_and_annotations.rst index 76e9cf9d9014..250697684aa7 100644 --- a/docs/source/type_inference_and_annotations.rst +++ b/docs/source/type_inference_and_annotations.rst @@ -34,7 +34,8 @@ compatible with ``List[object]``: .. code-block:: python def f(l: List[object], k: List[int]) -> None: - l = k # Type check error: incompatible types in assignment + l = k # error: Incompatible types in assignment + # (expression has type List[int], variable has type List[object]) The reason why the above assignment is disallowed is that allowing the assignment could result in non-int values stored in a list of ``int``: @@ -66,6 +67,8 @@ special type comment after an assignment statement: .. code-block:: python x = 1 # type: Union[int, str] + # or, as of Python 3.6: + x: Union[int, str] = 1 Without the type comment, the type of ``x`` would be just ``int``. We use an annotation to give it a more general type ``Union[int, str]``. @@ -76,7 +79,9 @@ type: .. code-block:: python - x = 1.1 # type: Union[int, str] # Error! + x = 1.1 # type: Union[int, str] + # error: Incompatible types in assignment + # (expression has type "float", variable has type "Union[int, str]") .. note:: @@ -134,7 +139,7 @@ right-hand side of an assignment, but not always: .. code-block:: python a, *bs = 1, 2, 3 # OK - p, q, *rs = 1, 2 # Error: Type of rs cannot be inferred + p, q, *rs = 1, 2 # error: Need type annotation for variable On first line, the type of ``bs`` is inferred to be ``List[int]``. However, on the second line, mypy cannot infer the type