All Python templates

Modern Python Rules

Type hints, ruff, black, uv, and pytest — opinionated Python defaults.

DevZone Tools3,120 copiesUpdated Apr 15, 2026Python
# 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