pyfaro check¶
pyfaro check is the one command for "is my project clean?". It runs the
format check, the linter and the type checker, then prints a three-line
summary. Use it before committing and as the quality gate in CI.
Quick example¶
$ pyfaro check
3 files already formatted
All checks passed!
All checks passed!
== pyfaro check summary ==
format: ok
lint: ok
type: ok
check: ok
Steps¶
check runs these steps in this order, and always runs all of them, even
when an earlier one fails:
format—ruff format --checklint—ruff checktype—ty check
Each tool's own output streams through as it runs, so reading from the top
shows format output first, then lint, then type. PATHS and --project
apply to every step.
The summary¶
After the steps, check prints a blank line, a == pyfaro check summary ==
header and one line per step, to stderr (stdout carries only the tools'
output). Each step is ok, failed (exit N) with the tool's exit code, or
unavailable (…). The last line is check: ok, or check: failed (…) listing
the failing steps.
Scenarios¶
The examples use pyfaro create lib demo plus src/demo/messy.py and
scripts/tool.py: unformatted, with unused imports, and one type error.
A failing project¶
$ pyfaro check
…
== pyfaro check summary ==
format: failed (exit 1)
lint: failed (exit 1)
type: failed (exit 1)
check: failed (format, lint, type)
Fix everything the tools can fix with --fix (below), then repair the rest by
hand.
Restrict to some paths¶
Paths are relative to the directory where you ran pyfaro:
$ pyfaro check src/demo/messy.py
1 file already formatted
F401 [*] `os` imported but unused
…
Found 2 errors.
[*] 2 fixable with the `--fix` option.
error[invalid-return-type]: Return type does not match returned value
…
Found 1 diagnostic
== pyfaro check summary ==
format: ok
lint: failed (exit 1)
type: failed (exit 1)
check: failed (lint, type)
Apply safe fixes first: --fix¶
pyfaro check --fix applies automatic fixes, then verifies. The sequence is:
- Print which checks can be fixed: format and lint can; type cannot.
ruff check --fix— safe fixes only. Pyfaro never passes--unsafe-fixes.ruff format— rewrites files. Formatting comes last so that lint fixes cannot leave unformatted code behind.- Re-run the full non-writing verification and print the summary.
$ pyfaro check --fix
fix: format and lint can be fixed automatically; type has no automatic fixes
Found 3 errors (3 fixed, 0 remaining).
fix lint: ok
2 files reformatted, 3 files left unchanged
fix format: ok
fix: rechecking without writing
5 files already formatted
All checks passed!
error[invalid-return-type]: Return type does not match returned value
--> src/demo/messy.py:6:12
|
5 | def label(n: int) -> str:
| --- Expected `str` because of return type
6 | return n
| ^ expected `str`, found `int`
Found 1 diagnostic
== pyfaro check summary ==
format: ok
lint: ok
type: failed (exit 1)
check: failed (type)
The unused imports are gone and the code is formatted; only the type error,
which needs a human, remains. A failure in a fix step (fix lint: failed
(exit 2)) is reported but does not stop the next step. The exit code follows
the final verification.
Another project: --project¶
--project <PATH> selects the project directory explicitly; otherwise the
nearest pyproject.toml upward is used.
Unavailable steps¶
If a tool is not installed, only its steps are marked unavailable, count as
failures, and the others still run. In a project that was never synced:
$ pyfaro check
== pyfaro check summary ==
format: unavailable (ruff not found in the project environment, VIRTUAL_ENV, or PATH; run `pyfaro add --dev ruff` then `pyfaro sync`)
lint: unavailable (ruff not found in the project environment, VIRTUAL_ENV, or PATH; run `pyfaro add --dev ruff` then `pyfaro sync`)
type: unavailable (ty not found in the project environment, VIRTUAL_ENV, or PATH; run `pyfaro add --dev ty` then `pyfaro sync`)
check: failed (format, lint, type)
With --fix the fix steps are unavailable the same way, and the recheck
follows:
$ pyfaro check --fix
fix: format and lint can be fixed automatically; type has no automatic fixes
fix lint: unavailable (ruff not found in the project environment, VIRTUAL_ENV, or PATH; run `pyfaro add --dev ruff` then `pyfaro sync`)
fix format: unavailable (ruff not found in the project environment, VIRTUAL_ENV, or PATH; run `pyfaro add --dev ruff` then `pyfaro sync`)
fix: rechecking without writing
…
Path handling¶
Same as the individual commands: paths are relative to your current
directory, tools run from the project root, and with explicit paths
--force-exclude keeps your configured exclusions in force.
Configuration¶
check has none of its own. Ruff reads [tool.ruff] (or ruff.toml) and ty
reads [tool.ty] (or ty.toml); see lint, fmt and
type for exclusions. Pyfaro passes no overrides.
Guarantees¶
- No implicit sync.
.venvanduv.lockare never created or modified. - No writes without
--fix. Plaincheckpasses--checktoruff format, never passes--fixtoruff check, andty checkdoes not write. The tools may refresh their own caches (such as.ruff_cache). - With
--fix, source files can be rewritten. Review the result withgit diff.
Exit codes¶
| Code | Meaning |
|---|---|
0 |
Every step passed |
1 |
Any step failed or was unavailable, or a Pyfaro failure (no project) |
130 |
Cancelled |
The tools' own exit codes appear in the summary, not in check's exit code.
See also¶
pyfaro lint,pyfaro fmt,pyfaro type— the individual steps.pyfaro test— run the tests (not part ofcheck).pyfaro doctor— diagnose a missing tool.