Modern Python
Guide for modern Python tooling and best practices.
When to Use This Skill
- •Creating a new Python project or package
- •Setting up
pyproject.tomlconfiguration - •Configuring development tools (linting, formatting, testing)
- •Writing Python scripts with external dependencies
- •Migrating from legacy tools (when user requests it)
When NOT to Use This Skill
- •User wants to keep legacy tooling: Respect existing workflows if explicitly requested
- •Python < 3.11 required: These tools target modern Python
- •Non-Python projects: Mixed codebases where Python isn't primary
Anti-Patterns to Avoid
| Avoid | Use Instead |
|---|---|
[tool.ty] python-version | [tool.ty.environment] python-version |
uv pip install | uv add and uv sync |
| Editing pyproject.toml manually to add deps | uv add <pkg> / uv remove <pkg> |
uv_build (simpler, sufficient for most cases) | hatchling build backend |
| Poetry | uv (faster, simpler, better ecosystem integration) |
| requirements.txt | PEP 723 for scripts, pyproject.toml for projects |
| mypy / pyright | ty (faster, from Astral team) |
[project.optional-dependencies] for dev tools | [dependency-groups] (PEP 735) |
Manual virtualenv activation (source .venv/bin/activate) | uv run <cmd> |
| pre-commit | prek (faster, no Python runtime needed) |
Key principles:
- •Always use
uv addanduv removeto manage dependencies - •Never manually activate or manage virtual environments—use
uv runfor all commands - •Use
[dependency-groups]for dev/test/docs dependencies, not[project.optional-dependencies]
Decision Tree
code
What are you doing?
│
├─ Single-file script with dependencies?
│ └─ Use PEP 723 inline metadata (./references/pep723-scripts.md)
│
├─ New multi-file project (not distributed)?
│ └─ Minimal uv setup (see Quick Start below)
│
├─ New reusable package/library?
│ └─ Full project setup (see Full Setup below)
│
└─ Migrating existing project?
└─ See Migration Guide (./references/migration.md)
Tool Overview
| Tool | Purpose | Replaces |
|---|---|---|
| uv | Package/dependency management | pip, virtualenv, pip-tools, pipx, pyenv |
| ruff | Linting AND formatting | flake8, black, isort, pyupgrade, pydocstyle |
| ty | Type checking | mypy, pyright (faster alternative) |
| pytest | Testing with coverage | unittest |
| prek | Pre-commit hooks (setup) | pre-commit (faster, Rust-native) |
Security Tools
| Tool | Purpose | When It Runs |
|---|---|---|
| shellcheck | Shell script linting | pre-commit |
| detect-secrets | Secret detection | pre-commit |
| actionlint | Workflow syntax validation | pre-commit, CI |
| zizmor | Workflow security audit | pre-commit, CI |
| pip-audit | Dependency vulnerability scanning | CI, manual |
See security-setup.md for configuration and usage.
Quick Start: Minimal Project
For simple multi-file projects not intended for distribution:
bash
# Create project with uv uv init myproject cd myproject # Add dependencies uv add requests rich # Add dev dependencies uv add --group dev pytest ruff ty # Run code uv run python src/myproject/main.py # Run tools uv run pytest uv run ruff check .
1. Create Project Structure
bash
uv init --package myproject cd myproject
This creates:
code
myproject/ ├── pyproject.toml ├── README.md ├── src/ │ └── myproject/ │ └── __init__.py └── .python-version
2. Configure pyproject.toml
See pyproject.md for complete configuration reference.
Key sections:
toml
[project]
name = "myproject"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = []
[dependency-groups]
dev = [{include-group = "lint"}, {include-group = "test"}, {include-group = "audit"}]
lint = ["ruff", "ty"]
test = ["pytest", "pytest-cov"]
audit = ["pip-audit"]
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = ["ALL"]
ignore = ["D", "COM812", "ISC001"]
[tool.pytest]
addopts = ["--cov=myproject", "--cov-fail-under=80"]
[tool.ty.terminal]
error-on-warning = true
[tool.ty.environment]
python-version = "3.11"
[tool.ty.rules]
# Strict from day 1 for new projects
possibly-unresolved-reference = "error"
unused-ignore-comment = "warn"
3. Install Dependencies
bash
# Install all dependency groups uv sync --all-groups # Or install specific groups uv sync --group dev
4. Add Makefile
makefile
.PHONY: dev lint format test build dev: uv sync --all-groups lint: uv run ruff format --check && uv run ruff check && uv run ty check src/ format: uv run ruff format . test: uv run pytest build: uv build
Quick Reference: uv Commands
| Command | Description |
|---|---|
uv init | Create new project |
uv init --package | Create distributable package |
uv add <pkg> | Add dependency |
uv add --group dev <pkg> | Add to dependency group |
uv remove <pkg> | Remove dependency |
uv sync | Install dependencies |
uv sync --all-groups | Install all dependency groups |
uv run <cmd> | Run command in venv |
uv run --with <pkg> <cmd> | Run with temporary dependency |
uv build | Build package |
uv publish | Publish to PyPI |
Ad-hoc Dependencies with --with
Use uv run --with for one-off commands that need packages not in your project:
bash
# Run Python with a temporary package
uv run --with requests python -c "import requests; print(requests.get('https://httpbin.org/ip').json())"
# Run a module with temporary deps
uv run --with rich python -m rich.progress
# Multiple packages
uv run --with requests --with rich python script.py
# Combine with project deps (adds to existing venv)
uv run --with httpx pytest # project deps + httpx
When to use --with vs uv add:
- •
uv add: Package is a project dependency (goes in pyproject.toml/uv.lock) - •
--with: One-off usage, testing, or scripts outside a project context
See uv-commands.md for complete reference.
Quick Reference: Dependency Groups
toml
[dependency-groups] dev = ["ruff", "ty"] test = ["pytest", "pytest-cov", "hypothesis"] docs = ["sphinx", "myst-parser"]
Install with: uv sync --group dev --group test
Best Practices Checklist
- • Use
src/layout for packages - • Set
requires-python = ">=3.11" - • Configure ruff with
select = ["ALL"]and explicit ignores - • Use ty for type checking
- • Enforce test coverage minimum (80%+)
- • Use dependency groups instead of extras for dev tools
- • Add
uv.lockto version control - • Use PEP 723 for standalone scripts
Read Next
- •migration-checklist.md - Step-by-step migration cleanup
- •pyproject.md - Complete pyproject.toml reference
- •uv-commands.md - uv command reference
- •ruff-config.md - Ruff linting/formatting configuration
- •testing.md - pytest and coverage setup
- •pep723-scripts.md - PEP 723 inline script metadata
- •prek.md - Fast pre-commit hooks with prek
- •security-setup.md - Security hooks and dependency scanning