Skip to content
Go back

Python Project Foundry: A Production-Ready Repository in One Command

Starting a Python library is easy. Setting up everything around it--testing, documentation, CI, security checks, packaging, releases, and containers--often takes longer than writing the first version of the library itself.

Python Project Foundry generates an opinionated, production-ready repository for a Python package or library from an interactive questionnaire.

uvx python-project-foundry ./my/new/project
Basic project scaffolding with Python Project Foundry.

What Foundry generates

Foundry starts with a package skeleton and builds the rest of the repository around it:

Questionnaire


Python package repository
├── Typed src/ package
├── Tests and examples
├── Documentation site
├── Development environment
├── Quality and security checks
├── GitHub Actions workflows
├── Container images
└── Release automation

The generated repository exposes the same commands to developers and CI.

Quickstart

The one-line invocation requires uv, Git, Make, Node.js, and npm.

Generate a repository:

uvx python-project-foundry ./orbit-tools

Foundry prompts for values such as:

After generation:

cd orbit-tools
make check

On Linux and macOS, Foundry can also initialize Git, install dependencies, create the initial commit, and install Git hooks.

Without uv, use the bootstrap script:

curl -LsSf https://raw.githubusercontent.com/ryancswallace/python-project-foundry/main/ppf |
  sh -s -- ./orbit-tools

Modern Python packaging defaults

Generated repositories use a src/ layout:

src/
└── orbit_tools/
    ├── __init__.py
    ├── _core.py
    ├── exceptions.py
    └── py.typed

Each project includes:

One interface for development

The generated Makefile provides a discoverable command surface:

make help

Common commands include:

GoalCommand
Install dependenciesmake install
Run testsmake test
Check formatting and lintmake lint
Check typesmake typecheck
Build documentationmake docs
Run the standard suitemake check
Build distributionsmake build
Test containersmake docker-check

Local development and CI use the same commands, so contributors do not have to remember each underlying tool invocation.

Testing and quality controls

Each generated project wires together:

ConcernTools
TestsPytest, Hypothesis, pytest-cov
Linting and formattingRuff
Type checkingBasedPyright
Dependency declarationsdeptry
Markdownmarkdownlint
SpellingCSpell
Workflowsactionlint, Zizmor
Automation matrixNox

Test coverage enforcement is configurable during generation.

The Linux CI matrix tests every selected Python version from the minimum through the default. macOS and Windows test the default version.

Documentation included

Every repository includes a MkDocs Material site with:

Preview it locally:

make serve-docs

The docs configuration uses the repository and package metadata supplied during generation.

Security and supply-chain checks

Security checks are present from the first commit:

The defaults are intentionally broad. A new repository starts with source, dependency, workflow, container, and release-artifact checks already wired into CI.

Container support

Generated repositories include a multi-stage Dockerfile with separate runtime and test targets.

Base image
├── Runtime image
└── Test image

The generated workflows can:

Run the complete local container suite with:

make docker-check

Open-source and proprietary licensing

Foundry can generate:

ChoiceIdentifier
MIT LicenseMIT
BSD 3-Clause LicenseBSD-3-Clause
Apache License 2.0Apache-2.0
Mozilla Public License 2.0MPL-2.0
GNU GPL version 3GPL-3.0-only
Proprietary noticeLicenseRef-Proprietary

The selected value is used consistently in the license file, package metadata, citation metadata, README, and container labels.

The proprietary option provides a general all-rights-reserved notice.

GitHub publishing

Generating files does not automatically create external resources.

When the repository is ready, preview publishing:

uvx python-project-foundry publish \
  --visibility private \
  --dry-run

Then publish it:

uvx python-project-foundry publish \
  --visibility private

The publish command:

Visibility must be selected explicitly:

Template updates

Generated repositories record their original Foundry template version and questionnaire answers.

Preview an update:

uvx --refresh python-project-foundry update --pretend

Apply it:

uvx --refresh python-project-foundry update

Foundry uses Copier’s update support to preserve project changes where possible. If the same content changed in both the project and template, conflicts are left for review.

After updating:

git diff
make check

Updates are pinned to the installed Foundry release rather than selecting the latest template version.

Automation-friendly generation

For unattended generation, skip the questionnaire:

uvx python-project-foundry ./orbit-tools --defaults

Useful options include:

OptionEffect
--defaultsAccept questionnaire defaults
--pretendPreview without writing
--skip-tasksRender files without setup tasks
--overwriteReplace existing destination files

When to use Foundry

Python Project Foundry is useful when you want a package repository with mature engineering practices from its first commit.

Each generated repository includes:

Foundry quickly creates strong repo scaffolding so you can focus on developing your Python application itself.


Share this post on:

Previous Post
Inside Jobman, Part 4: Process Trees, Timeouts, and Durable Logs
Next Post
Inside Jobman, Part 3: Scheduling Without a Central Scheduler