Skip to content
Merged
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
44 changes: 44 additions & 0 deletions docs/source/common_issues.rst
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,47 @@ understand how mypy handles a particlar piece of code. Example:
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.

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 False:`` so that they are not executed at runtime.
The reason this works is that mypy (currently) does not analyze
unreachable code like this. Example:

File ``foo.py``:

.. code-block:: python

from typing import List

if False:
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::

It is possible that in the future, mypy will change its dead code
analysis and this trick will stop working. We will then offer an
alternative, e.g. a constant defined by the ``typing`` module that
is ``False`` at runtime but ``True`` while type checking.