Skip to content

Type-check package sources with Pyrefly strict mode - #237

Merged
janluke merged 4 commits into
masterfrom
codex/pyrefly-strict
Sep 11, 2026
Merged

Type-check package sources with Pyrefly strict mode#237
janluke merged 4 commits into
masterfrom
codex/pyrefly-strict

Conversation

@janluke

@janluke janluke commented Sep 11, 2026

Copy link
Copy Markdown
Owner

This makes src/cloup pass and run under Pyrefly's strict preset while tests and examples retain the default policy. Note that we use Mypy in the same way.

Fixes include the use of @override for all overridden methods. Since this was introduced in Python 3.12 and we support Python 3.10, typing_extensions is now installed also on Python 3.11.

See the individual commit messages for the motivation and typing details of each change.

Closes #234.

Pyrefly's strict preset requires concrete overrides to be declared with
@OverRide. Mark the methods that intentionally replace Click or Cloup base
implementations, including the concrete implementations of the overloaded
command and group decorators.

Besides satisfying strict checking, these markers make inheritance assumptions
executable: a checker will report a renamed or removed base method instead of
silently treating the subclass method as unrelated.

Use typing.override where available and typing_extensions.override on Python
3.10 and 3.11. Extend the existing conditional typing_extensions dependency
through Python 3.11 so importing Cloup does not rely on an undeclared runtime
package.
The public signatures for argument(), option(), and Option live in
_params.pyi, but Pyrefly also checks the implementation file in strict mode.
Its previously unannotated variadic parameters and nested decorators therefore
became implicit Any errors.

Add broad implementation annotations that agree with the stub while leaving
the detailed keyword contract in one place. Use the existing callback type
variable so each decorator remains explicitly identity-preserving.

Once the callback is typed, reading __click_params__ from it is invalid because
Click creates that private attribute dynamically inside _param_memo(). Keep the
newly constructed Option instead of retrieving the same object from that list,
and use setattr for Cloup's intentional dynamic group extension. This preserves
the existing attach-then-configure order without hiding the value behind Any.
_constraint_memo() attaches a list dynamically to decorated callbacks. An
empty list provides no element evidence, so Pyrefly strict mode inferred Any
for its contents and reported the container.

Annotate the newly created accumulator with the same BoundConstraintSpec /
BoundConstraint union accepted by the function. This documents the dynamic
attribute's invariant without changing its runtime representation.
The default preset was useful for initial adoption, but the distributable
package is fully annotated and can support Pyrefly's stricter diagnostics.
Check src with the strict preset while tests and examples retain the default
policy introduced with the initial Pyrefly integration.

Pyrefly does not permit preset selection inside a sub-config. Run the two
scopes separately in the Hatch typing script so src uses the real strict
preset instead of copying its current settings into pyproject.toml. This also
means future changes to Pyrefly's strict preset are exercised automatically.

Run the strict source check first for fast feedback, followed by the default
tests and examples check. Task and CI matrix entry points continue to invoke
the same Hatch script.
@codecov

codecov Bot commented Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.86%. Comparing base (81af894) to head (f1cd739).

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #237      +/-   ##
==========================================
+ Coverage   96.71%   96.86%   +0.14%     
==========================================
  Files          22       22              
  Lines        1552     1626      +74     
==========================================
+ Hits         1501     1575      +74     
  Misses         51       51              

☔ 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.

@janluke
janluke merged commit dd1d1a8 into master Sep 11, 2026
15 checks passed
@janluke
janluke deleted the codex/pyrefly-strict branch September 11, 2026 14:43
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.

Use Pyrefly in strict mode for src/

1 participant