Repository navigation
Releases
v0.7.0
Added
check --rule <CODE>andcheck --strict/--no-strict, for the host's
steps. They mean nothing to ruff, mypy or pytest;checkparses them
into aStepOptions(rules, strict)and hands it to every extra step that
declares the newCheckStep.run_with_options(target, options). A step
without it keeps gettingrun(target). When no step reads options, a
typed--rule/--strictexits2before anything runs, instead of
passing the gate while ignoring the flag.run_full_checktakes
step_options=;StepOptionsis exported fromtempest_cli.
v0.6.0
Changed
testandcheckrun the suite in parallel by default. The
pytest-xdist run that needed--fast(-n auto -p no:cacheprovider) is
now what a baretempest-cli testdoes;--serialopts out (for
--lf/--ff, or a debugger), and--workerstunes the default
without a flag. Measured on a FastAPI service suite of 1136 tests on a
12-CPU machine: 262 s serially, 37.6 s in parallel, same outcome.- Without pytest-xdist the default degrades instead of failing. When
the environment pytest runs in cannot import it, a baretest/check
prints a one-line notice naming the install command and runs the suite
serially (exit code is pytest's); an explicit--fastkeeps the old
behavior — the fix is printed and the exit code is 127, nothing runs.
run_pytest/run_full_checktakerequire_xdist=(defaultTrue,
the old library behavior) to pick between the two. --workerswith--serialis a usage error (exit 2), as--workers
without--fastused to be.
v0.5.1
Fixed
fixexplains the E501 the formatter cannot resolve. A line still
too long afterruff formatis one the formatter has nowhere to break
— a dotted name (it never splits one, and drops parentheses that do not
make the line fit), a string literal, a comment — but the bare
Line too long (94 > 79)read as ifline-lengthwere being ignored.
fixnow reads ruff's JSON report of the leftovers and names each such
line with the overflowing token, its kind and the action that does
resolve it, then splits the residual violations into those with no
autofix and thosefix --unsafewould fix. The exit code is unchanged:
CI still fails on them. Closes #3.fixshortens the long comments and strings the formatter leaves
alone. Afterruff format, each E501 that is a comment is wrapped at
the limit (a trailing one moves above its line) and each that is a
plain string literal is split at its spaces into implicitly
concatenated parts inside parentheses; the touched files are formatted
again. Every edit is kept only when the file's AST is identical before
and after, so the program cannot change. Tool pragmas (noqa,
type: ignore,fmt:, …), f-strings, triple-quoted strings and words
longer than a line are left alone and explained instead. On by
default: neither rewrite changes behavior.fixreports on the formatted file. The passes are now
ruff check --fix-only,ruff format, thenruff check; before, the
report and the exit code came from the lint pass that ran before the
formatter, so a violation the formatter went on to resolve still showed
up and still failed the command.
v0.5.0
Added
extra_steps: a framework's own rules insidecheck. The new
CheckStep(name, run)(frozen dataclass, exported fromtempest_cli)
is a stepcheckruns aftermypyand beforepytest:runreceives
thechecktarget and returns an exit code.run_full_check(..., extra_steps=)andregister_commands(app, *, extra_steps=)take a
sequence of them — keyword-only, empty by default, so every existing
call runs the same four steps as before. Each extra step is echoed as
$ <name>on stderr, runs in list order, and the first non-zero code
stops the gate and becomes its exit code, with or without--fast.
They sit beforepytestbecause they are static checks that should
fail in a second, not after the suite. Requested in
mauriciobenjamin700/tempest-fastapi-sdk#520, where the SDK adds its
service-layer rules totempest checkwithout this package learning
about any framework.
v0.4.0
Added
-
test --fastandcheck --fast: the suite in parallel.--fast
runs pytest aspytest -n <workers> -p no:cacheprovider [target], with
pytest-xdist spreading the suite across the cores;--workers/-w
takes whatpytest -ntakes (an integer,auto— the default — or
logical) and is a usage error (exit 2) without--fast. The cache
plugin is off because several workers writing.pytest_cacheat once
is a race that buys nothing. The target is forwarded and pytest's exit
code comes straight back, as in the serial run. It is a flag rather
than atest fastsubcommand becausetestalready takes a
positional path:test fastkeeps meaning thefast/folder.
Requested in mauriciobenjamin700/tempest-fastapi-sdk#328.Measured on a machine with 6 physical cores / 12 threads. On this
package's own suite (100 tests, warm environment, three runs each)
tempest-cli testtook 2.2 s andtempest-cli test --fast1.6–1.7 s
(12 workers: nopsutilhere, soautocounts logical CPUs) — worker
start-up is most of the fast run at this size. On the
tempest-fastapi-sdk suite (10 218 tests, one run each, same
invocation), pytest reported 2127 s serial and 411 s with--fast
(auto→ 6 workers, sincepsutilis installed there), about 5.2x;
both runs ended with the same 10 failures, all fromruffbeing a dead
pyenv shim on thatPATH.autois pytest-xdist's rule, not ours: physical cores whenpsutil
is importable, logical CPUs otherwise.-w logicalasks for the
threads explicitly. -
A missing pytest-xdist is a sentence, not
unrecognized arguments: -n. Before spawning,--fastasks the interpreter pytest will run
under — read from the pytest script's shebang, its siblingpython,
or the sameuv run --with pytestoverlay — whether it can import
xdist. When it cannot, the message namespytest-xdist,
tempest-cli[tools]andtempest-fastapi-sdk[tests], and the exit code
is 127, with no traceback.check --fastmakes that check before its
first step. A probe that cannot run at all is not taken as "missing":
the run proceeds and pytest reports for itself. -
run_pytest(..., fast=, workers=)andrun_full_check(..., fast=, workers=)for library callers — keyword-only, defaulting to the
serial run, so every existing call is unchanged.DEFAULT_FAST_WORKERS,
XDIST_MODULEandMISSING_TOOL_EXIT_CODEare exported from
tempest_cli.lint.
Changed
[tools]now carriespytest-xdist>=3.8.0next to mypy and pytest,
so the bundle is enough for--fast. Itsrequires-dist
(execnet>=2.1,pytest>=7.0.0) has no upper bound.
v0.3.0
Changed
-
ruffnow ships with the package. It moved from the[tools]
extra into the runtime dependencies, souv add --dev tempest-cliis
enough forlint,fix,formatandfmt-checkto run — no second
install, and no dependency onuvbeing around to fetch one. The cost
is nil: ruff is a static binary wheel with no Python dependencies of
its own, so no bound of its reaches a consumer's resolution.mypyandpyteststay out on purpose. A mypy bump changes which
errors a codebase reports and pytest has to match the suite and its
plugins — those are the project's call.[tools]now installs exactly
those two. -
The project's environment is searched before the CLI's own. With
ruff bundled, the CLI's environment always has one; looking there
first would silently override a version the project pinned whenever
tempest-cliis installed apart from it (uv tool install, pipx).
The order is now$VIRTUAL_ENV→ nearest.venv→ the CLI's own
environment →PATH→uv run --with.
v0.2.0
Added
tc, the short alias. The package now installs a second console
script pointing at the same entry point, sotc checkistempest-cli check. While the installing environment is onPATH,tcshadows
iproute2'stc(8); call the traffic controller as/usr/sbin/tcwhen
you need it.
Fixed
-
The gate no longer runs a dead pyenv/asdf shim.
tempest-cli fix
in a project whose environment has no ruff answeredpyenv: ruff: command not foundand exited 127 — the lookup took the firstPATH
hit, and on a version-manager machine that hit is a shim that exists
for every tool any installed interpreter ever provided. The lookup now
searches the environments that belong to the run first (the CLI's own
interpreter directory,$VIRTUAL_ENV, the nearest.venv), accepts a
shim only after<tool> --versionproves it dispatches, and applies
the same check touvitself. -
The
uvfallback stopped leaking back toPATH. It ranuv run <tool>, which falls back toPATHwhen the project environment has
no such tool — landing on the very shim that had just been rejected.
It is nowuv run --with <tool> <tool>, so the tool is always present
in the run's overlay; a version pinned by the project still wins,
since uv resolves the overlay against the project's requirements. -
The 127 message names the fix. It now says what to install
(uv add --dev ruff, or"tempest-cli[tools]"for the set) instead
of only reporting thatPATHanduvcame up empty.
v0.1.0
First release. Extracted from
tempest-fastapi-sdk,
where the same gate shipped as tempest check — reachable only by
installing a FastAPI SDK.
Added
-
The quality gate:
lint,fix,format,fmt-check,type,
testandcheck, overruff/mypy/pytest. Each returns the
underlying tool's exit code;checkruns the four in order and stops
at the first failure. -
Typing strictness as configuration, read from
[tool.tempest] typing_strictnessinpyproject.toml(lenient|standard|
strict, defaulting tostandard), with a--strictness/-s
override per run. Levels only ever add flags on top of the
project's own[tool.ruff]/[tool.mypy].ANN401is never enabled
at any level:Anyis a legitimate annotation. -
pr-prompt— builds the prompt that makes an AI write a branch's
pull-request description, carrying the repository's own PR template
(or a bundled PT-BR / EN-US default), the rules that stop a model from
returning the template unfilled, and the branch context read as
base...head. -
A library surface:
run_full_check,run_ruff_check,
run_ruff_fix,run_ruff_format,run_mypy,run_pytest,
load_tempest_config,find_pyproject,generate_pr_prompt. -
register_commands(app)mounts the whole gate onto an existing
typer.Typer, so another CLI exposes these commands under its own
name without copying a body.tempest-fastapi-sdkuses exactly this,
which is what keepstempest checkandtempest-cli checkidentical.
Notes
- The only runtime dependency is
typer.ruff,mypyandpytest
are invoked from the active environment (or throughuv runwhen they
are not onPATH), so the project pins the versions it wants. The
[tools]extra installs all three for whoever prefers that. - Measured against the SDK it came from: reaching these commands there
loaded 38.7 MB of dependencies and about 0.5 s of import time per
invocation — for four commands that touch none of it. A test in this
package asserts that importing it pulls no web framework.