home / skills / phrazzld / claude-config / python-standards
This skill enforces modern Python practices using uv, ruff, mypy, and pytest, guiding project setup, typing, testing, and package structure.
npx playbooks add skill phrazzld/claude-config --skill python-standardsReview the files below or copy the command above to add this skill to your agents.
---
name: python-standards
description: |
Modern Python development with uv, ruff, mypy, and pytest. Use when:
- Writing or reviewing Python code
- Setting up Python projects or pyproject.toml
- Choosing dependency management (uv, poetry, pip)
- Configuring linting, formatting, or type checking
- Organizing Python packages
Keywords: Python, pyproject.toml, uv, ruff, mypy, pytest, type hints,
virtual environment, lockfile, package structure
effort: high
---
# Python Standards
Modern Python with uv + ruff + mypy + pytest. All config in pyproject.toml.
## Toolchain
| Tool | Purpose |
|------|---------|
| **uv** | Dependencies + virtual envs (lockfile: `uv.lock`) |
| **ruff** | Linting + formatting (replaces black, isort, flake8) |
| **mypy** | Type checking (strict mode) |
| **pytest** | Testing + coverage |
```bash
# Setup
uv init && uv add <deps> && uv sync
# Daily workflow
uv run ruff check . --fix && uv run ruff format .
uv run mypy . && uv run pytest
```
## Type Hints
**All functions and classes must have explicit type hints:**
```python
def fetch_user(user_id: str) -> User | None:
"""Fetch user by ID."""
...
def process_items(items: list[Item]) -> dict[str, int]:
...
```
**mypy strict mode:**
```toml
[tool.mypy]
strict = true
disallow_untyped_defs = true
disallow_any_generics = true
```
## Package Structure
Feature-based, not layer-based:
```
src/myproject/
users/ # Domain
__init__.py # Public API: __all__ = ['User', 'UserService']
models.py
services.py
orders/ # Another domain
shared/ # Cross-cutting concerns
```
## Error Handling
**Catch specific exceptions with context:**
```python
try:
result = parse_config(path)
except FileNotFoundError:
logger.warning(f"Config not found: {path}")
return defaults
except json.JSONDecodeError as e:
raise ConfigError(f"Invalid JSON in {path}") from e
```
Never: bare `except:`, silent swallowing, `except Exception`.
## pyproject.toml
Single source of truth (no setup.py, requirements.txt):
```toml
[project]
name = "myproject"
version = "1.0.0"
requires-python = ">=3.11"
dependencies = ["httpx", "pydantic"]
[project.optional-dependencies]
dev = ["pytest", "mypy", "ruff"]
[tool.ruff]
select = ["E", "W", "F", "I", "B", "UP", "SIM", "S", "ANN"]
line-length = 88
[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = ["--cov=src", "--cov-fail-under=85"]
```
## Anti-Patterns
- `Any` without documented justification
- Layer-based folders (`/controllers`, `/models`, `/views`)
- Circular imports
- Legacy tools (pip, black+isort, flake8)
- Multiple config files
- `noqa` comments without justification
## References
- [testing-patterns.md](references/testing-patterns.md) - pytest, fixtures, parametrize
- [ruff-config.md](references/ruff-config.md) - Complete ruff rule configuration
This skill defines a modern Python development standard centered on uv for dependency and venv management, ruff for linting/formatting, mypy for strict typing, and pytest for testing. All configuration is consolidated in pyproject.toml so project metadata, tooling, and dev dependencies live in one place. It enforces feature-based package layout, explicit type hints, and clear error handling patterns to keep code reliable and maintainable.
The skill prescribes a toolchain and workflow: use uv to initialize projects, add dependencies, and produce a lockfile; run ruff to lint and format; run mypy in strict mode for static typing; and run pytest for tests and coverage. pyproject.toml is the single source of truth for project metadata, tool settings, and dev dependencies. The skill also provides conventions for package layout, exception handling, and anti-patterns to avoid.
Why use uv instead of pip or poetry?
uv manages virtual environments and generates a lockfile with a simple workflow; it avoids multiple scattered config files and integrates well with the pyproject-first approach.
How strict should mypy be?
Enable strict mode in mypy (disallow untyped defs, disallow Any generics) and enforce it in CI; relax only with documented justification.