Referência¶
Gerada a partir das docstrings do pacote via
mkdocstrings.
Superfície de topo¶
tempest_cli
¶
Framework-agnostic quality gate for Python projects.
tempest-cli runs ruff, mypy and pytest behind one command, with a
typing-strictness dial read from [tool.tempest] in the project's
pyproject.toml — and a generator for the prompt that makes an AI fill
a pull-request description from the branch's own diff.
It knows nothing about any web framework. ruff ships with it, so the
lint/format commands work the moment it is installed; mypy and
pytest are left to the project, which pins the versions it wants.
The tools are invoked from the project's environment first, so a pinned
version always beats the bundled one.
tempest-cli check # lint + fmt-check + type + test
tempest-cli fix # every ruff autofix, then format
tempest-cli type -s strict # override the configured strictness
tempest-cli pr-prompt | claude -p
tc check # `tc` is the short alias for the same CLI
Everything is importable too, for a project that would rather wire the gate into its own tooling:
from tempest_cli import load_tempest_config, run_full_check
config = load_tempest_config()
exit_code = run_full_check(".", config=config)
And :func:tempest_cli.main.register_commands mounts the whole gate onto
an existing :class:typer.Typer, so another CLI can expose these
commands under its own name without copying them.
DEFAULT_TYPING_STRICTNESS
module-attribute
¶
DEFAULT_TYPING_STRICTNESS: TypingStrictness = 'standard'
Level applied when the key is absent or no pyproject.toml is found.
TypingStrictness
module-attribute
¶
Allowed values for [tool.tempest] typing_strictness.
TempestConfig
dataclass
¶
TempestConfig(typing_strictness: TypingStrictness = DEFAULT_TYPING_STRICTNESS)
Resolved [tool.tempest] settings.
Attributes:
| Name | Type | Description |
|---|---|---|
typing_strictness |
TypingStrictness
|
How strictly the CLI gates
enforce typing. One of |
ruff_ann_select
¶
Return the ANN rule codes to add to ruff for this level.
Returns:
| Type | Description |
|---|---|
list[str]
|
list[str]: Rule codes for |
list[str]
|
|
Source code in tempest_cli/config.py
mypy_flags
¶
Return the extra mypy flags to add for this level.
Returns:
| Type | Description |
|---|---|
list[str]
|
list[str]: Flags layered on top of the project's |
list[str]
|
|
Source code in tempest_cli/config.py
GitError
¶
Bases: RuntimeError
A git invocation failed, or the repository lacks what was asked.
Carries the command's own stderr so the caller can print the
reason git gave instead of a generic failure.
PromptLanguage
¶
Bases: StrEnum
Language of the bundled template and of the prompt's instructions.
Only the bundled template is translated: a repository template is used verbatim in whatever language it was written in, since it is that repository's contract.
find_pyproject
¶
Locate the nearest pyproject.toml walking up from start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
Path | None
|
Directory to begin the search. Defaults to the current working directory. |
None
|
Returns:
| Type | Description |
|---|---|
Path | None
|
Path | None: The path to the first |
Path | None
|
|
Source code in tempest_cli/config.py
load_tempest_config
¶
load_tempest_config(start: Path | None = None) -> TempestConfig
Load [tool.tempest] from the nearest pyproject.toml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
Path | None
|
Directory to begin the search. Defaults to the current working directory. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
TempestConfig |
TempestConfig
|
The resolved config. Falls back to defaults when |
TempestConfig
|
no |
Raises:
| Type | Description |
|---|---|
ValueError
|
When |
Source code in tempest_cli/config.py
resolve_tool
¶
Return an argv prefix invoking executable or None when absent.
Public because callers outside the gate need the same lookup — the
SDK's OpenAPI code generator formats what it emits with the project's
own ruff, and reimplementing the environment/uv run fallback
there would be a second answer to the same question.
Preference order:
- the environments that belong to this run (see
:func:
_environment_dirs): the CLI's own interpreter directory,$VIRTUAL_ENV, then the nearest.venv; executableonPATH— skipped when it resolves to a version-manager shim that does not dispatch anywhere;uv run --with <executable> <executable>whenuvis on thePATH: the project's own environment plus the tool, without requiring activation or a prioruv sync.
Step 3 carries --with on purpose. A plain uv run ruff falls
back to PATH when the project environment has no ruff — landing
right back on the dead shim this lookup just rejected. --with
puts the tool in the run's own overlay, so the command is always the
one that runs. When the project pins a version, uv resolves the
overlay against the project's requirements, so the pin still wins.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
executable
|
str
|
The command name ( |
required |
Returns:
| Type | Description |
|---|---|
list[str] | None
|
list[str] | None: argv prefix to extend with extra arguments, or |
list[str] | None
|
|
Source code in tempest_cli/lint.py
run_full_check
¶
run_full_check(target: str, *, config: TempestConfig | None = None) -> int
Run the entire quality gate sequentially.
Order: ruff check → ruff format --check → mypy → pytest.
Stops at the first non-zero exit code so failures surface fast.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path inspected by ruff/mypy. Pytest always runs
against the project's configured |
required |
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The first non-zero exit code, or |
Source code in tempest_cli/lint.py
run_mypy
¶
run_mypy(target: str, *, config: TempestConfig | None = None) -> int
Invoke mypy <target> with the configured strictness flags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to mypy. |
required |
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The mypy exit code. |
Source code in tempest_cli/lint.py
run_pytest
¶
Invoke pytest with an optional target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str | None
|
Optional pytest path filter. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The pytest exit code. |
Source code in tempest_cli/lint.py
run_ruff_check
¶
run_ruff_check(target: str, *, config: TempestConfig | None = None) -> int
Invoke ruff check <target> with the configured ANN rules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to ruff. |
required |
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The ruff exit code. |
Source code in tempest_cli/lint.py
run_ruff_fix
¶
run_ruff_fix(
target: str, *, unsafe: bool = False, config: TempestConfig | None = None
) -> int
Apply every automatic fix ruff can perform, then format the target.
Runs in two passes so the second one sees the rewritten file:
ruff check --fix [--unsafe-fixes] <target>— autofix imports (sort + dedupe), remove unused imports, normalize string quotes, drop trailing whitespace, fix the rest of the lint rules that have safe (or, withunsafe=True, also unsafe) autofixers.ruff format <target>— normalize indentation, line length, blank lines and trailing newlines.
Both passes always run. ruff check --fix exits non-zero whenever
any residual violation remains that it cannot autofix (an
over-length string/comment, an undefined name, etc.) — even though
it already rewrote everything it could. Short-circuiting on that
exit code would skip ruff format entirely, leaving the file
un-wrapped and its extra blank lines intact. So the formatter runs
unconditionally; the lint exit code is surfaced afterwards so CI
still fails on the leftover issues.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to ruff. |
required |
unsafe
|
bool
|
When True, pass |
False
|
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
|
int
|
otherwise the lint pass exit code (residual violations), or the |
|
int
|
format pass exit code when the lint pass was clean. |
Source code in tempest_cli/lint.py
run_ruff_format
¶
Invoke ruff format (write or check-only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to ruff. |
required |
check
|
bool
|
When True, run |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The ruff exit code. |
Source code in tempest_cli/lint.py
generate_pr_prompt
¶
generate_pr_prompt(
*,
base: str = DEFAULT_BASE,
head: str | None = None,
cwd: Path | None = None,
template: Path | None = None,
language: PromptLanguage = PT_BR,
max_files: int | None = DEFAULT_MAX_FILES,
max_chars: int | None = DEFAULT_MAX_CHARS,
) -> tuple[str, PullRequestContext, ResolvedTemplate]
Read the repository and render the prompt in one call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base
|
str
|
The base ref the pull request targets. |
DEFAULT_BASE
|
head
|
str | None
|
The branch being described. Defaults to the checked-out one. |
None
|
cwd
|
Path | None
|
Any directory inside the repository. |
None
|
template
|
Path | None
|
An explicit template path. |
None
|
language
|
PromptLanguage
|
Language of the instructions and of the bundled fallback template. |
PT_BR
|
max_files
|
int | None
|
How many files contribute a patch
excerpt. |
DEFAULT_MAX_FILES
|
max_chars
|
int | None
|
Characters kept per patch, or |
DEFAULT_MAX_CHARS
|
Returns:
| Type | Description |
|---|---|
str
|
tuple[str, PullRequestContext, ResolvedTemplate]: The prompt plus |
PullRequestContext
|
the context and template it was built from, so a caller can |
ResolvedTemplate
|
report what was read and what was dropped. |
Raises:
| Type | Description |
|---|---|
GitError
|
When the repository, the base ref or the template path cannot be resolved. |
Source code in tempest_cli/pr_prompt.py
Configuração¶
TempestConfig
dataclass
¶
TempestConfig(typing_strictness: TypingStrictness = DEFAULT_TYPING_STRICTNESS)
Resolved [tool.tempest] settings.
Attributes:
| Name | Type | Description |
|---|---|---|
typing_strictness |
TypingStrictness
|
How strictly the CLI gates
enforce typing. One of |
ruff_ann_select
¶
Return the ANN rule codes to add to ruff for this level.
Returns:
| Type | Description |
|---|---|
list[str]
|
list[str]: Rule codes for |
list[str]
|
|
Source code in tempest_cli/config.py
mypy_flags
¶
Return the extra mypy flags to add for this level.
Returns:
| Type | Description |
|---|---|
list[str]
|
list[str]: Flags layered on top of the project's |
list[str]
|
|
Source code in tempest_cli/config.py
TypingStrictness
module-attribute
¶
Allowed values for [tool.tempest] typing_strictness.
load_tempest_config
¶
load_tempest_config(start: Path | None = None) -> TempestConfig
Load [tool.tempest] from the nearest pyproject.toml.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
Path | None
|
Directory to begin the search. Defaults to the current working directory. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
TempestConfig |
TempestConfig
|
The resolved config. Falls back to defaults when |
TempestConfig
|
no |
Raises:
| Type | Description |
|---|---|
ValueError
|
When |
Source code in tempest_cli/config.py
find_pyproject
¶
Locate the nearest pyproject.toml walking up from start.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
start
|
Path | None
|
Directory to begin the search. Defaults to the current working directory. |
None
|
Returns:
| Type | Description |
|---|---|
Path | None
|
Path | None: The path to the first |
Path | None
|
|
Source code in tempest_cli/config.py
Runners¶
run_ruff_check
¶
run_ruff_check(target: str, *, config: TempestConfig | None = None) -> int
Invoke ruff check <target> with the configured ANN rules.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to ruff. |
required |
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The ruff exit code. |
Source code in tempest_cli/lint.py
run_ruff_fix
¶
run_ruff_fix(
target: str, *, unsafe: bool = False, config: TempestConfig | None = None
) -> int
Apply every automatic fix ruff can perform, then format the target.
Runs in two passes so the second one sees the rewritten file:
ruff check --fix [--unsafe-fixes] <target>— autofix imports (sort + dedupe), remove unused imports, normalize string quotes, drop trailing whitespace, fix the rest of the lint rules that have safe (or, withunsafe=True, also unsafe) autofixers.ruff format <target>— normalize indentation, line length, blank lines and trailing newlines.
Both passes always run. ruff check --fix exits non-zero whenever
any residual violation remains that it cannot autofix (an
over-length string/comment, an undefined name, etc.) — even though
it already rewrote everything it could. Short-circuiting on that
exit code would skip ruff format entirely, leaving the file
un-wrapped and its extra blank lines intact. So the formatter runs
unconditionally; the lint exit code is surfaced afterwards so CI
still fails on the leftover issues.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to ruff. |
required |
unsafe
|
bool
|
When True, pass |
False
|
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
|
int
|
otherwise the lint pass exit code (residual violations), or the |
|
int
|
format pass exit code when the lint pass was clean. |
Source code in tempest_cli/lint.py
run_ruff_format
¶
Invoke ruff format (write or check-only).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to ruff. |
required |
check
|
bool
|
When True, run |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The ruff exit code. |
Source code in tempest_cli/lint.py
run_mypy
¶
run_mypy(target: str, *, config: TempestConfig | None = None) -> int
Invoke mypy <target> with the configured strictness flags.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path passed verbatim to mypy. |
required |
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The mypy exit code. |
Source code in tempest_cli/lint.py
run_pytest
¶
Invoke pytest with an optional target.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str | None
|
Optional pytest path filter. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The pytest exit code. |
Source code in tempest_cli/lint.py
run_full_check
¶
run_full_check(target: str, *, config: TempestConfig | None = None) -> int
Run the entire quality gate sequentially.
Order: ruff check → ruff format --check → mypy → pytest.
Stops at the first non-zero exit code so failures surface fast.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
str
|
The path inspected by ruff/mypy. Pytest always runs
against the project's configured |
required |
config
|
TempestConfig | None
|
Resolved |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
int |
int
|
The first non-zero exit code, or |
Source code in tempest_cli/lint.py
Prompt de PR¶
generate_pr_prompt
¶
generate_pr_prompt(
*,
base: str = DEFAULT_BASE,
head: str | None = None,
cwd: Path | None = None,
template: Path | None = None,
language: PromptLanguage = PT_BR,
max_files: int | None = DEFAULT_MAX_FILES,
max_chars: int | None = DEFAULT_MAX_CHARS,
) -> tuple[str, PullRequestContext, ResolvedTemplate]
Read the repository and render the prompt in one call.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base
|
str
|
The base ref the pull request targets. |
DEFAULT_BASE
|
head
|
str | None
|
The branch being described. Defaults to the checked-out one. |
None
|
cwd
|
Path | None
|
Any directory inside the repository. |
None
|
template
|
Path | None
|
An explicit template path. |
None
|
language
|
PromptLanguage
|
Language of the instructions and of the bundled fallback template. |
PT_BR
|
max_files
|
int | None
|
How many files contribute a patch
excerpt. |
DEFAULT_MAX_FILES
|
max_chars
|
int | None
|
Characters kept per patch, or |
DEFAULT_MAX_CHARS
|
Returns:
| Type | Description |
|---|---|
str
|
tuple[str, PullRequestContext, ResolvedTemplate]: The prompt plus |
PullRequestContext
|
the context and template it was built from, so a caller can |
ResolvedTemplate
|
report what was read and what was dropped. |
Raises:
| Type | Description |
|---|---|
GitError
|
When the repository, the base ref or the template path cannot be resolved. |
Source code in tempest_cli/pr_prompt.py
PromptLanguage
¶
Bases: StrEnum
Language of the bundled template and of the prompt's instructions.
Only the bundled template is translated: a repository template is used verbatim in whatever language it was written in, since it is that repository's contract.
GitError
¶
Bases: RuntimeError
A git invocation failed, or the repository lacks what was asked.
Carries the command's own stderr so the caller can print the
reason git gave instead of a generic failure.
CLI¶
register_commands
¶
Register the quality gate on an existing Typer application.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Typer
|
The application to extend. Its own name and help text are left untouched; only commands are added. |
required |
Example
Source code in tempest_cli/main.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 | |