Skip to content

Python Standard

Authoritative source: skill/standards/languages/python.md

Template metadata

Field Value
id standard.language.python
status stable
version 1.2.0

Rendered preview

Python Standard

Apply by impact

Apply only rule groups activated by the current task or change-impact record. Do not invent evidence for untouched surfaces; when a required gate asks about one, record why it is not applicable.

Rules

Design and boundaries

  • Keep domain logic in importable modules; keep CLI, web, database, and framework code at adapters.
  • Prefer composition, small protocols at real seams, and explicit dependency injection over inheritance or service locators.

Types and data

  • Type public and important internal interfaces. Use precise unions, generics, enums, dataclasses, or validated models instead of broad Any and unstructured dictionaries.
  • Validate external data at trust boundaries; do not repeatedly revalidate trusted domain values.

Errors and resources

  • Raise domain-specific exceptions, preserve causes with raise ... from ..., and never catch Exception without a clear recovery or translation boundary.
  • Use context managers for owned files, locks, transactions, sessions, and temporary resources.

Concurrency and state

  • Avoid import-time side effects and mutable module globals. State whether APIs are sync, async, thread-safe, process-safe, cancellable, and idempotent where relevant.
  • Do not mix blocking I/O into an event loop; bound task creation and define shutdown behaviour.

Testing

  • Use pytest or the project-standard runner. Cover expected behaviour, errors, boundaries, serialization, async cancellation, and installed-package imports where relevant.
  • Prefer deterministic fakes over network or clock dependence; test public behaviour rather than private implementation details.

Performance

  • Measure before optimizing. Prefer vectorized or streaming libraries for large data, avoid accidental quadratic loops, and inspect serialization/copy costs.

Security

  • Treat deserialization, subprocesses, paths, templates, SQL, and dynamic imports as trust boundaries. Avoid unsafe eval/exec, shell interpolation, and secret-bearing logs.

Public API documentation

  • Add meaningful PEP 257-style docstrings to changed public modules, classes, protocols, exceptions, functions, and methods.
  • Document caller-visible parameters, returns, raised errors, side effects, ownership, units, valid ranges, and examples when they are not evident from names and types.
  • Do not use docstrings that merely repeat a symbol name or signature. Private helpers need documentation when their contract, algorithm, invariants, or failure behaviour is non-obvious.

Tooling and delivery

  • Use project-defined pyproject.toml tooling; do not replace tools without a task reason.
  • When packaging changes, test build, clean installation, import, entry points, metadata, and declared Python versions.

Review triggers

Review missing or stale public docstrings, untyped public APIs, broad Any, circular imports, framework leakage into domain code, orchestration functions mixing I/O and policy, hidden optional imports, unsafe dynamic execution, unbounded async tasks, and package behaviour that works only from the source tree.

Required response

Update types and public API docstrings, localise ignores with a reason, move side effects behind explicit functions, validate boundary data once, separate domain and adapters, add focused tests, and test the installed artefact when packaging is affected.

Exceptions

Dynamic interfaces may remain when runtime validation and focused tests provide equivalent evidence. Generated, vendored, compatibility-only, or framework-required public symbols may use narrowly configured exclusions.

Evidence

Record formatter, linter, type-checker, pytest, coverage, test, build, install, and import results that exist in the project. Record configured docstring lint or coverage, doctest, security scan, and MkDocs/Sphinx/API-reference build results when applicable.

Complete source

---
id: standard.language.python
version: 1.2.0
status: stable
---
# Python Standard

## Apply by impact

Apply only rule groups activated by the current task or change-impact record. Do not invent
evidence for untouched surfaces; when a required gate asks about one, record why it is not
applicable.

## Rules
### Design and boundaries
- Keep domain logic in importable modules; keep CLI, web, database, and framework code at adapters.
- Prefer composition, small protocols at real seams, and explicit dependency injection over inheritance or service locators.
### Types and data
- Type public and important internal interfaces. Use precise unions, generics, enums, dataclasses, or validated models instead of broad `Any` and unstructured dictionaries.
- Validate external data at trust boundaries; do not repeatedly revalidate trusted domain values.
### Errors and resources
- Raise domain-specific exceptions, preserve causes with `raise ... from ...`, and never catch `Exception` without a clear recovery or translation boundary.
- Use context managers for owned files, locks, transactions, sessions, and temporary resources.
### Concurrency and state
- Avoid import-time side effects and mutable module globals. State whether APIs are sync, async, thread-safe, process-safe, cancellable, and idempotent where relevant.
- Do not mix blocking I/O into an event loop; bound task creation and define shutdown behaviour.
### Testing
- Use pytest or the project-standard runner. Cover expected behaviour, errors, boundaries, serialization, async cancellation, and installed-package imports where relevant.
- Prefer deterministic fakes over network or clock dependence; test public behaviour rather than private implementation details.
### Performance
- Measure before optimizing. Prefer vectorized or streaming libraries for large data, avoid accidental quadratic loops, and inspect serialization/copy costs.
### Security
- Treat deserialization, subprocesses, paths, templates, SQL, and dynamic imports as trust boundaries. Avoid unsafe `eval`/`exec`, shell interpolation, and secret-bearing logs.
### Public API documentation
- Add meaningful PEP 257-style docstrings to changed public modules, classes, protocols, exceptions, functions, and methods.
- Document caller-visible parameters, returns, raised errors, side effects, ownership, units, valid ranges, and examples when they are not evident from names and types.
- Do not use docstrings that merely repeat a symbol name or signature. Private helpers need documentation when their contract, algorithm, invariants, or failure behaviour is non-obvious.
### Tooling and delivery
- Use project-defined `pyproject.toml` tooling; do not replace tools without a task reason.
- When packaging changes, test build, clean installation, import, entry points, metadata, and declared Python versions.
## Review triggers
Review missing or stale public docstrings, untyped public APIs, broad `Any`, circular imports,
framework leakage into domain code, orchestration functions mixing I/O and policy, hidden optional
imports, unsafe dynamic execution, unbounded async tasks, and package behaviour that works only
from the source tree.
## Required response
Update types and public API docstrings, localise ignores with a reason, move side effects behind
explicit functions, validate boundary data once, separate domain and adapters, add focused tests,
and test the installed artefact when packaging is affected.
## Exceptions
Dynamic interfaces may remain when runtime validation and focused tests provide equivalent
evidence. Generated, vendored, compatibility-only, or framework-required public symbols may
use narrowly configured exclusions.
## Evidence
Record formatter, linter, type-checker, pytest, coverage, test, build, install, and import results
that exist in the project. Record configured docstring lint or coverage, doctest, security scan,
and MkDocs/Sphinx/API-reference build results when applicable.