npx skills add ...
npx skills add github/awesome-copilot --skill python-pypi-package-builder
End-to-end skill for building, testing, linting, versioning, and publishing a production-grade Python library to PyPI. Covers all four build backends (setuptools+setuptools_scm, hatchling, flit, poetry), PEP 440 versioning, semantic versioning, dynamic git-tag versioning, OOP/SOLID design, type hints (PEP 484/526/544/561), Trusted Publishing (OIDC), and the full PyPA packaging flow. Use for: creating Python packages, pip-installable SDKs, CLI tools, framework plugins, pyproject.toml setup, py.typed, setuptools_scm, semver, mypy, pre-commit, GitHub Actions CI/CD, or PyPI publishing.
npx skills add github/awesome-copilot --skill python-pypi-package-builder
A complete, battle-tested guide for building, testing, linting, versioning, typing, and publishing a production-grade Python library to PyPI — from first commit to community-ready release.
AI Agent Instruction: Read this entire file before writing a single line of code or creating any file. Every decision — layout, backend, versioning strategy, patterns, CI — has a decision rule here. Follow the decision trees in order. This skill applies to any Python package type (utility, SDK, CLI, plugin, data library). Do not skip sections.
| Section in this file | What it covers |
|---|---|
| 1. Skill Trigger | When to load this skill |
| 2. Package Type Decision | Identify what you are building |
| 3. Folder Structure Decision | src/ vs flat vs monorepo |
| 4. Build Backend Decision | setuptools / hatchling / flit / poetry |
| 5. PyPA Packaging Flow | The canonical publish pipeline |
| 6. Project Structure Templates | Full layouts for every option |
| 7. Versioning Strategy | PEP 440, semver, dynamic vs static |
| Reference file | What it covers |
|---|---|
references/pyproject-toml.md | All four backend templates, setuptools_scm, py.typed, tool configs |
references/library-patterns.md | OOP/SOLID, type hints, core class design, factory, protocols, CLI |
references/testing-quality.md | conftest.py, unit/backend/async tests, ruff/mypy/pre-commit |
references/ci-publishing.md | ci.yml, publish.yml, Trusted Publishing, TestPyPI, CHANGELOG, release checklist |
references/community-docs.md | README, docstrings, CONTRIBUTING, SECURITY, anti-patterns, master checklist |
references/architecture-patterns.md | Backend system (plugin/strategy), config layer, transport layer, CLI, backend injection |
references/versioning-strategy.md | PEP 440, SemVer, pre-release, setuptools_scm deep-dive, flit static, decision engine |
references/release-governance.md | Branch strategy, branch protection, OIDC, tag author validation, prevent invalid tags |
references/tooling-ruff.md | Ruff-only setup (replaces black/isort), mypy config, pre-commit, asyncio_mode=auto |
Scaffold script: run python skills/python-pypi-package-builder/scripts/scaffold.py --name your-package-name
to generate the entire directory layout, stub files, and pyproject.toml in one command.
Load this skill whenever the user wants to:
pyproject.toml, linting, mypy, pre-commit, or GitHub Actions for a Python projectsetuptools_scm, PEP 440, semver, static versioning)py.typed, MANIFEST.in, RECORD, classifiersAlso trigger for phrases like: "build a Python SDK", "publish my library", "set up PyPI CI", "create a pip package", "how do I publish to PyPI", "pyproject.toml help", "PEP 561 typed", "setuptools_scm version", "semver Python", "PEP 440", "git tag release", "Trusted Publishing".
Identify what the user is building before writing any code. Each type has distinct patterns.
| Type | Core Pattern | Entry Point | Key Deps | Example Packages |
|---|---|---|---|---|
| Utility library | Module of pure functions + helpers | Import API only | Minimal | arrow, humanize, boltons, more-itertools |
| API client / SDK | Class with methods, auth, retry logic | Import API only | httpx or requests | boto3, stripe-python, openai |
| CLI tool | Command functions + argument parser | [project.scripts] or [project.entry-points] | click or typer | black, ruff, httpie, rich |
| Framework plugin | Plugin class, hook registration | [project.entry-points."framework.plugin"] | Framework dep | pytest-*, django-*, flask-* |
| Data processing library | Classes + functional pipeline | Import API only | Optional: numpy, pandas | pydantic, marshmallow, cerberus |
| Mixed / generic | Combination of above | Varies | Varies | Many real-world packages |
Decision Rule: Ask the user if unclear. A package can combine types (e.g., SDK with a CLI entry point) — use the primary type for structural decisions and add secondary type patterns on top.
For implementation patterns of each type, see references/library-patterns.md.
my-python-librarymy_python_librarypip install <name> fails first)| Situation | Use |
|---|---|
| New project, unknown future size | src/ layout (safest default) |
| Single-purpose, 1–4 modules | Flat layout |
| Large library, many contributors | src/ layout |
| Multiple packages in one repo | Namespace / monorepo |
| Migrating old flat project | Keep flat; migrate to src/ at next major version |
| Backend | Version source | Config | C extensions | Best for |
|---|---|---|---|---|
setuptools + setuptools_scm | git tags (automatic) | pyproject.toml + optional setup.py shim | Yes | Projects with git-tag releases; any complexity |
hatchling | manual or plugin | pyproject.toml only | No | New pure-Python projects; fast, modern |
flit | __version__ in __init__.py | pyproject.toml only | No | Very simple, single-module packages |
poetry | pyproject.toml field | pyproject.toml only | No | Teams wanting integrated dep management |
For all four complete pyproject.toml templates, see references/pyproject-toml.md.
This is the canonical end-to-end flow from source code to user install. Every step must be understood before publishing.
| Concept | What it means |
|---|---|
| sdist | Source distribution — your source + metadata; used when no wheel is available |
| wheel (.whl) | Pre-built binary — pip extracts directly into site-packages; no build step |
| PEP 517/518 | Standard build system interface via pyproject.toml [build-system] table |
| PEP 621 | Standard [project] table in pyproject.toml; all modern backends support it |
| PEP 639 | license key as SPDX string (e.g., "MIT", "Apache-2.0") — not {text = "MIT"} |
| PEP 561 | py.typed empty marker file — tells mypy/IDEs this package ships type information |
For complete CI workflow and publishing setup, see references/ci-publishing.md.
Each sub-package has its own pyproject.toml. They share the your_org namespace via PEP 420
implicit namespace packages (no __init__.py in the namespace root).
| File | Purpose | When to include |
|---|---|---|
__init__.py | Public API surface; re-exports; __version__ | Always |
py.typed | PEP 561 typed-package marker (empty) | Always |
core.py | Primary class / main logic | Always |
config.py | Settings dataclass or Pydantic model | When configurable |
exceptions.py | Exception hierarchy (YourBaseError → specifics) | Always |
models.py | Data models / DTOs / TypedDicts | When data-heavy |
utils.py | Internal helpers (not part of public API) | As needed |
types.py | Shared TypeVar, TypeAlias, Protocol definitions | When complex typing |
cli.py | CLI entry points (click/typer) | CLI type only |
backends/ | Plugin/strategy pattern | When swappable implementations |
_compat.py | Python version compatibility shims | When 3.9–3.13 compat needed |
Required pyproject.toml config:
Critical: always set fetch-depth: 0 in every CI checkout step. Without full git history,
setuptools_scm cannot find tags and the build version silently falls back to 0.0.0+dev.
For complete pyproject.toml templates for all four backends, see references/pyproject-toml.md.
After understanding decisions and structure:
Set up pyproject.toml → references/pyproject-toml.md
All four backend templates (setuptools+scm, hatchling, flit, poetry), full tool configs,
py.typed setup, versioning config.
Write your library code → references/library-patterns.md
OOP/SOLID principles, type hints (PEP 484/526/544/561), core class design, factory functions,
__init__.py, plugin/backend pattern, CLI entry point.
Add tests and code quality → references/testing-quality.md
conftest.py, unit/backend/async tests, parametrize, ruff/mypy/pre-commit setup.
Set up CI/CD and publish → references/ci-publishing.md
ci.yml, publish.yml with Trusted Publishing (OIDC, no API tokens), CHANGELOG format,
release checklist.
Polish for community/OSS → references/community-docs.md
README sections, docstring format, CONTRIBUTING, SECURITY, issue templates, anti-patterns
table, and master release checklist.
Design backends, config, transport, CLI → references/architecture-patterns.md
Backend system (plugin/strategy pattern), Settings dataclass, HTTP transport layer,
CLI with click/typer, backend injection rules.
Choose and implement a versioning strategy → references/versioning-strategy.md
PEP 440 canonical forms, SemVer rules, pre-release identifiers, setuptools_scm deep-dive,
flit static versioning, decision engine (DEFAULT/BEGINNER/MINIMAL).
Govern releases and secure the publish pipeline → references/release-governance.md
Branch strategy, branch protection rules, OIDC Trusted Publishing setup, tag author
validation in CI, tag format enforcement, full governed publish.yml.
Simplify tooling with Ruff → references/tooling-ruff.md
Ruff-only setup replacing black/isort/flake8, mypy config, pre-commit hooks,
asyncio_mode=auto (remove @pytest.mark.asyncio), migration guide.