| .. _common_issues: |
| |
| Common issues and solutions |
| =========================== |
| |
| This section has examples of cases when you need to update your code |
| to use static typing, and ideas for working around issues if mypy |
| doesn't work as expected. Statically typed code is often identical to |
| normal Python code (except for type annotations), but sometimes you need |
| to do things slightly differently. |
| |
| Can't install mypy using pip |
| ---------------------------- |
| |
| If installation fails, you've probably hit one of these issues: |
| |
| * Mypy needs Python 3.5 or later to run. |
| * You may have to run pip like this: |
| ``python3 -m pip install mypy``. |
| |
| .. _annotations_needed: |
| |
| No errors reported for obviously wrong code |
| ------------------------------------------- |
| |
| There are several common reasons why obviously wrong code is not |
| flagged as an error. |
| |
| - **The function containing the error is not annotated.** Functions that |
| do not have any annotations (neither for any argument nor for the |
| return type) are not type-checked, and even the most blatant type |
| errors (e.g. ``2 + 'a'``) pass silently. The solution is to add |
| annotations. Where that isn't possible, functions without annotations |
| can be checked using :option:`--check-untyped-defs <mypy --check-untyped-defs>`. |
| |
| Example: |
| |
| .. code-block:: python |
| |
| def foo(a): |
| return '(' + a.split() + ')' # No error! |
| |
| This gives no error even though ``a.split()`` is "obviously" a list |
| (the author probably meant ``a.strip()``). The error is reported |
| once you add annotations: |
| |
| .. code-block:: python |
| |
| def foo(a: str) -> 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: |
| |
| - **One of the values involved has type 'Any'.** Extending the above |
| example, if we were to leave out the annotation for ``a``, we'd get |
| no error: |
| |
| .. code-block:: python |
| |
| def foo(a) -> str: |
| return '(' + a.split() + ')' # No error! |
| |
| The reason is that if the type of ``a`` is unknown, the type of |
| ``a.split()`` is also unknown, so it is inferred as having type |
| ``Any``, and it is no error to add a string to an ``Any``. |
| |
| If you're having trouble debugging such situations, |
| :ref:`reveal_type() <reveal-type>` might come in handy. |
| |
| Note that sometimes library stubs have imprecise type information, |
| e.g. the :py:func:`pow` builtin returns ``Any`` (see `typeshed issue 285 |
| <https://github.com/python/typeshed/issues/285>`_ for the reason). |
| |
| - **Some imports may be silently ignored**. Another source of |
| unexpected ``Any`` values are the :option:`--ignore-missing-imports |
| <mypy --ignore-missing-imports>` and :option:`--follow-imports=skip |
| <mypy --follow-imports>` flags. When you use :option:`--ignore-missing-imports <mypy --ignore-missing-imports>`, |
| any imported module that cannot be found is silently replaced with |
| ``Any``. When using :option:`--follow-imports=skip <mypy --follow-imports>` the same is true for |
| modules for which a ``.py`` file is found but that are not specified |
| on the command line. (If a ``.pyi`` stub is found it is always |
| processed normally, regardless of the value of |
| :option:`--follow-imports <mypy --follow-imports>`.) To help debug the former situation (no |
| module found at all) leave out :option:`--ignore-missing-imports <mypy --ignore-missing-imports>`; to get |
| clarity about the latter use :option:`--follow-imports=error <mypy --follow-imports>`. You can |
| read up about these and other useful flags in :ref:`command-line`. |
| |
| - **A function annotated as returning a non-optional type returns 'None' |
| and mypy doesn't complain**. |
| |
| .. code-block:: python |
| |
| def foo() -> str: |
| return None # No error! |
| |
| You may have disabled strict optional checking (see |
| :ref:`no_strict_optional` for more). |
| |
| .. _silencing_checker: |
| |
| Spurious errors and locally silencing the checker |
| ------------------------------------------------- |
| |
| You can use a ``# type: ignore`` comment to silence the type checker |
| on a particular line. For example, let's say our code is using |
| the C extension module ``frobnicate``, and there's no stub available. |
| Mypy will complain about this, as it has no information about the |
| module: |
| |
| .. code-block:: python |
| |
| import frobnicate # Error: No module "frobnicate" |
| frobnicate.start() |
| |
| You can add a ``# type: ignore`` comment to tell mypy to ignore this |
| error: |
| |
| .. code-block:: python |
| |
| import frobnicate # type: ignore |
| frobnicate.start() # Okay! |
| |
| The second line is now fine, since the ignore comment causes the name |
| ``frobnicate`` to get an implicit ``Any`` type. |
| |
| .. note:: |
| |
| You can use the form ``# type: ignore[<code>]`` to only ignore |
| specific errors on the line. This way you are less likely to |
| silence unexpected errors that are not safe to ignore, and this |
| will also document what the purpose of the comment is. See |
| :ref:`error-codes` for more information. |
| |
| .. note:: |
| |
| The ``# type: ignore`` comment will only assign the implicit ``Any`` |
| type if mypy cannot find information about that particular module. So, |
| if we did have a stub available for ``frobnicate`` then mypy would |
| ignore the ``# type: ignore`` comment and typecheck the stub as usual. |
| |
| Another option is to explicitly annotate values with type ``Any`` -- |
| mypy will let you perform arbitrary operations on ``Any`` |
| values. Sometimes there is no more precise type you can use for a |
| particular value, especially if you use dynamic Python features |
| such as :py:meth:`__getattr__ <object.__getattr__>`: |
| |
| .. code-block:: python |
| |
| class Wrapper: |
| ... |
| def __getattr__(self, a: str) -> Any: |
| return getattr(self._wrapped, a) |
| |
| Finally, you can create a stub file (``.pyi``) for a file that |
| generates spurious errors. Mypy will only look at the stub file |
| and ignore the implementation, since stub files take precedence |
| over ``.py`` files. |
| |
| Ignoring a whole file |
| --------------------- |
| |
| A ``# type: ignore`` comment at the top of a module (before any statements, |
| including imports or docstrings) has the effect of ignoring the *entire* module. |
| |
| .. code-block:: python |
| |
| # type: ignore |
| |
| import foo |
| |
| foo.bar() |
| |
| Unexpected errors about 'None' and/or 'Optional' types |
| ------------------------------------------------------ |
| |
| Starting from mypy 0.600, mypy uses |
| :ref:`strict optional checking <strict_optional>` by default, |
| and the ``None`` value is not compatible with non-optional types. |
| It's easy to switch back to the older behavior where ``None`` was |
| compatible with arbitrary types (see :ref:`no_strict_optional`). |
| You can also fall back to this behavior if strict optional |
| checking would require a large number of ``assert foo is not None`` |
| checks to be inserted, and you want to minimize the number |
| of code changes required to get a clean mypy run. |
| |
| Mypy runs are slow |
| ------------------ |
| |
| If your mypy runs feel slow, you should probably use the :ref:`mypy |
| daemon <mypy_daemon>`, which can speed up incremental mypy runtimes by |
| a factor of 10 or more. :ref:`Remote caching <remote-cache>` can |
| make cold mypy runs several times faster. |
| |
| 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: |
| |
| .. code-block:: python |
| |
| a: List[int] = [] |
| |
| Without the annotation mypy can't always figure out the |
| precise type of ``a``. |
| |
| 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 |
| of the variable has been declared or inferred before, or if you perform a simple |
| modification operation in the same scope (such as ``append`` for a list): |
| |
| .. code-block:: python |
| |
| a = [] # Okay because followed by append, inferred type List[int] |
| for i in range(n): |
| a.append(i * i) |
| |
| However, in more complex cases an explicit type annotation can be |
| required (mypy will tell you this). Often the annotation can |
| make your code easier to understand, so it doesn't only help mypy but |
| everybody who is reading the code! |
| |
| Redefinitions with incompatible types |
| ------------------------------------- |
| |
| Each name within a function only has a single 'declared' type. You can |
| reuse for loop indices etc., but if you want to use a variable with |
| multiple types within a single function, you may need to declare it |
| with the ``Any`` type. |
| |
| .. code-block:: python |
| |
| def f() -> None: |
| n = 1 |
| ... |
| n = 'x' # Type error: n has type int |
| |
| .. note:: |
| |
| This limitation could be lifted in a future mypy |
| release. |
| |
| Note that you can redefine a variable with a more *precise* or a more |
| concrete type. For example, you can redefine a sequence (which does |
| not support ``sort()``) as a list and sort it in-place: |
| |
| .. code-block:: python |
| |
| def f(x: Sequence[int]) -> None: |
| # Type of x is Sequence[int] here; we don't know the concrete type. |
| x = list(x) |
| # Type of x is List[int] here. |
| x.sort() # Okay! |
| |
| .. _variance: |
| |
| Invariance vs covariance |
| ------------------------ |
| |
| Most mutable generic collections are invariant, and mypy considers all |
| user-defined generic classes invariant by default |
| (see :ref:`variance-of-generics` for motivation). This could lead to some |
| unexpected errors when combined with type inference. For example: |
| |
| .. code-block:: python |
| |
| class A: ... |
| class B(A): ... |
| |
| 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 |
| |
| Possible strategies in such situations are: |
| |
| * Use an explicit type annotation: |
| |
| .. code-block:: python |
| |
| new_lst: List[A] = [B(), B()] |
| lst = new_lst # OK |
| |
| * Make a copy of the right hand side: |
| |
| .. code-block:: python |
| |
| lst = list(new_lst) # Also OK |
| |
| * Use immutable collections as annotations whenever possible: |
| |
| .. code-block:: python |
| |
| def f_bad(x: List[A]) -> A: |
| return x[0] |
| f_bad(new_lst) # Fails |
| |
| def f_good(x: Sequence[A]) -> A: |
| return x[0] |
| f_good(new_lst) # OK |
| |
| Declaring a supertype as variable type |
| -------------------------------------- |
| |
| Sometimes the inferred type is a subtype (subclass) of the desired |
| type. The type inference uses the first assignment to infer the type |
| of a name (assume here that ``Shape`` is the base class of both |
| ``Circle`` and ``Triangle``): |
| |
| .. code-block:: python |
| |
| shape = Circle() # Infer shape to be Circle |
| ... |
| shape = Triangle() # Type error: Triangle is not a Circle |
| |
| You can just 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 = Triangle() # OK |
| |
| Complex type tests |
| ------------------ |
| |
| Mypy can usually infer the types correctly when using :py:func:`isinstance <isinstance>` |
| type tests, but for other kinds of checks you may need to add an |
| explicit type cast: |
| |
| .. code-block:: python |
| |
| 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 |
| ... |
| else: |
| ... |
| |
| .. note:: |
| |
| Note that the :py:class:`object` type used in the above example is similar |
| to ``Object`` in Java: it only supports operations defined for *all* |
| objects, such as equality and :py:func:`isinstance`. The type ``Any``, |
| in contrast, supports all operations, even if they may fail at |
| runtime. The cast above would have been unnecessary if the type of |
| ``o`` was ``Any``. |
| |
| Mypy can't infer the type of ``o`` after the :py:class:`type() <type>` check |
| because it only knows about :py:func:`isinstance` (and the latter is better |
| style anyway). We can write the above code without a cast by using |
| :py:func:`isinstance`: |
| |
| .. code-block:: python |
| |
| 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 |
| ... |
| |
| Type inference in mypy is designed to work well in common cases, to be |
| 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 |
| sometimes have to give the type checker a little help. |
| |
| .. _version_and_platform_checks: |
| |
| Python version and system platform checks |
| ----------------------------------------- |
| |
| Mypy supports the ability to perform Python version checks and platform |
| checks (e.g. Windows vs Posix), ignoring code paths that won't be run on |
| the targeted Python version or platform. This allows you to more effectively |
| typecheck code that supports multiple versions of Python or multiple operating |
| systems. |
| |
| More specifically, mypy will understand the use of :py:data:`sys.version_info` and |
| :py:data:`sys.platform` checks within ``if/elif/else`` statements. For example: |
| |
| .. code-block:: python |
| |
| import sys |
| |
| # Distinguishing between different versions of Python: |
| if sys.version_info >= (3, 5): |
| # Python 3.5+ specific definitions and imports |
| elif sys.version_info[0] >= 3: |
| # Python 3 specific definitions and imports |
| else: |
| # Python 2 specific definitions and imports |
| |
| # Distinguishing between different operating systems: |
| if sys.platform.startswith("linux"): |
| # Linux-specific code |
| elif sys.platform == "darwin": |
| # Mac-specific code |
| elif sys.platform == "win32": |
| # Windows-specific code |
| else: |
| # Other systems |
| |
| As a special case, you can also use one of these checks in a top-level |
| (unindented) ``assert``; this makes mypy skip the rest of the file. |
| Example: |
| |
| .. code-block:: python |
| |
| import sys |
| |
| assert sys.platform != 'win32' |
| |
| # The rest of this file doesn't apply to Windows. |
| |
| Some other expressions exhibit similar behavior; in particular, |
| :py:data:`~typing.TYPE_CHECKING`, variables named ``MYPY``, and any variable |
| whose name is passed to :option:`--always-true <mypy --always-true>` or :option:`--always-false <mypy --always-false>`. |
| (However, ``True`` and ``False`` are not treated specially!) |
| |
| .. note:: |
| |
| Mypy currently does not support more complex checks, and does not assign |
| any special meaning when assigning a :py:data:`sys.version_info` or :py:data:`sys.platform` |
| check to a variable. This may change in future versions of mypy. |
| |
| By default, mypy will use your current version of Python and your current |
| operating system as default values for ``sys.version_info`` and |
| ``sys.platform``. |
| |
| To target a different Python version, use the :option:`--python-version X.Y <mypy --python-version>` flag. |
| For example, to verify your code typechecks if were run using Python 2, pass |
| in :option:`--python-version 2.7 <mypy --python-version>` from the command line. Note that you do not need |
| to have Python 2.7 installed to perform this check. |
| |
| To target a different operating system, use the :option:`--platform PLATFORM <mypy --platform>` flag. |
| For example, to verify your code typechecks if it were run in Windows, pass |
| in :option:`--platform win32 <mypy --platform>`. See the documentation for :py:data:`sys.platform` |
| for examples of valid platform parameters. |
| |
| .. _reveal-type: |
| |
| Displaying the type of an expression |
| ------------------------------------ |
| |
| You can use ``reveal_type(expr)`` to ask mypy to display the inferred |
| static type of an expression. This can be useful when you don't quite |
| understand how mypy handles a particular piece of code. Example: |
| |
| .. code-block:: python |
| |
| reveal_type((1, 'hello')) # Revealed type is 'Tuple[builtins.int, builtins.str]' |
| |
| You can also use ``reveal_locals()`` at any line in a file |
| to see the types of all local variables at once. Example: |
| |
| .. code-block:: python |
| |
| a = 1 |
| b = 'one' |
| reveal_locals() |
| # Revealed local types are: |
| # a: builtins.int |
| # b: builtins.str |
| .. note:: |
| |
| ``reveal_type`` and ``reveal_locals`` are only understood by mypy and |
| don't exist in Python. If you try to run your program, you'll have to |
| remove any ``reveal_type`` and ``reveal_locals`` calls before you can |
| run your code. Both are always available and you don't need to import |
| them. |
| |
| |
| .. _import-cycles: |
| |
| Import cycles |
| ------------- |
| |
| An import cycle occurs where module A imports module B and module B |
| imports module A (perhaps indirectly, e.g. ``A -> B -> C -> A``). |
| Sometimes in order to add type annotations you have to add extra |
| imports to a module and those imports cause cycles that didn't exist |
| before. If those cycles become a problem when running your program, |
| there's a trick: if the import is only needed for type annotations in |
| forward references (string literals) or comments, you can write the |
| imports inside ``if TYPE_CHECKING:`` so that they are not executed at runtime. |
| Example: |
| |
| File ``foo.py``: |
| |
| .. code-block:: python |
| |
| from typing import List, TYPE_CHECKING |
| |
| if TYPE_CHECKING: |
| import bar |
| |
| def listify(arg: 'bar.BarClass') -> 'List[bar.BarClass]': |
| return [arg] |
| |
| File ``bar.py``: |
| |
| .. code-block:: python |
| |
| from typing import List |
| from foo import listify |
| |
| class BarClass: |
| def listifyme(self) -> 'List[BarClass]': |
| return listify(self) |
| |
| .. note:: |
| |
| The :py:data:`~typing.TYPE_CHECKING` constant defined by the :py:mod:`typing` module |
| is ``False`` at runtime but ``True`` while type checking. |
| |
| Python 3.5.1 doesn't have :py:data:`~typing.TYPE_CHECKING`. An alternative is |
| to define a constant named ``MYPY`` that has the value ``False`` |
| at runtime. Mypy considers it to be ``True`` when type checking. |
| Here's the above example modified to use ``MYPY``: |
| |
| .. code-block:: python |
| |
| from typing import List |
| |
| MYPY = False |
| if MYPY: |
| import bar |
| |
| def listify(arg: 'bar.BarClass') -> 'List[bar.BarClass]': |
| return [arg] |
| |
| .. _not-generic-runtime: |
| |
| Using classes that are generic in stubs but not at runtime |
| ---------------------------------------------------------- |
| |
| Some classes are declared as generic in stubs, but not at runtime. Examples |
| in the standard library include :py:class:`os.PathLike` and :py:class:`queue.Queue`. |
| Subscripting such a class will result in a runtime error: |
| |
| .. code-block:: python |
| |
| from queue import Queue |
| |
| class Tasks(Queue[str]): # TypeError: 'type' object is not subscriptable |
| ... |
| |
| results: Queue[int] = Queue() # TypeError: 'type' object is not subscriptable |
| |
| To avoid these errors while still having precise types you can either use |
| string literal types or :py:data:`~typing.TYPE_CHECKING`: |
| |
| .. code-block:: python |
| |
| from queue import Queue |
| from typing import TYPE_CHECKING |
| |
| if TYPE_CHECKING: |
| BaseQueue = Queue[str] # this is only processed by mypy |
| else: |
| BaseQueue = Queue # this is not seen by mypy but will be executed at runtime. |
| |
| class Tasks(BaseQueue): # OK |
| ... |
| |
| results: 'Queue[int]' = Queue() # OK |
| |
| If you are running Python 3.7+ you can use ``from __future__ import annotations`` |
| as a (nicer) alternative to string quotes, read more in :pep:`563`. For example: |
| |
| .. code-block:: python |
| |
| from __future__ import annotations |
| from queue import Queue |
| |
| results: Queue[int] = Queue() # This works at runtime |
| |
| .. _silencing-linters: |
| |
| Silencing linters |
| ----------------- |
| |
| In some cases, linters will complain about unused imports or code. In |
| these cases, you can silence them with a comment after type comments, or on |
| the same line as the import: |
| |
| .. code-block:: python |
| |
| # to silence complaints about unused imports |
| from typing import List # noqa |
| a = None # type: List[int] |
| |
| |
| To silence the linter on the same line as a type comment |
| put the linter comment *after* the type comment: |
| |
| .. code-block:: python |
| |
| a = some_complex_thing() # type: ignore # noqa |
| |
| Covariant subtyping of mutable protocol members is rejected |
| ----------------------------------------------------------- |
| |
| Mypy rejects this because this is potentially unsafe. |
| Consider this example: |
| |
| .. code-block:: python |
| |
| from typing_extensions import Protocol |
| |
| class P(Protocol): |
| x: float |
| |
| def fun(arg: P) -> None: |
| arg.x = 3.14 |
| |
| class C: |
| x = 42 |
| c = C() |
| fun(c) # This is not safe |
| c.x << 5 # Since this will fail! |
| |
| To work around this problem consider whether "mutating" is actually part |
| of a protocol. If not, then one can use a :py:class:`@property <property>` in |
| the protocol definition: |
| |
| .. code-block:: python |
| |
| from typing_extensions import Protocol |
| |
| class P(Protocol): |
| @property |
| def x(self) -> float: |
| pass |
| |
| def fun(arg: P) -> None: |
| ... |
| |
| class C: |
| x = 42 |
| fun(C()) # OK |
| |
| Dealing with conflicting names |
| ------------------------------ |
| |
| Suppose you have a class with a method whose name is the same as an |
| imported (or built-in) type, and you want to use the type in another |
| method signature. E.g.: |
| |
| .. code-block:: python |
| |
| class Message: |
| def bytes(self): |
| ... |
| def register(self, path: bytes): # error: Invalid type "mod.Message.bytes" |
| ... |
| |
| The third line elicits an error because mypy sees the argument type |
| ``bytes`` as a reference to the method by that name. Other than |
| renaming the method, a work-around is to use an alias: |
| |
| .. code-block:: python |
| |
| bytes_ = bytes |
| class Message: |
| def bytes(self): |
| ... |
| def register(self, path: bytes_): |
| ... |
| |
| Using a development mypy build |
| ------------------------------ |
| |
| You can install the latest development version of mypy from source. Clone the |
| `mypy repository on GitHub <https://github.com/python/mypy>`_, and then run |
| ``pip install`` locally: |
| |
| .. code-block:: text |
| |
| git clone --recurse-submodules https://github.com/python/mypy.git |
| cd mypy |
| sudo python3 -m pip install --upgrade . |