Skip to content

🔧 mypy: enable strict type checking on src#795

Merged
GeigerJ2 merged 2 commits into
aiidateam:mainfrom
GeigerJ2:ci/mypy-on-src
Jun 29, 2026
Merged

🔧 mypy: enable strict type checking on src#795
GeigerJ2 merged 2 commits into
aiidateam:mainfrom
GeigerJ2:ci/mypy-on-src

Conversation

@GeigerJ2

@GeigerJ2 GeigerJ2 commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

The mypy pre-commit hook excluded all of src/, so nothing under it was ever actually type-checked. This turns it on with a strict config and gets the already-clean modules checked, without a big annotation push up front. The main decisions:

  • strict = true is enforced everywhere; modules that aren't annotated yet are parked in an ignore_errors list that shrinks one module at a time. Global strictness is never relaxed to silence errors, so the list only ever gets emptied (the opposite of ratcheting strictness up flag by flag).
  • On top of strict, a few off-by-default error codes are enabled (deprecated, possibly-undefined, mutable-override, truthy-iterable, exhaustive-match, etc.); all pass on the checked modules.
  • yaml and tabulate are checked against real stubs (types-PyYAML, types-tabulate, pinned to the runtime package versions); the genuinely untyped deps (node_graph, aiida_pythonjob, kiwipy) stay on ignore_missing_imports.
  • The hook runs with language: system and pass_filenames: false against a fixed src/aiida_workgraph target, so a commit, pre-commit run --all-files, and a bare mypy all check the whole tree (an incremental commit can't pass while breaking a caller in an unchanged module). mypy is pinned ~=2.1.0 in the pre-commit extra, matching aiida-core.

explicit-override is left for a follow-up, since requiring @override means a sweep across the existing class hierarchies.

The mypy pre-commit hook excluded all of `src/`, so nothing was actually
type-checked. Enable it: drop `src/.*` from the hook's exclude and add a
strict `[tool.mypy]` config (`strict = true`).

Strictness is enforced everywhere rather than ratcheted up flag by flag.
The 17 modules that already pass are checked now; the 35 not yet
annotated are listed under an `ignore_errors` override and get removed
from that list one by one as they are typed. The global strictness is
never relaxed to silence errors; the goal is to empty that list.

Third-party deps without type information (node_graph, aiida_pythonjob,
kiwipy, yaml, tabulate) are handled with `ignore_missing_imports`.

Pin `mypy~=2.1.0` in the `pre-commit` extra so the hook environment
provides it in CI; update the lockfile accordingly.
The mypy pre-commit hook excluded all of `src/`, so nothing was
actually type-checked. Enable it: drop `src/.*` from the hook's
exclude and add a strict `[tool.mypy]` config (`strict = true`).

Strictness is enforced everywhere rather than ratcheted up flag by
flag. The 17 modules that already pass are checked now; the 35 not
yet annotated are listed under an `ignore_errors` override and get
removed from that list one by one as they are typed. The global
strictness is never relaxed to silence errors; the goal is to empty
that list.

On top of `strict`, enable several off-by-default error codes
(`deprecated`, `exhaustive-match`, `mutable-override`,
`possibly-undefined`, `redundant-self`, `truthy-iterable`,
`unimported-reveal`, `unused-awaitable`); all pass on the checked
modules.

Third-party deps without type information (node_graph, aiida_pythonjob,
kiwipy) are handled with `ignore_missing_imports`; yaml and tabulate
are checked against the types-PyYAML and types-tabulate stubs in the
`pre-commit` extra, pinned to match the runtime package versions.

Run the hook with `language: system` so it uses the mypy from the
activated dev/CI environment instead of building an isolated env that
cannot import the project, and with `pass_filenames: false` against a
fixed `files = ['src/aiida_workgraph']` target so every run checks the
whole tree (an incremental commit can no longer miss a broken caller
in an unchanged module). Pin `mypy~=2.1.0` in the `pre-commit` extra
so that environment provides it, and update the lockfile accordingly.
@GeigerJ2 GeigerJ2 marked this pull request as ready for review June 25, 2026 12:32

@elinscott elinscott left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mypy pre-commit hook excluded all of src/
... or, indeed, did not exist in the first place 🤦

I would also be in favour of a github test that runs mypy without the list of files to skip, just so we don't forget to eventually get that list down to zero.

@GeigerJ2 GeigerJ2 merged commit 0c6fe3c into aiidateam:main Jun 29, 2026
6 checks passed
@GeigerJ2 GeigerJ2 deleted the ci/mypy-on-src branch June 29, 2026 09:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants