Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
pyproject.toml (PEP 518/621) is the standard project manifest in 2026 — it replaces setup.py, setup.cfg, Pipfile, and the bespoke configs of 90% of tools. It carries project metadata, dependencies, build backend, and tool config (ruff, mypy, pytest all read from it). A fresh project in 2026 has one pyproject.toml and that's it — no setup.py, no setup.cfg. Knowing every section by heart is the difference between 'I copy from a template' and 'I can ship a Python library to PyPI'.
pyproject.toml is the single source of truth for a Python project: it declares direct dependencies, the required Python version, build backend, optional dependency groups (like dev), and the configuration of every tool (ruff, mypy, pytest) that reads from it. Before PEP 518/621 you needed setup.py, setup.cfg, MANIFEST.in, tox.ini, and a bespoke requirements-dev.txt — all of which are now replaced by one file. A production-grade pyproject.toml also declares [project.scripts] entry points so that pip install automatically wires up CLI binaries on the user's PATH.
uv pip install -e . (editable install) and confirm pip list shows your package.[project.scripts] entry pointing at a function in your code. Re-install. Now there's a CLI binary on your PATH.[tool.ruff] section. Run ruff check . — it picks up the config automatically. This is the new standard.uv pip install -e ".[dev]" to install with optional deps. This is how dev-only deps stay out of production.# pyproject.toml
[project]
name = "myapp"
version = "0.1.0"
description = "A FastAPI service"
requires-python = ">=3.12"
authors = [{ name = "You", email = "you@example.com" }]
readme = "README.md"
license = "MIT"
dependencies = [
"fastapi>=0.110",
"uvicorn[standard]>=0.29",
"httpx>=0.27",
"pydantic-settings>=2.2",
]
[project.optional-dependencies]
dev = [
"pytest>=8",
"pytest-asyncio>=0.23",
"ruff>=0.4",
"mypy>=1.10",
]
[project.scripts]
myapp = "myapp.cli:main" # `pip install` will create a `myapp` binary
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.ruff]
line-length = 100
target-version = "py312"
[tool.mypy]
python_version = "3.12"
strict = truepython3 main.py