Python Development
Python: uv-first, Pyright strict, typed JSON/data shapes, boundary validation, practical tests, small composable modules.
Activation Triggers
.py, pyproject.toml, uv commands, Python packaging, inline script metadata
- pip/pip3/poetry/venv/virtualenv replacement or migration
- Python typing, Pyright strict, inherited mypy, Ruff, pytest, Hypothesis
- TypedDict, Literal, discriminated unions, JSON/API/RPC payloads, pydantic, msgspec, boundary validation
- Async I/O, data pipelines, CLI tooling, parsing, test strategy
Workflow
1. DETECT -> package manager, runtime target, scripts, type/test gates
2. ROUTE -> read the required follow-up docs for async, typing, engineering, tests, syntax, patterns, packaging
3. MODEL -> typed payloads, invariants, boundaries, distinct domain concepts, public API types
4. COMPOSE -> functional core, imperative shell, small modules; reuse the first adequate existing tool or helper
5. VALIDATE -> parse untrusted input once at the edge; convert inward; make resource ownership, cancellation, timeouts, and errors explicit
6. VERIFY -> Pyright/Ruff/pytest gates appropriate to the repo; test observable behavior and failure paths
Core Principles
- Respect the declared Python target first:
requires-python, CI matrix, Docker image, Ruff target-version, Pyright config
- Prefer explicit types and error paths; Pyright strict is the default for new projects
- Keep raw JSON, env, CLI, API, and RPC data at boundaries; validate once with pydantic/msgspec or narrow typed code
- Model dict-shaped data with
TypedDict, Literal, and discriminated unions while it remains dict-shaped
- Prefer pure transformations, immutable values, copy-on-write updates, protocols, dataclasses, comprehensions/generators, and small modules when they clarify code
- Keep I/O, logging, retries, timeouts, mutation, and process exits in the imperative shell
- Give concepts that must not mix distinct types; use
NewType, tagged unions, or domain records only when a mix-up would be a real bug
- Own resources with context managers and concurrency with explicit cancellation, timeout, and cleanup scopes
- Keep errors specific and actionable. Catch or translate them only where that layer can make a decision
- Do not add a dependency, abstraction, parser, normalization step, or defensive branch without a concrete caller, boundary, or failure mode
- Use mypy only for inherited repos that already use it
uv Essentials
Prefer uv over raw python, pip, poetry, and python -m venv when uv is the intended workflow.
uv run python script.py
uv run pytest
uv run pyright
uv run ruff check .
uv run ruff format --check .
uv run --with requests python script.py
uv add requests httpx
uv add --dev pytest pytest-asyncio pyright ruff
uv venv
uv init --script example.py --python 3.12
uv add --script example.py requests rich
uv lock --script example.py
Use inline script metadata for standalone scripts that need dependencies:
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx"]
# ///
Quality Gate Essentials
- New projects: Pyright strict, Ruff lint/format, pytest
- Inherited projects: preserve the existing checker stack unless changing it is part of the task
- Baseline commands:
uv run pyright
uv run ruff check .
uv run ruff format --check .
uv run pytest
- Boundary-heavy code needs contract tests for JSON/API/RPC/CLI ingress and failure paths
- Parser/transform-heavy code should use Hypothesis only for invariants, round-trips, idempotence, and lossless conversion properties
- Tests should be deterministic, isolated, and behavior-focused. Prefer real values, in-memory fakes, or wire-level fakes; mock only an unavailable external edge
- Do not pin private constants, incidental formatting, prose, or one implementation path when the user-visible contract is what matters
- Ruff baseline:
E, F, I, UP, B, SIM; expand deliberately after the baseline is clean
Build Note
Use uv_build for pure Python packages. For extension modules, prefer an appropriate backend such as hatchling.
[build-system]
requires = ["uv_build>=0.9.28,<0.10.0"]
build-backend = "uv_build"
Prefer src/ layout unless the repository has a strong reason not to.
Required follow-up reads
Only task-relevant references MUST be loaded.
| Need |
Read |
When |
| Async I/O, concurrency, cancellation |
cookbook/async.md |
Async behavior is central |
| Typing and data boundaries |
reference.md, cookbook/correctness.md |
JSON, API, RPC, CLI, or validation boundaries matter |
| Design, ownership, error, or test-quality decisions |
references/engineering.md |
Choosing models, error paths, resource lifecycles, abstractions, or behavioral tests |
| Opinionated stack recipes and deep implementation patterns |
references/advanced/README.md, then its matching reference |
A task needs a detailed framework, library, strict-tooling, or data-processing recipe; repository policy and existing tooling take precedence |
| Cross-language code-smell or logging review |
references/advanced/engineering/code-smells.md, references/advanced/engineering/logging.md |
Reviewing structure or observability beyond Python-specific mechanics |
| Testing and property-based invariants |
cookbook/testing.md, then matching cookbook/testing-*.md |
Designing or debugging tests |
| Modern syntax and runtime compatibility |
cookbook/modern.md, then matching version guide |
Target-version behavior matters |
| Functional, iterator, or design patterns |
cookbook/patterns.md, then matching pattern guide |
Choosing an implementation pattern |
| Packaging, uv, metadata, build backends |
This file, project config, official tool output |
Packaging or dependency work |
Must / Must Not
- MUST type public APIs, validate untrusted inputs at boundaries, prefer pathlib, and respect the project runtime target
- MUST use
uv for running Python, adding deps, script metadata, and env setup when uv is intended
- MUST keep validators, raw payloads, mocks, retries, and I/O out of core logic unless they are the domain being modeled
- MUST NOT use mutable default args, bare
except, untracked background tasks, blocking calls in async code, or broad fallbacks that hide bad input
- MUST NOT keep known payloads as
dict[str, Any], propagate raw JSON inward, or carry boundary validator objects through core logic by accident
1---2disable-model-invocation: true3name: python4description: "Use when Python, .py files, uv, typing, validation, APIs, async code, tests, or packaging are involved."5license: AGPL-3.0-or-later6metadata:7 author: anntnzrb89---1011# Python Development1213Python: uv-first, Pyright strict, typed JSON/data shapes, boundary validation, practical tests, small composable modules.1415## Activation Triggers1617- `.py`, `pyproject.toml`, uv commands, Python packaging, inline script metadata18- pip/pip3/poetry/venv/virtualenv replacement or migration19- Python typing, Pyright strict, inherited mypy, Ruff, pytest, Hypothesis20- TypedDict, Literal, discriminated unions, JSON/API/RPC payloads, pydantic, msgspec, boundary validation21- Async I/O, data pipelines, CLI tooling, parsing, test strategy2223## Workflow2425```text261. DETECT -> package manager, runtime target, scripts, type/test gates272. ROUTE -> read the required follow-up docs for async, typing, engineering, tests, syntax, patterns, packaging283. MODEL -> typed payloads, invariants, boundaries, distinct domain concepts, public API types294. COMPOSE -> functional core, imperative shell, small modules; reuse the first adequate existing tool or helper305. VALIDATE -> parse untrusted input once at the edge; convert inward; make resource ownership, cancellation, timeouts, and errors explicit316. VERIFY -> Pyright/Ruff/pytest gates appropriate to the repo; test observable behavior and failure paths32```3334## Core Principles3536- Respect the declared Python target first: `requires-python`, CI matrix, Docker image, Ruff `target-version`, Pyright config37- Prefer explicit types and error paths; Pyright strict is the default for new projects38- Keep raw JSON, env, CLI, API, and RPC data at boundaries; validate once with pydantic/msgspec or narrow typed code39- Model dict-shaped data with `TypedDict`, `Literal`, and discriminated unions while it remains dict-shaped40- Prefer pure transformations, immutable values, copy-on-write updates, protocols, dataclasses, comprehensions/generators, and small modules when they clarify code41- Keep I/O, logging, retries, timeouts, mutation, and process exits in the imperative shell42- Give concepts that must not mix distinct types; use `NewType`, tagged unions, or domain records only when a mix-up would be a real bug43- Own resources with context managers and concurrency with explicit cancellation, timeout, and cleanup scopes44- Keep errors specific and actionable. Catch or translate them only where that layer can make a decision45- Do not add a dependency, abstraction, parser, normalization step, or defensive branch without a concrete caller, boundary, or failure mode46- Use mypy only for inherited repos that already use it4748## uv Essentials4950Prefer `uv` over raw `python`, `pip`, `poetry`, and `python -m venv` when uv is the intended workflow.5152```bash53uv run python script.py54uv run pytest55uv run pyright56uv run ruff check .57uv run ruff format --check .58uv run --with requests python script.py59uv add requests httpx60uv add --dev pytest pytest-asyncio pyright ruff61uv venv62uv init --script example.py --python 3.1263uv add --script example.py requests rich64uv lock --script example.py65```6667Use inline script metadata for standalone scripts that need dependencies:6869```python70# /// script71# requires-python = ">=3.12"72# dependencies = ["httpx"]73# ///74```7576## Quality Gate Essentials7778- New projects: Pyright strict, Ruff lint/format, pytest79- Inherited projects: preserve the existing checker stack unless changing it is part of the task80- Baseline commands:81 - `uv run pyright`82 - `uv run ruff check .`83 - `uv run ruff format --check .`84 - `uv run pytest`85- Boundary-heavy code needs contract tests for JSON/API/RPC/CLI ingress and failure paths86- Parser/transform-heavy code should use Hypothesis only for invariants, round-trips, idempotence, and lossless conversion properties87- Tests should be deterministic, isolated, and behavior-focused. Prefer real values, in-memory fakes, or wire-level fakes; mock only an unavailable external edge88- Do not pin private constants, incidental formatting, prose, or one implementation path when the user-visible contract is what matters89- Ruff baseline: `E`, `F`, `I`, `UP`, `B`, `SIM`; expand deliberately after the baseline is clean9091## Build Note9293Use `uv_build` for pure Python packages. For extension modules, prefer an appropriate backend such as `hatchling`.9495```toml96[build-system]97requires = ["uv_build>=0.9.28,<0.10.0"]98build-backend = "uv_build"99```100101Prefer `src/` layout unless the repository has a strong reason not to.102103## Required follow-up reads104105Only task-relevant references MUST be loaded.106107| Need | Read | When |108| --- | --- | --- |109| Async I/O, concurrency, cancellation | `cookbook/async.md` | Async behavior is central |110| Typing and data boundaries | `reference.md`, `cookbook/correctness.md` | JSON, API, RPC, CLI, or validation boundaries matter |111| Design, ownership, error, or test-quality decisions | `references/engineering.md` | Choosing models, error paths, resource lifecycles, abstractions, or behavioral tests |112| Opinionated stack recipes and deep implementation patterns | `references/advanced/README.md`, then its matching reference | A task needs a detailed framework, library, strict-tooling, or data-processing recipe; repository policy and existing tooling take precedence |113| Cross-language code-smell or logging review | `references/advanced/engineering/code-smells.md`, `references/advanced/engineering/logging.md` | Reviewing structure or observability beyond Python-specific mechanics |114| Testing and property-based invariants | `cookbook/testing.md`, then matching `cookbook/testing-*.md` | Designing or debugging tests |115| Modern syntax and runtime compatibility | `cookbook/modern.md`, then matching version guide | Target-version behavior matters |116| Functional, iterator, or design patterns | `cookbook/patterns.md`, then matching pattern guide | Choosing an implementation pattern |117| Packaging, uv, metadata, build backends | This file, project config, official tool output | Packaging or dependency work |118119## Must / Must Not120121- MUST type public APIs, validate untrusted inputs at boundaries, prefer pathlib, and respect the project runtime target122- MUST use `uv` for running Python, adding deps, script metadata, and env setup when uv is intended123- MUST keep validators, raw payloads, mocks, retries, and I/O out of core logic unless they are the domain being modeled124- MUST NOT use mutable default args, bare `except`, untracked background tasks, blocking calls in async code, or broad fallbacks that hide bad input125- MUST NOT keep known payloads as `dict[str, Any]`, propagate raw JSON inward, or carry boundary validator objects through core logic by accident