Skip to content

Switch type checking from mypy to Pyrefly (#8182) - #8227

Open
rosspeili wants to merge 6 commits into
quantumlib:mainfrom
rosspeili:switch-to-pyrefly-8182
Open

rosspeili wants to merge 6 commits into
quantumlib:mainfrom
rosspeili:switch-to-pyrefly-8182

Conversation

@rosspeili

@rosspeili rosspeili commented Jul 26, 2026 •

Copy link
Copy Markdown
Contributor

Switch type checking from mypy to Pyrefly per 8182, also includes the check/typecheck rename/deprecation from 8225, can close once this lands.

  1. Migrated [tool.mypy] with pyrefly init, then set monorepo search-path to match dev_tools/pypath.
  2. Excluded notebooks (and generated cirq_google/cloud) as discussed on 8182.
  3. Mapped mypy’s follow_imports=silent/skip third-party posture to ignore-missing-imports + replace-imports-with-any for sympy/networkx/pandas/protobuf.
  4. Fixed two first-party issues similar to OpenFermion take (dtype is not None, cast before sorted for Qids).
  5. Added check/typecheck, deprecated check/mypy (remove in v1.8), updated CI / check/all / shellcheck / deps / docs.

notes

  • Left mypy-protobuf / --mypy_out alone (stub generation, not the typechecker CLI).
  • Some Pyrefly error kinds that are much stricter than Cirq’s old silent-import mypy setup are disabled in [tool.pyrefly.errors] for this migration.

Test plan

  • pyrefly check → 0 errors locally
  • black / ruff clean on touched Python
  • pytest on touched modules
  • CI Type check job green

Fixes #8182

@rosspeili
rosspeili requested a review from a team as a code owner July 26, 2026 14:36
@rosspeili
rosspeili requested a review from viathor July 26, 2026 14:36
@github-actions github-actions Bot added the size: L 250< lines changed <1000 label Jul 26, 2026
@rosspeili

Copy link
Copy Markdown
Contributor Author

Config choices and follow-up

Since pyrefly is stricter than cirq’s previous mypy config (follow_imports=silent on sympy/networkx/pandas/protobuf), after mapping that to replace-imports-with-any, hundreds of first-party diagnostics remained (bad-argument-type, overload/kwargs patterns, etc.) that mypy did not effectively enforce. Per #8182 (“fix or adjust config for low-priority”), those kinds are disabled for now so the tool switch stays green without cirq-wide annotation rewrite.

Same idea as the OpenFermion pyrefly migration (#1433): migrate the checker first, tighten selectively later.

Suggested follow-up unless otherwise advised

  1. Re-enable error kinds one at a time (start with bad-return / missing-attribute).
  2. Fix or narrowly # type: ignore real first-party issues.
  3. Prefer that over expanding replace-imports-with-any.

Happy to open that follow-ups after this lands, or adjust the disable list here if you’d rather tighten in this PR.

@pavoljuhas @mhucka, this also covers #8225’s check/typecheck / deprecate-check/mypy bits.

@codecov

codecov Bot commented Jul 26, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.59%. Comparing base (cfa8a84) to head (6eccdbc).
⚠️ Report is 11 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8227      +/-   ##
==========================================
- Coverage   99.59%   99.59%   -0.01%     
==========================================
  Files        1125     1127       +2     
  Lines      103250   103414     +164     
==========================================
+ Hits       102829   102992     +163     
- Misses        421      422       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mhucka mhucka self-assigned this Sep 2, 2026
@mhucka mhucka added the triage/discuss Needs decision / discussion, bring these up during Cirq Cynque label Sep 2, 2026
@mhucka

mhucka commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Discussed in Cirq Cynq 2026-09-02:

We'll try to do this before 1.8.

@mhucka mhucka assigned pavoljuhas and unassigned mhucka Sep 2, 2026
@mhucka mhucka added the priority/before-1.8 Leave for after the Cirq 1.7 release label Sep 2, 2026
@rosspeili

Copy link
Copy Markdown
Contributor Author

@mhucka you want me to rebase and clean up any arising conflicts or you'll do during merge?

@pavoljuhas
pavoljuhas self-requested a review September 3, 2026 18:51
@pavoljuhas

Copy link
Copy Markdown
Collaborator

@rosspeili - please hold on with the rebase. I will merge the main branch myself.

@pavoljuhas pavoljuhas 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.

As it is, the PR removes mypy and suppresses most pyrefly errors - effectively leaving the code without type check. Let us loosely follow the advice at https://pyrefly.org/en/docs/migrating-from-mypy/#3-handle-the-new-errors-and-drop-mypy instead, i.e., please restore mypy and keep it active in the CI. For the initial pyrefly config please generate and commit the "pyrefly-baseline.json" file and configure pyrefly to use it as its baseline.

This will enforce pyrefly for any changed code. We can then gradually work on errors suppressed in pyrefly-baseline.json until it is not needed anymore. Once we get there, we can remove mypy and use the pyrefly only.

Comment thread check/mypy
@@ -1,7 +1,7 @@
#!/usr/bin/env bash

################################################################################
# Runs mypy on the repository.

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.

Please restore to the main version. We will keep mypy around for the time of transition.

@@ -154,7 +154,10 @@ def __init__(

@property
def qubits(self) -> tuple[cirq.Qid, ...]:
return cast(tuple['cirq.Qid', ...], tuple(sorted(self.device_graph.vertices)))
return cast(

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.

Please revert, this does not make a difference at this point.

Comment thread check/typecheck
@@ -13,4 +13,4 @@ repo_dir=$(git -C "${thisdir}" rev-parse --show-toplevel) || exit $?
cd "${repo_dir}" || exit $?

source dev_tools/pypath || exit $?
mypy "$@" .

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.

Please update to run both mypy and typecheck, for example,

mypy "$@" . && pyrefly check

For now we can ignore the command-line arguments for pyrefly and add them there after dropping mypy.

@@ -0,0 +1,6 @@
# Type checking tool
pyrefly==1.2.0

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.

Please add mypy==2.1.0 back here.

Comment thread dev_tools/bash_scripts_test.py Outdated
@@ -49,6 +49,7 @@ def run(
'pylint',
'env',
'pytest',
'pyrefly',

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.

Not necessary, please revert.

Comment thread docs/dev/development.md Outdated
@@ -163,12 +163,12 @@ This script uses the `grpcio-tools` package to generate the Python proto API.

There are a few options for running continuous integration checks, varying from easy and fast to slow and reliable.

The simplest way to run checks is to invoke `pytest`, `pylint`, or `mypy` for yourself as follows:
The simplest way to run checks is to invoke `pytest`, `pylint`, or `pyrefly` for yourself as follows:

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.

Please revert this file, for the transition we will use mypy as the main type checker.

Comment thread pyproject.toml
Comment on lines -46 to -49
[tool.mypy]
exclude = [
'/setup\.py',
'cirq-google/cirq_google/cloud/',

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.

Please restore the mypy section.

Comment thread pyproject.toml

# Checks that are much stricter than mypy under Cirq's silent-import setup.
# Tracked for follow-up tightening after the tool switch.
[tool.pyrefly.errors]

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.

This would essentially disable typechecking. For consistency with our internal config, please use

redundant-cast = "error"
unused-type-ignore = "error"

Instead of disabling most errors, we should generate and commit the "pyrefly-baseline.json" file following the advice at https://pyrefly.org/en/docs/migrating-from-mypy/#3-handle-the-new-errors-and-drop-mypy. When pyrefly checks against the baseline file, it will flag typing errors in any new code. We can then gradually work on fixing the errors in the baseline file so it is eventually not necessary and can be removed. At that point we can drop mypy and use pyrefly only.

Comment thread pyproject.toml
Comment on lines +283 to +290
"**/setup.py",
"**/cirq-google/cirq_google/cloud/**",
"**/*.ipynb",
"**/docs/**",
"**/__pycache__/**",
"**/.venv/**",
"**/venv/**",
"**/node_modules/**",

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.

Are all of these needed? Please keep only the patterns which may match some files in the search-path above.

Add check/typecheck, deprecate check/mypy, and wire CI/deps/docs.
Migrate config from mypy with monorepo search-path and notebook excludes.
Restore mypy as the primary type checker during the Pyrefly transition.
Run both mypy and pyrefly in check/typecheck, commit pyrefly-baseline.json
so only new/changed code must satisfy Pyrefly, and revert docs to reference
mypy per maintainer feedback.
@rosspeili
rosspeili force-pushed the switch-to-pyrefly-8182 branch from 3476384 to 53ee0cc Compare September 6, 2026 11:54
@github-actions github-actions Bot added size: XL lines changed >1000 and removed size: L 250< lines changed <1000 labels Sep 6, 2026
Fixes check/misc EOF whitespace failure in CI.
Add stim to pyrefly ignore-missing-imports (matching mypy) and baseline
entries for numpy typing errors seen in CI on Python 3.11.
@rosspeili

Copy link
Copy Markdown
Contributor Author

Hey @pavoljuhas, all points addressed the best I could. Will tweak if CI has issues. Let me know how this looks, and any feedback and directional tips more than welcome <3

Comment thread check/typecheck Outdated
Drop the ANSI red prefix and EXIT trap; mypy and pyrefly already
colorize their own output when FORCE_COLOR is set.
@rosspeili

Copy link
Copy Markdown
Contributor Author

Good catch @mhucka and yes, that would have turned all mypy/pyrefly output red until exit. Removed in last commit as both tools already colorize their own output via FORCE_COLOR=1.

@mhucka mhucka added area/typecheck and removed triage/discuss Needs decision / discussion, bring these up during Cirq Cynque labels Sep 16, 2026
@mhucka mhucka added the area/devops Involving development tools, procedures, documentation, services, and so on label Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/devops Involving development tools, procedures, documentation, services, and so on area/typecheck priority/before-1.8 Leave for after the Cirq 1.7 release size: XL lines changed >1000

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Switch from mypy to Pyrefly

3 participants