---
applyTo: "**/*.py"
description: Python conventions
---

# Python

- Tooling: `uv run ruff format`, `uv run ruff check --fix`, `uv run pyright` (or mypy), `uv run pytest -q`. Add deps with `uv add`, never `pip install`.
- Type hints on all function signatures; modern syntax (`list[int]`, `str | None`). Avoid `Any`; use `TypedDict`, dataclasses, or Pydantic models for structured data.
- Raise specific exceptions with useful messages; never bare `except:` or `except Exception: pass`.
- `pathlib.Path` for files, `encoding="utf-8"` on every open.
- `logging.getLogger(__name__)` in modules; `print` only in CLI output.
- No mutable default arguments; no module-level side effects (network, DB) at import time.
- Keep functions short with early returns; prefer comprehensions for simple transforms, loops when logic grows.
- Timezone-aware datetimes (`datetime.now(tz=UTC)`).
- Secrets and config from environment via a settings object (pydantic-settings or the repo's equivalent).

## Tests
pytest functions with fixtures and `parametrize`; mock only external boundaries.
