python-coding-standards
Python Coding Standards
Produce straightforward, organized Python code that is easy to follow and maintain. The aim is not clever or impressive architecture: prefer direct control flow, ordinary names, and the fewest responsibilities and abstractions needed for the task. For review or diagnosis, return findings and their consequences without implementing them. A change request includes its relevant local checks; it does not imply a repository-wide migration, cleanup, or publication.
Start from the repository
Read the applicable project instructions, Python support range, dependency constraints, nearby implementation and tests, and configured checks before choosing syntax or tools. Existing public imports, accepted inputs, serialized values, and persisted data remain compatible unless the requested change includes a migration. An instruction to adopt a new style does not by itself authorize breaking those interfaces.
The user's current request takes precedence, then explicit repository constraints. Apply this skill's defaults to new and changed code; existing mixed style alone is not an exemption. Use Python 3.12 or later for new projects, select a supported version compatible with deployment and dependencies, and record the support range in pyproject.toml. If an existing project requires older Python or incompatible tooling, identify the conflict instead of silently breaking support or migrating unrelated code. Preserve configured formatters, linters, type checkers, and test runners unless their change is in scope.
Manage the project with uv
Prefer uv's project workflow for Python setup and dependency changes: pyproject.toml, uv.lock, uv add, uv sync, and uv run. Do not use pip install or uv pip install as routine setup, a convenience shortcut, or a retry after resolution fails. An exceptional environment restriction needs a concrete reason and a reproducible dependency record. Read project environment when setting up Python, changing dependencies, or arranging test and lint groups. Keep runtime dependencies and development groups distinct; adding this skill does not itself authorize project migration or global tool installation.
Types and data boundaries
Type annotations are required for functions and methods, return values, model fields, attributes, module-level values, and local variable declarations, even when the assigned value makes the type inferable. Use Python 3.12-compatible forms such as dict[str, int], list[Item], and Item | None, not legacy typing.Dict or typing.List. Include precise SDK client, request, response, stream, and result types rather than omitting them because an external library is complex. Read types and enums for binding syntax, SDK types, and narrow exceptions. Do not use Any, a cast, or a suppression merely to make an annotation present.
Use Pydantic BaseModel as the default for application-owned structured data, including internal models, configuration, inputs, and results. Do not choose TypedDict, dataclasses, or dictionaries as competing record representations unless a concrete interface, behavior, or measured constraint makes them necessary. Reuse one model when the meaning is unchanged instead of adding parallel dictionary, dataclass, and model layers. Services and resource owners can remain ordinary classes; scalar values and real key-value mappings do not need artificial model wrappers. Explain necessary exceptions near the code.