mypy tips
Following are some tips from my experience of using mypy.
Making your module type checking compatible §
Follow the steps in the mypy documentation on “Making PEP 561 compatible packages”.
In short, this consists of:
- Add an empty
py.typed
file into your module’s root (adjacent to the__init__.py
file). - Add
package_data={"": ["py.typed"]}
to yoursetup.py
to include thepy.typed
at build time.
It should now be possible for other modules to import this module, and avoid type checking errors upon import. Of course, you’ll still need to add type hinting to your module for this to actually be useful.
If you get errors, mypy has good documentation on how to resolve these.
Note that there are two other ways of enabling type checking, using stub files, or using stub only packages. My preference is for the first method of inline type annotations.
Cyclical imports §
Adding type checking can introduce cylical imports.
This can be avoided through first using if TYPE_CHECKING:
to conditionally import the necessary modules. This will be True
when type checking is performed, and False
otherwise (e.g. at runtime).
Then, put the affected imports as strings, e.g. "MyClass"
. This allows the imports to not be present at runtime, but when type checking occurs, mypy will infer the type from the string.
Optional imports §
Alternatively, type checking can require all optional dependencies to be present, which can be problematic!
For example, consider having module A, which at runtime depends upon having module B xor C present - it doesn’t require both. However, the type checker does require both. This contradiction can be resolved using the same method as for resolving cyclical imports:
Signal handling §
For signal handlers:
- The
frame
type isFrameType
. - The
signum
type isint
, or perhapsUnion[int, Signals]
?
Common Uncommon Types §
The common types such as int
and str
and quite straight-forward. But some of the less-common common types are not quite so straight-forward.
Queue §
In Python 3.6 or below, the queue.Queue
type requires specifying as a string, e.g.:
In Python 3.7 or above, you can put from __future__ import annotations
in your imports and use Queues as normal, e.g.: