Skip to content

Repository files navigation

Python Template

CI OpenSSF Scorecard License: MIT Copier uv Ruff Last commit Github Stars

A modern Python project template with CI/CD ready for production.

Usage

You need uv. Nothing else.

uvx copier copy gh:leynier/python-template my-project

Answer the prompts and you get a working project: dependencies installed, git initialised, tests passing.

To pull later improvements to this template into a project you already generated:

cd my-project
uvx copier update

That last command is the reason this template uses Copier instead of Cookiecutter — Cookiecutter has no way to update a project after generating it.

What you get

One prompt, project_type, replaces what used to be three separate branches:

project_type What it generates
library An importable package
cli A command line app built with Typer
api A web API built with FastAPI

Tooling

  • uv for dependencies, with a committed uv.lock, PEP 621 metadata and PEP 735 dependency groups.
  • Ruff for linting and formatting — one tool in place of flake8, black, isort and pyupgrade.
  • ty for type checking.
  • deptry for undeclared and unused dependencies.
  • pre-commit wiring all of the above into git hooks.
  • src/ layout with a py.typed marker.

CI/CD, via GitHub Actions

  • Test matrix across Linux, macOS and Windows × every supported Python version.
  • Least-privilege permissions: on every workflow, concurrency groups, and actions pinned to full commit SHAs.
  • PyPI publishing with Trusted Publishing — OIDC, no API tokens, with Sigstore attestations. The workflow refuses to publish if the git tag does not match the project version.
  • CodeQL scanning and zizmor auditing the workflows themselves.
  • Dependabot covering uv, github-actions and Docker.

Documentation

Built with Zensical, the successor to Material for MkDocs from the same team, with mkdocstrings generating an API reference from your docstrings. Deployed to GitHub Pages via OIDC on every push to main.

Optional extras

A multi-stage Dockerfile running as a non-root user, a VS Code devcontainer, and an AGENTS.md so AI coding agents pick up the project conventions.

Two deliberate bets

This template adopts two tools that are not yet 1.0. Both are used in a way that fails soft:

  • ty is at 0.0.x and has no plugin system. CI runs ty check with continue-on-error: true, so it reports findings without gating your build. When ty reaches 1.0, drop that line from .github/workflows/ci.yml.
  • Zensical is at 0.0.x and does not yet have full plugin parity with Material for MkDocs. mkdocstrings is verified to work — the test suite asserts the API reference is really rendered, not passed through — but other plugins may not be. Zensical reads mkdocs.yml, so moving back is cheap.

If you would rather not take those bets, answer use_docs: false and swap ty for mypy in pyproject.toml.

File naming

Generated projects use lowercase filenames (readme.md), except for files that GitHub or tooling matches by exact name, which stay uppercase: LICENSE, CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md, AGENTS.md, Dockerfile and .github/ISSUE_TEMPLATE/.

Developing this template

uv sync --all-groups
uv run pytest -m "not slow"   # structural tests: what gets rendered
uv run pytest -m slow         # generates each variant and runs its toolchain
uv run pytest                 # everything

The slow suite is the important one: it generates every project type and runs uv sync, Ruff, pytest, deptry, ty, uv build and the docs build inside each generated project. The previous version of this template had no tests at all, which is how it managed to sit broken for years without anyone noticing.

License

This project is collaborative and open source under the MIT license. Contributions are super appreciated.