Mypy configuration
As of now, we've seen two "modes" for mypy to operate in, regular mode and "strict" mode. Regular mode seems to be a lot more lax, but it doesn't catch as many errors as it possibly can.
But there's a whole spectrum of in-between that you can set mypy to find or ignore, to suit your needs or your project's needs. We're going to take a look at that right now.
So what is --strict
really?
mypy --strict somefile.py
is actually the same as:
mypy --disallow-subclassing-any
--disallow-untyped-calls
--disallow-untyped-defs
--disallow-incomplete-defs
--check-untyped-defs
--disallow-untyped-decorators
--no-implicit-optional
--warn-redundant-casts
--warn-unused-ignores
--warn-return-any
--no-implicit-reexport
--strict-equality
somefile.py
Each of these flags makes mypy a little bit more strict. Let's look at some of the more important ones:
--disallow-incomplete-defs
and --disallow-untyped-defs
The --disallow-incomplete-defs
flag makes mypy raise an error whenever it sees
a function that has partial annotations.
Here's some example code:
def untyped(x):
print(x)
def incomplete(x: int):
print(x)
def complete(x: int) -> None:
print(x)
Running mypy with --disallow-incomplete-defs
on this code gives us:
$ mypy --disallow-incomplete-defs mycode.py
mycode.py:4: error: Function is missing a return type annotation
Found 1 error in 1 file (checked 1 source file)
--disallow-untyped-defs
is a stricter version of this, where functions with no
type hints are also flagged:
$ mypy --disallow-untyped-defs mycode.py
mycode.py:1: error: Function is missing a type annotation
mycode.py:4: error: Function is missing a return type annotation
Found 2 errors in 1 file (checked 1 source file)
--check-untyped-defs
Since mypy doesn't check the code inside untyped functions, you can run into situations like:
def foo():
return "abc" + 42
mypy
is fine with this by default:
$ mypy mycode.py
Success: no issues found in 1 source file
But you can start checking the bodies of untyped functions by doing:
$ mypy --check-untyped-defs mycode.py
mycode.py:2: error: Unsupported operand types for + ("str" and "int")
Found 1 error in 1 file (checked 1 source file)
--strict-equality
Mypy also doesn't shout about "impossible" conditionals, like these:
x = 40
x += 2
if x == "foo":
print('x is foo')
Since x
can never be a string, it's a weird conditional. But it's not flagged
by default:
$ mypy mycode.py
Success: no issues found in 1 source file
But you can do this:
$ mypy --strict-equality mycode.py
mycode.py:4: error: Non-overlapping equality check (left operand type: "int", right operand type: "Literal['foo']")
Found 1 error in 1 file (checked 1 source file)
Using a config file
The easiest way to create a config file for mypy is to make a mypy.ini
file,
and add your configuration to it. Like, if you use the following flags:
mypy --disallow-incomplete-defs --strict-equality mycode.py
You can make this config file:
[mypy]
disallow_incomplete_defs = True
strict_equality = True
And then simply running mypy mycode.py
will use the configuration.
A general config that I recommend, and use in my projects is this:
[mypy]
strict = True
exclude = setup.py|venv|build
exclude
sets the paths to ignore during a mypy run. This avoids mypy type
checking the venv
folder for example, when you do mypy .
in your project.