Modern Python Tooling Checklist
Use this checklist when you start a Python project or standardize a team template. It covers the defaults most projects need and links to deeper handbook pages when a choice needs more context.
Set the foundation
- Install Python with uv unless your team already standardizes on another interpreter manager. See the uv reference for the full command set.
- Create the project with uv init and pick the right uv init project type.
- Use a
srclayout over a flat layout for packages, so tests run against the installed code. - Use
pyproject.tomlfor project metadata and dependencies. - Commit
uv.lockfor applications, services, notebooks, and team projects that need reproducible installs. See what a lockfile is if you’re deciding whether to commit one. - Keep
.venv/out of version control. It’s the project’s virtual environment, rebuilt from the lockfile.
Manage dependencies
- Add runtime dependencies with
uv add. - Add development dependencies with
uv add --dev. - Use dependency groups for optional development workflows such as docs, linting, or tests.
- Prefer
pyproject.tomloverrequirements.txtfor new projects. - Use private package index settings only when the project needs them.
Format and lint
- Use Ruff for formatting and linting.
- Start with the recommended Ruff defaults before adding project-specific rules.
- Sort imports with Ruff instead of maintaining a separate isort setup.
- Replace Black, isort, flake8, and pyupgrade with Ruff so one tool covers formatting and linting.
- Run Ruff locally and in CI.
Run tests
- Use pytest as the default test runner.
- Run tests through uv:
uv run pytest. - Measure coverage with pytest-cov once the project has enough tests for the number to mean something.
- Test against multiple Python versions with a CI matrix when you support more than one.
Check types
- Type-check with Pyrefly for the best current combination of speed and inference. Reach for mypy, Pyright, or ty if your team already standardizes on one; compare the trade-offs before you switch.
- Run the type checker in CI once the project has enough annotations to make the output useful.
- Adopt type checking gradually for existing codebases.
Automate checks
- Add pre-commit hooks for formatting, linting, and cheap checks.
- Use GitHub Actions with uv for CI.
- Cache uv downloads in CI to speed up runs.
- Scan dependencies for vulnerabilities in CI so a bad transitive dependency fails the build.
- Keep generated artifacts out of commits unless they are part of the release output.
Publish packages
- Use trusted publishing for PyPI releases, and read why trusted publishing beats API tokens.
- Build wheels in CI for packages that other projects install; see what a wheel is.
- Publish to TestPyPI before publishing a new release workflow to PyPI.
- Check the built wheel before release with twine. The source tree can hide packaging mistakes.
Set team defaults
- Document the supported Python versions with a
.python-versionfile. - Document the project commands: install, test, lint, format, type check, build, publish.
- Keep tool choices boring unless the project has a concrete reason to differ.
- Revisit the template when Python, uv, Ruff, or the team’s type checker changes in a way that affects defaults.