--- name: python description: > Python coding conventions, style, and tooling. Use for anything involving Python code. --- # Python Coding Conventions ## Tooling - **Always use `uv`** — never bare `pip`, `python`, `venv`, or `virtualenv`. - Run code: `uv run script.py` (or `uv run python -m module`) - Add dependencies: `uv add `; sync: `uv sync` - One-off tools: `uv run --with ...` or `uvx ` - **Format before done:** `uv run ruff format` - **Lint before done:** `uv run ruff check --fix` - Treat "done" as: formatted, linted clean, type hints present. ## Core Principles - **Readability first** — code must be easily readable and understandable at a glance - **Simplicity** — prefer the simplest solution that solves the problem; avoid unnecessary abstractions and cleverness - **Clean Code** — meaningful names, small focused functions, single responsibility, no duplication (DRY), clear intent ## Style - Follow PEP 8, but max line length **120 characters** (not the default 88) ## Types and Annotations - Use Python 3.12+ built-in generics: `list[str]`, `dict[str, int]`, `tuple[int, ...]` - Use `X | Y` instead of `Union[X, Y]`, `str | None` instead of `Optional[str]` - Do not import from `typing` unless truly necessary (e.g., `Protocol`, `TypeVar`) - All public functions and methods must have type hints ## Docstrings and Comments - Add a docstring or comment only when it explains **intent** not obvious from the code or signature - First line: short imperative summary; omit parameter/return docs if self-explanatory - Prefer clear naming over explanatory comments; never restate what the code does ## Functions - Break complex functions into smaller ones; one thing at one level of abstraction - Keep the parameter count low (0–3) - No boolean flag arguments — split into two well-named functions or use an enum - Command-Query Separation: a function that returns a value must not mutate state - Handle edge cases explicitly; prefer specific exceptions over bare `except` ## Control Flow - Fail fast — validate inputs up front with guard clauses and early returns - Avoid deep nesting (max 2–3 levels); invert conditions to return early - Replace magic numbers and strings with named constants ## Error Handling - Never silently swallow exceptions - Do not unnecessarily wrap exceptions in other exception types ## Paths - Prefer `pathlib.Path` over `os.path`