Skip to content

Type checking for Python code#3382

Open
fedimser wants to merge 23 commits into
mainfrom
fedimser/mypy-1
Open

Type checking for Python code#3382
fedimser wants to merge 23 commits into
mainfrom
fedimser/mypy-1

Conversation

@fedimser

@fedimser fedimser commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

This PR:

  • Adds an option to run python static checks using build.py. Currently it only runs type checks using pyright, but more static checks (line length, linter, formatter) can be added here.
  • Adds a new CI workflow that installs minimal requirements and runs the static checks.
  • Fixes code to make static checks pass.

Notes:

  • I only check Python code in source/qdk_package/qdk.
  • Type checking requires different dependencies than tests, so I created a new file check_requirements.txt that includes minimal dependencies that are required to run static checks. This minimizes setup time for CI workflow.

The type checking can be done in multiple ways:

  • pyright - runs pyright directly.
  • ./build.py --check-py - recommended. This installs required dependencies and runs mypy, and doesn't do anything else. If this passes locally, it's guaranteed that it will pass on CI.
  • python ./build.py --check-py --no-check-prereqs - like above, but skips checking prerequisites (like wasm) which are irrelevant for Python. This is used in the CI workflow.
  • Run build.py in a way that includes building qdk and doesn't disable checks. This includes build.py --qdk and build.py with no arguments.

Missing checks (will be added in follow-up PRs):

  • If we remove 6 excluded modules and specify "reportMissingParameterType": "error" and "typeCheckingMode": "strict" in pyrightconfig.json, we get 2745 errors. I plan to gradually fix them in a series of PRs.

@fedimser fedimser marked this pull request as ready for review June 24, 2026 21:10
matplotlib
pandas>=2.1
pandas-stubs
pyqir>=0.12.5,<0.13

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do these need to be installed for the checks? Does it need to verify the types from any package your our code may use? (In which case, would it need to ultimately extend to qiskit, cirq, etc.)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

When typechecker sees import statement and library is not installed, it raises an error (both mypy and pyright).
There are 2 ways to deal with it:

  1. Have the library installed (or "type stubs" which provides type signatures for public API) - then you get all calls to the library type-checked.
  2. Ignore this import - then all calls to the library are not type-checked, reducing usefulness of type checking.

We can make this choice for every library we import, this is why I created this separate requirements file. I chose to install matplotlib, pandas and pyqir rather than ignoring them.

Yes, I intend to ultimately extend it here to use other libraries, like cirq and qiskit, but I want to be able to make this choice for each library. If I see that some library would take a lot of time to install (e.g. cirq that has a lot of dependencies) and is used only in few limited places, I can ignore it or maybe only install type stubs.

Comment thread build.py
)

parser.add_argument(
"--check-py",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The existing check flag does JavaScript/TypeScript and Rust. Is there a reason to add a distinct Python check flag than just roll it into the existing check (if building a Python package).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes,

  1. So I can run Python checks only without having to wait for Rust and TypeScript checks that might be irrelevant for me if I am only working on Python code.
  2. So we can call call build.py --check-py in CI workflow for python static checks.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If we're going to split it out, I'd lean towards splitting all of them out and then having check mean "check all".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I talked to @swernli about this and he suggested the same - having an option in build.py to run every check separately, but this can be done in later PR.

This option exists for the following scenario: let's say you did some change to Python and "static Python check" workflow failed. You want to do fixes, verify them locally, push your changes and get workflow green as soon as possible. You do your local changes, run build.py --check-py, it passes, then you push your changes and the workflow is green.

Without this option, there would be no way to run python static checks only.

Comment thread pyrightconfig.json
"source/qdk_package/qdk/cirq",
"source/qdk_package/qdk/simulation",
"source/qdk_package/qdk/qiskit",
"source/qdk_package/qdk/qre"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do we plan to include this at a later point?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, in follow-up PRs.

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.

4 participants