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---2name: python3description: Use when Python, .py files, uv, typing, validation, APIs, async code, tests, or packaging are involved.4license: AGPL-3.0-or-later5---67# Python Development89Python: uv-first, Pyright strict, typed JSON/data shapes, boundary validation, practical tests, small composable modules.1011## Activation Triggers1213- `.py`, `pyproject.toml`, uv commands, Python packaging, inline script metadata14- pip/pip3/poetry/venv/virtualenv replacement or migration15- Python typing, Pyright strict, inherited mypy, Ruff, pytest, Hypothesis16- TypedDict, Literal, discriminated unions, JSON/API/RPC payloads, pydantic, msgspec, boundary validation17- Async I/O, data pipelines, CLI tooling, parsing, test strategy1819## Workflow2021```text221. DETECT -> package manager, runtime target, scripts, type/test gates232. ROUTE -> read the required follow-up docs for async, typing, engineering, tests, syntax, patterns, packaging243. MODEL -> typed payloads, invariants, boundaries, distinct domain concepts, public API types254. COMPOSE -> functional core, imperative shell, small modules; reuse the first adequate existing tool or helper265. VALIDATE -> parse untrusted input once at the edge; convert inward; make resource ownership, cancellation, timeouts, and errors explicit276. VERIFY -> Pyright/Ruff/pytest gates appropriate to the repo; test observable behavior and failure paths28```2930## Core Principles3132- Respect the declared Python target first: `requires-python`, CI matrix, Docker image, Ruff `target-version`, Pyright config33- Prefer explicit types and error paths; Pyright strict is the default for new projects34- Keep raw JSON, env, CLI, API, and RPC data at boundaries; validate once with pydantic/msgspec or narrow typed code35- Model dict-shaped data with `TypedDict`, `Literal`, and discriminated unions while it remains dict-shaped36- Prefer pure transformations, immutable values, copy-on-write updates, protocols, dataclasses, comprehensions/generators, and small modules when they clarify code37- Keep I/O, logging, retries, timeouts, mutation, and process exits in the imperative shell38- Give concepts that must not mix distinct types; use `NewType`, tagged unions, or domain records only when a mix-up would be a real bug39- Own resources with context managers and concurrency with explicit cancellation, timeout, and cleanup scopes40- Keep errors specific and actionable. Catch or translate them only where that layer can make a decision41- Do not add a dependency, abstraction, parser, normalization step, or defensive branch without a concrete caller, boundary, or failure mode42- Use mypy only for inherited repos that already use it4344## uv Essentials4546Prefer `uv` over raw `python`, `pip`, `poetry`, and `python -m venv` when uv is the intended workflow.4748```bash49uv run python script.py50uv run pytest51uv run pyright52uv run ruff check .53uv run ruff format --check .54uv run --with requests python script.py55uv add requests httpx56uv add --dev pytest pytest-asyncio pyright ruff57uv venv58uv init --script example.py --python 3.1259uv add --script example.py requests rich60uv lock --script example.py61```6263Use inline script metadata for standalone scripts that need dependencies:6465```python66# /// script67# requires-python = ">=3.12"68# dependencies = ["httpx"]69# ///70```7172## Quality Gate Essentials7374- New projects: Pyright strict, Ruff lint/format, pytest75- Inherited projects: preserve the existing checker stack unless changing it is part of the task76- Baseline commands:77 - `uv run pyright`78 - `uv run ruff check .`79 - `uv run ruff format --check .`80 - `uv run pytest`81- Boundary-heavy code needs contract tests for JSON/API/RPC/CLI ingress and failure paths82- Parser/transform-heavy code should use Hypothesis only for invariants, round-trips, idempotence, and lossless conversion properties83- Tests should be deterministic, isolated, and behavior-focused. Prefer real values, in-memory fakes, or wire-level fakes; mock only an unavailable external edge84- Do not pin private constants, incidental formatting, prose, or one implementation path when the user-visible contract is what matters85- Ruff baseline: `E`, `F`, `I`, `UP`, `B`, `SIM`; expand deliberately after the baseline is clean8687## Build Note8889Use `uv_build` for pure Python packages. For extension modules, prefer an appropriate backend such as `hatchling`.9091```toml92[build-system]93requires = ["uv_build>=0.9.28,<0.10.0"]94build-backend = "uv_build"95```9697Prefer `src/` layout unless the repository has a strong reason not to.9899## Required follow-up reads100101Only task-relevant references MUST be loaded.102103| Need | Read | When |104| --- | --- | --- |105| Async I/O, concurrency, cancellation | `cookbook/async.md` | Async behavior is central |106| Typing and data boundaries | `reference.md`, `cookbook/correctness.md` | JSON, API, RPC, CLI, or validation boundaries matter |107| Design, ownership, error, or test-quality decisions | `references/engineering.md` | Choosing models, error paths, resource lifecycles, abstractions, or behavioral tests |108| 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 |109| 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 |110| Testing and property-based invariants | `cookbook/testing.md`, then matching `cookbook/testing-*.md` | Designing or debugging tests |111| Modern syntax and runtime compatibility | `cookbook/modern.md`, then matching version guide | Target-version behavior matters |112| Functional, iterator, or design patterns | `cookbook/patterns.md`, then matching pattern guide | Choosing an implementation pattern |113| Packaging, uv, metadata, build backends | This file, project config, official tool output | Packaging or dependency work |114115## Must / Must Not116117- MUST type public APIs, validate untrusted inputs at boundaries, prefer pathlib, and respect the project runtime target118- MUST use `uv` for running Python, adding deps, script metadata, and env setup when uv is intended119- MUST keep validators, raw payloads, mocks, retries, and I/O out of core logic unless they are the domain being modeled120- MUST NOT use mutable default args, bare `except`, untracked background tasks, blocking calls in async code, or broad fallbacks that hide bad input121- MUST NOT keep known payloads as `dict[str, Any]`, propagate raw JSON inward, or carry boundary validator objects through core logic by accident