Modern Python Rules
Type hints, ruff, black, uv, and pytest — opinionated Python defaults.
# CLAUDE.md — Modern Python
## Tooling
- **uv** for environments and dependency management. No pip, poetry, or pipenv.
- **ruff** for linting and import sorting. Replaces flake8, isort, pyupgrade, pylint.
- **ruff format** for code formatting. No black.
- **mypy** or **pyright** in strict mode for type checking. Pick one and enforce in CI.
- **pytest** for tests. No unittest unless you're maintaining a legacy suite.
## Python version
- Target Python 3.12+ unless you have a hard reason not to.
- Use `match`/`case` for exhaustive dispatch where it improves clarity.
- Use `pathlib.Path` for filesystem work — never `os.path.join` in new code.
## Type hints
- Type every function parameter and return. `-> None` is required for procedures.
- Modern syntax: `list[int]` not `List[int]`, `dict[str, int]` not `Dict`, `X | Y` not `Union[X, Y]`, `X | None` not `Optional[X]`.
- `from __future__ import annotations` at the top of every module so types are lazily evaluated.
- Use `TypedDict` or `dataclass` for structured dicts. `Protocol` for structural interfaces.
## Project layout
```
src/your_package/
__init__.py
domain/
services/
api/
tests/
pyproject.toml
README.md
```
- `src/` layout, not flat. Stops accidental imports of in-tree code over installed code.
- `__init__.py` is empty unless re-exporting a small public surface.
## Dataclasses & validation
- `@dataclass(frozen=True, slots=True)` for value objects.
- Pydantic for I/O boundary types (request bodies, config, deserialization).
- Don't use Pydantic for internal-only domain types — it's heavier than needed.
## Errors
- Custom exceptions inherit from a base `<App>Error`. Never raise bare `Exception`.
- Catch the narrowest exception possible. Bare `except:` is a bug.
- Don't use exceptions for control flow (`StopIteration` is the rare exception).
## Logging
- `logging.getLogger(__name__)` per module. Never `print` in library code.
- Structured logs in JSON for services. Plain text for CLIs.
- Don't log secrets. Add a redaction filter if there's any risk.
## Don't
- Don't shadow built-ins (`list`, `dict`, `id`, `type`).
- Don't mutate default arguments. Use `None` and a fresh value inside the function.
- Don't rely on dict ordering for correctness — it's stable but a code smell.
- Don't ship code with `# type: ignore` unless the line above explains why.
Other Python templates
Python Data Science (pandas + numpy)
Notebook discipline, vectorization, and reproducible analysis with pandas.
Python Clean Architecture
Layered architecture with use-cases, repositories, and dependency inversion.
Python asyncio Patterns
asyncio fundamentals: tasks, gather, cancellation, and structured concurrency.
Python CLI Tools (Typer)
Build polished CLIs with Typer, Rich output, and clean argument parsing.
Django + DRF Rules
Django REST Framework conventions: viewsets, serializers, permissions.