Pyrefly Coverage
pyrefly coverage measures how much of your code is annotated with types. It has two subcommands:
pyrefly coverage checkfails when coverage is below a threshold, useful as a CI gate.pyrefly coverage reportemits a JSON report with per-module statistics.
The output format and behavior may change in future releases without notice.
How coverage is measured
Coverage is counted over typables: function return types, function parameters, module-level
variables, and class attributes. Each typable is either typed (annotated, no Any in the
resolved type), any (annotated, but the resolved type contains Any), or untyped (no
annotation).
- Coverage is the percentage of typables that are annotated;
Anycounts as covered. - Strict coverage is the percentage of typables that are typed;
Anydoesn't count.
Only public symbols count: names without a leading underscore, plus anything in __all__.
self/cls are not typable, overloads are merged, and .py files are skipped when their .pyi
stub is also analyzed (--prefer-stubs=false disables this). With --public-only, only symbols
reachable from public modules via re-export chains count: the library's public API.
Checking coverage against a threshold
pyrefly coverage check robot/ --fail-under 60
On success it prints a one-line summary and exits 0:
INFO type coverage 66.67% (4 of 6 typable)
Otherwise it exits non-zero and reports every offending symbol in the same style as
pyrefly check, as coverage-missing (no annotations at all) or coverage-partial (only some):
WARN `walk` is not fully typed [coverage-partial]
--> robot/legs.py:1:1
|
1 | / def walk(speed, direction: str) -> None:
2 | | print(f"walking {speed} {direction}")
| |_________________________________________-
|
WARN `stop` is untyped [coverage-missing]
--> robot/legs.py:5:1
|
5 | / def stop():
6 | | print("stopping")
| |_____________________-
|
ERROR type coverage 66.67% (4 of 6 typable) is below the 100.00% threshold
With --strict, annotations that resolve to Any count as untyped. The findings format is
configurable with --output-format. See pyrefly coverage check --help for all flags.
Generating a JSON report
pyrefly coverage report path/to/directory/ > coverage.json
The report contains a "major.minor" schema_version, a summary, and one entry per module in
module_reports, with:
- per-symbol typed/any/untyped counts and locations (
symbol_reports) - the module's public names (
names) - error-suppression comments (
type_ignores) - typable totals,
coverageandstrict_coveragepercentages, and counts of functions, methods, parameters, classes, attributes, and properties
See pyrefly coverage report --help for all flags. The output is easy to consume with e.g. jq:
pyrefly coverage report path/to/directory/ | jq .summary.strict_coverage