Skip to content

JnyJny/python-package-cookiecutter

Repository files navigation

gh:JnyJny/python-package-cookiecutter release build-status

Python Package Cookiecutter Template

There are many cookiecutter templates, but this one is mine and I'm sharing it with you. With it, you can quickly create a full-featured Python package designed to be managed with uv and direnv, a default typer command-line interface, optional settings using pydantic-settings and logging using my favorite logger, loguru. Development activities like testing, code quality checks, and publishing to PyPI are all baked in and ready to go thanks to Poe The Poet. Best of all, I've added all sorts of templates and base files to help provide a great GitHub experience for you and people that interact with your project repository.

Build Features

  • Choose from a plethora of Open Source licenses.
  • Automatically detects GitHub user name and email address (if configured).
  • Installs requested version of development Python if needed.
  • Creates a virtual environment in the project directory.
  • Enables direnv for this subdirectory if direnv available.
  • Automatically syncs dependencies and the project into virtual environment.
  • Automatically initializes a git repository with a main branch.
  • Automatically creates an initial git commit.
  • Optionally creates an upstream repository and pushes (GitHub only, requires gh).

Package Features

  • Python project designed to be managed with uv.
  • Exposes a command line interface built with typer.
  • Package is callable via python -m <package>.
  • Poe the Poet tasks integrated into pyproject.toml:
    • Test with pytest.
    • Generate HTML code coverage reports.
    • Run code quality checks using mypy, ruff, and ty.
    • Publish to PyPI via GitHub Actions with poe publish.
  • Development tool options integrated into pyproject.toml.
  • Generic GitHub Issue and Pull Request templates.
  • Configured to use dependabot dependency checker.
    • Checks project dependencies.
    • Checks project GitHub action dependencies.
  • Operating System and Python version test matrices.
  • Configured to use direnv to automatically activate & deactivate venvs.
  • Optionally configured badges in README.md for cool points.
  • Optionally managed CLI settings using pydantic-settings.
  • Optionally logs to a file.

Prerequisites

User Accounts

  • GitHub account optional but recommended
  • PyPI account optional but recommended

Tools You Need To Make This Work

Tool Required Optional Use
cookiecutter Creates projects from templates.
git Version control system.
uv Manage python, virtual environments and your project!
direnv Automatically activate and deactivate virtual environments.
gh GitHub CLI tool for working with repositories.

Creating Your Project

If you haven't authenticated to GitHub with gh yet and you plan to ask cookiecutter to create the upstream repository, you should do that now:

gh auth login

All done? Now you are ready to create your project and the good news is once you install uv you get the great tool runner uvx for free!

uvx cookiecutter gh:JnyJny/python-package-cookiecutter

After answering the cookiecutter prompts, you should see the following:

Task [Install Dev Python............] 🟢
Task [Create .venv..................] 🟢
Task [Enable Direnv.................] 🟢
Task [Sync Project Deps.............] 🟢
Task [Ruff Check Source.............] 🟢
Task [Initialize Git................] 🟢
Task [Add Files.....................] 🟢
Task [Initial Commit................] 🟢
Task [Create Upstream Repo .........] 🟢
$ 

If you didn't ask to have the upstream GitHub repository created, the last task will not run. If you don't have gh installed or you aren't authenticated, the last task will fail but the template generation will complete successfully.

Example Package Tree

$ poe tree
.
├── .cookiecutter.json
├── .envrc
├── .github
│   ├── dependabot.yaml
│   ├── ISSUE_TEMPLATE
│   │   ├── 1_bug_report.yaml
│   │   ├── 2_feature_request.yaml
│   │   ├── 3_question.yaml
│   │   └── config.yaml
│   ├── PULL_REQUEST_TEMPLATE.md
│   └── workflows
│       ├── README.md
│       └── release.yaml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── pyproject.toml
├── README.md
├── src
│   └── thing
│       ├── __init__.py
│       ├── __main__.py
│       ├── self_subcommand.py
│       └── settings.py
├── tests
│   ├── __init__.py
│   ├── conftest.py
│   └── test_cli.py
└── uv.lock

The .cookiecutter.json file is a dump of the cookiecutter JSON that created this project. The .envrc file can be safely removed if you aren't using direnv.

Post Install

If you have direnv installed, your project's virtual environment will be activated when you enter the project directory or sub-directories. You can activate the project virtual environment manually without direnv using source .venv/bin/activate, but it's less cool.

