Enable static type checks using mypy in CI #601
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is a first step in adding type annotations. See #558 for discussion.
Some things to pay attention to during review:
I'm using
from __future__ import annotations
to force postponed evaluation of annotations. This has several advantages:dict[str, str]
orint | None
to be used in Python versions where the interpreter doesn't support that syntax yetQuerySet
in Django 3.2, whereQuerySet
does not yet inherit fromtyping.Generic
I added
typing_extensions
as a runtime dependency. This makes it possible to use both runtime and static features from newer versions of Python in older versions as well. In particular,typing.Self
simplifies a lot of annotations, but was only added to the standard library in Python 3.11.It is possible to only use static features of
typing_extensions
and put the import within aif TYPE_CHECKING:
guard. It makes maintenance a bit more cumbersome, but it would eliminate the runtime dependency. As a lot of other libraries are usingtyping_extensions
already, I'm not sure if it avoiding the dependency indjango-model-utils
would actually make a difference in any real-world application. But if you want me to make that change, let me know.I've used Python 3.8 in the tox configuration to run mypy, because that is the one that also runs flake8 and isort. I'm not sure that's a good reason though. Another option would be to use Python 3.12, as that is the fastest. Note that mypy's results do not depend on the Python version it runs under: it always has access to all typing features it supports.
The type checking of the unit tests requires all imported libraries to exist, which is why I added
time_machine
as a dependency of the mypy env in tox. If we want to avoid that duplication, maybe it would make sense to create arequirements-testlib.txt
or add atestlib
extra tosetup.py
.It would also be possible to move
time_machine
intorequirements-test.txt
, but installing the test tools and runtime dependencies likepsycopg2-binary
isn't necessary for mypy to work and I wanted to avoid slowing down CI.