---
description: Modern Python project (uv + ruff) conventions
globs: ["**/*.py","pyproject.toml"]
alwaysApply: false
---

# Python project (uv)

- Use uv for everything: `uv add httpx`, `uv add --dev pytest`, `uv run <cmd>`, `uv sync`. Don't call `pip install` or edit `uv.lock` by hand.
- `src/` layout with a package in `src/<name>/`; config in `pyproject.toml` only (no `setup.py`, `requirements.txt` unless exported for deploys).
- Target Python 3.12+: built-in generics (`list[str]`), `X | None`, `match` where it reads better, `type` aliases, f-strings.
- Type hints on every public function. Typecheck with `uv run pyright` (or `mypy` if configured); no new `# type: ignore` without a reason in the comment.
- Data containers: `@dataclass(slots=True)` or Pydantic models at I/O boundaries. Avoid passing raw dicts around.
- Paths with `pathlib.Path`; files opened with explicit `encoding="utf-8"`.
- Logging with `logging.getLogger(__name__)`, not `print`, in library code.
- Errors: raise specific exceptions, never bare `except:`; catch only what you can handle.
- HTTP with `httpx` (timeouts set); async only when the project is async.
- CLI entry points in `[project.scripts]`.

## Don't
- Don't use mutable default arguments, `from x import *`, or global state for config.

## Done when
`uv run ruff format --check . && uv run ruff check . && uv run pyright && uv run pytest -q` pass.