Once your venv is activated, all the development tools are available for use without having to use uv run to preface the command. Check out poe!

Default Poe Tasks

$ poe
Poe the Poet - A task runner that works well with poetry.
version 0.34.0

Result: No task specified.

Usage:
  poe [global options] task [task arguments]

Global options:
  -h, --help [TASK]     Show this help page and exit, optionally supply a task.
  --version             Print the version and exit
  -v, --verbose         Increase command output (repeatable)
  -q, --quiet           Decrease command output (repeatable)
  -d, --dry-run         Print the task contents but don't actually run it
  -C, --directory PATH  Specify where to find the pyproject.toml
  -e, --executor EXECUTOR
                        Override the default task executor
  --ansi                Force enable ANSI output
  --no-ansi             Force disable ANSI output

Configured tasks:
  coverage              [Code Quality] Open generated coverage report in a browser.
  mypy                  [Code Quality] Run mypy type checker on source.
  ty                    [Code Quality] Run ty type checker on source.
  ruff-check            [Code Quality] Run ruff check on source.
  ruff-format           [Code Quality] Run ruff format on source.
  ruff                  [Code Quality] Run Ruff check and format on source.
  check                 [Code Quality] Run all code quality tools on source.
  test                  [Code Quality] Runs testing suites using pytest.
  qc                    [Code Quality] Run all code quality tasks.
  publish_patch         [Publish] Patch release.
  publish_minor         [Publish] Minor release.
  publish_major         [Publish] Major release.
  publish               [Publish] Minor release.
  clean                 [Clean] Remove testing, build and code quality artifacts.
  tree                  [Misc] List project files in tree format.

These are the tasks that I like. Feel free to hack them up however it suits you best. It won't hurt my feelings at all.

Example Development Workflow

This is roughly how I write code and how I would use the generated package.

flowchart TD
    Create((Create Project)) --> Edit[Edit Files]
    Edit --> |Add Bugs| Commit((Commit))
    Edit --> |Remove Bugs| Commit
    Commit -->|Not Done| Edit
    Commit --> |Breaking Features| Major[poe publish_major]
    Commit --> |Non-breaking Features| Minor[poe publish_minor]
    Commit --> |Bug Fixes| Patch[poe publish_patch]
    Major --> workflow[.github/workflows/release.yaml]
    Minor --> workflow
    Patch --> workflow
    workflow --> test[test package with pytest]
    test --> |succcess| publish[uv publishes project to PyPI]
Loading

Things You Will Want to Change

This package is how I like things and it would be an unimaginable coincidence if this was exactly how you like things. I've listed some files here that you will definitely want to consider changing to suit your needs.

LICENSE

Depending on the Open Source license you chose, you may need to edit the license file and/or source files to be in compliance with the license. I am not a lawyer. I don't play one on TV. I am the last person to ask for advice on this matter. Also, I am not a lawyer.

CONTRIBUTING.md

You want to update this file with all the details that potential contributors to your project need to know. This file is currently a skeleton. Be as specific as possible.

pyproject.toml - Trove Classifiers

I supply a couple of Trove classifiers in the project pyproject.toml file, however you should update them to match the specific details of your project. It will help people connect with your project.

pyproject.toml - ruff rules

You may not want to check against ALL of the rules. Or maybe you do.

pyproject.toml - tool.poe.tasks.qc

The qc poe task runs all the of the code quality tasks which could be called "a lot". Pare those down or add the checks that make sense for your project.

.github/ISSUE_TEMPLATE/*.yaml

This directory holds a set of YAML files describing GitHub Issue templates. You should edit them to reflect your projects needs and personality. You may want to uncomment and edit issue links in config.yaml if it suits your needs.

.github/workflows/release.yml

The release.yaml workflow defines a matrix of operating systems and Python versions to test against. Tests are run when a semantic versioning tag or a tag with the suffix "-test" is pushed to a branch. If and when the requested tests complete successfully, the package will be built and published to PyPI, unless the triggering tag has a "-test" suffix in which case the workflow skips publishing.

Tests are designed to be run against matrices of Operating System and Python version values. The matrices can be a list with a single item or a list of multiple items.

The End

If you've read this far, you have my gratitude. Send me some email, open an issue, or just make something cool (and let me know!).