{"id":"014aeafe-6bf2-421f-83d2-7e44e25706b0","shortId":"hHtjtC","kind":"skill","title":"python-pypi-package-builder","tagline":"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/SOL","description":"# Python PyPI Package Builder Skill\n\nA complete, battle-tested guide for building, testing, linting, versioning, typing, and\npublishing a production-grade Python library to PyPI — from first commit to community-ready\nrelease.\n\n> **AI Agent Instruction:** Read this entire file before writing a single line of code or\n> creating any file. Every decision — layout, backend, versioning strategy, patterns, CI —\n> has a decision rule here. Follow the decision trees in order. This skill applies to any\n> Python package type (utility, SDK, CLI, plugin, data library). Do not skip sections.\n\n---\n\n## Quick Navigation\n\n| Section in this file | What it covers |\n|---|---|\n| [1. Skill Trigger](#1-skill-trigger) | When to load this skill |\n| [2. Package Type Decision](#2-package-type-decision) | Identify what you are building |\n| [3. Folder Structure Decision](#3-folder-structure-decision) | src/ vs flat vs monorepo |\n| [4. Build Backend Decision](#4-build-backend-decision) | setuptools / hatchling / flit / poetry |\n| [5. PyPA Packaging Flow](#5-pypa-packaging-flow) | The canonical publish pipeline |\n| [6. Project Structure Templates](#6-project-structure-templates) | Full layouts for every option |\n| [7. Versioning Strategy](#7-versioning-strategy) | PEP 440, semver, dynamic vs static |\n\n| Reference file | What it covers |\n|---|---|\n| `references/pyproject-toml.md` | All four backend templates, `setuptools_scm`, `py.typed`, tool configs |\n| `references/library-patterns.md` | OOP/SOLID, type hints, core class design, factory, protocols, CLI |\n| `references/testing-quality.md` | `conftest.py`, unit/backend/async tests, ruff/mypy/pre-commit |\n| `references/ci-publishing.md` | `ci.yml`, `publish.yml`, Trusted Publishing, TestPyPI, CHANGELOG, release checklist |\n| `references/community-docs.md` | README, docstrings, CONTRIBUTING, SECURITY, anti-patterns, master checklist |\n| `references/architecture-patterns.md` | Backend system (plugin/strategy), config layer, transport layer, CLI, backend injection |\n| `references/versioning-strategy.md` | PEP 440, SemVer, pre-release, setuptools_scm deep-dive, flit static, decision engine |\n| `references/release-governance.md` | Branch strategy, branch protection, OIDC, tag author validation, prevent invalid tags |\n| `references/tooling-ruff.md` | Ruff-only setup (replaces black/isort), mypy config, pre-commit, asyncio_mode=auto |\n\n**Scaffold script:** run `python skills/python-pypi-package-builder/scripts/scaffold.py --name your-package-name`\nto generate the entire directory layout, stub files, and `pyproject.toml` in one command.\n\n---\n\n## 1. Skill Trigger\n\nLoad this skill whenever the user wants to:\n\n- Create, scaffold, or publish a Python package or library to PyPI\n- Build a pip-installable SDK, utility, CLI tool, or framework extension\n- Set up `pyproject.toml`, linting, mypy, pre-commit, or GitHub Actions for a Python project\n- Understand versioning (`setuptools_scm`, PEP 440, semver, static versioning)\n- Understand PyPA specs: `py.typed`, `MANIFEST.in`, `RECORD`, classifiers\n- Publish to PyPI using Trusted Publishing (OIDC) or API tokens\n- Refactor an existing package to follow modern Python packaging standards\n- Add type hints, protocols, ABCs, or dataclasses to a Python library\n- Apply OOP/SOLID design patterns to a Python package\n- Choose between build backends (setuptools, hatchling, flit, poetry)\n\n**Also trigger for phrases like:** \"build a Python SDK\", \"publish my library\", \"set up PyPI CI\",\n\"create a pip package\", \"how do I publish to PyPI\", \"pyproject.toml help\", \"PEP 561 typed\",\n\"setuptools_scm version\", \"semver Python\", \"PEP 440\", \"git tag release\", \"Trusted Publishing\".\n\n---\n\n## 2. Package Type Decision\n\nIdentify what the user is building **before** writing any code. Each type has distinct patterns.\n\n### Decision Table\n\n| Type | Core Pattern | Entry Point | Key Deps | Example Packages |\n|---|---|---|---|---|\n| **Utility library** | Module of pure functions + helpers | Import API only | Minimal | `arrow`, `humanize`, `boltons`, `more-itertools` |\n| **API client / SDK** | Class with methods, auth, retry logic | Import API only | `httpx` or `requests` | `boto3`, `stripe-python`, `openai` |\n| **CLI tool** | Command functions + argument parser | `[project.scripts]` or `[project.entry-points]` | `click` or `typer` | `black`, `ruff`, `httpie`, `rich` |\n| **Framework plugin** | Plugin class, hook registration | `[project.entry-points.\"framework.plugin\"]` | Framework dep | `pytest-*`, `django-*`, `flask-*` |\n| **Data processing library** | Classes + functional pipeline | Import API only | Optional: `numpy`, `pandas` | `pydantic`, `marshmallow`, `cerberus` |\n| **Mixed / generic** | Combination of above | Varies | Varies | Many real-world packages |\n\n**Decision Rule:** Ask the user if unclear. A package can combine types (e.g., SDK with a CLI\nentry point) — use the primary type for structural decisions and add secondary type patterns on top.\n\nFor implementation patterns of each type, see `references/library-patterns.md`.\n\n### Package Naming Rules\n\n- PyPI name: all lowercase, hyphens — `my-python-library`\n- Python import name: underscores — `my_python_library`\n- Check availability: https://pypi.org/search/ before starting\n- Avoid shadowing popular packages (verify `pip install <name>` fails first)\n\n---\n\n## 3. Folder Structure Decision\n\n### Decision Tree\n\n```\nDoes the package have 5+ internal modules OR multiple contributors OR complex sub-packages?\n├── YES → Use src/ layout\n│         Reason: prevents accidental import of uninstalled code during development;\n│         separates source from project root files; PyPA-recommended for large projects.\n│\n├── NO → Is it a single-module, focused package (e.g., one file + helpers)?\n│         ├── YES → Use flat layout\n│         └── NO (medium complexity) → Use flat layout, migrate to src/ if it grows\n│\n└── Is it multiple related packages under one namespace (e.g., myorg.http, myorg.db)?\n          └── YES → Use namespace/monorepo layout\n```\n\n### Quick Rule Summary\n\n| Situation | Use |\n|---|---|\n| New project, unknown future size | `src/` layout (safest default) |\n| Single-purpose, 1–4 modules | Flat layout |\n| Large library, many contributors | `src/` layout |\n| Multiple packages in one repo | Namespace / monorepo |\n| Migrating old flat project | Keep flat; migrate to `src/` at next major version |\n\n---\n\n## 4. Build Backend Decision\n\n### Decision Tree\n\n```\nDoes the user need version derived automatically from git tags?\n├── YES → Use setuptools + setuptools_scm\n│         (git tag v1.0.0 → that IS your release workflow)\n│\n└── NO → Does the user want an all-in-one tool (deps + build + publish)?\n          ├── YES → Use poetry (v2+ supports standard [project] table)\n          │\n          └── NO → Is the package pure Python with no C extensions?\n                    ├── YES, minimal config preferred → Use flit\n                    │   (zero config, auto-discovers version from __version__)\n                    │\n                    └── YES, modern & fast preferred → Use hatchling\n                        (zero-config, plugin system, no setup.py needed)\n\nDoes the package have C/Cython/Fortran extensions?\n└── YES → MUST use setuptools (only backend with full native extension support)\n```\n\n### Backend Comparison\n\n| Backend | Version source | Config | C extensions | Best for |\n|---|---|---|---|---|\n| `setuptools` + `setuptools_scm` | git tags (automatic) | `pyproject.toml` + optional `setup.py` shim | Yes | Projects with git-tag releases; any complexity |\n| `hatchling` | manual or plugin | `pyproject.toml` only | No | New pure-Python projects; fast, modern |\n| `flit` | `__version__` in `__init__.py` | `pyproject.toml` only | No | Very simple, single-module packages |\n| `poetry` | `pyproject.toml` field | `pyproject.toml` only | No | Teams wanting integrated dep management |\n\nFor all four complete `pyproject.toml` templates, see `references/pyproject-toml.md`.\n\n---\n\n## 5. PyPA Packaging Flow\n\nThis is the canonical end-to-end flow from source code to user install.\n**Every step must be understood before publishing.**\n\n```\n1. SOURCE TREE\n   Your code in version control (git)\n   └── pyproject.toml describes metadata + build system\n\n2. BUILD\n   python -m build\n   └── Produces two artifacts in dist/:\n       ├── *.tar.gz   → source distribution (sdist)\n       └── *.whl      → built distribution (wheel) — preferred by pip\n\n3. VALIDATE\n   twine check dist/*\n   └── Checks metadata, README rendering, and PyPI compatibility\n\n4. TEST PUBLISH (first release only)\n   twine upload --repository testpypi dist/*\n   └── Verify: pip install --index-url https://test.pypi.org/simple/ your-package\n\n5. PUBLISH\n   twine upload dist/*          ← manual fallback\n   OR GitHub Actions publish.yml  ← recommended (Trusted Publishing / OIDC)\n\n6. USER INSTALL\n   pip install your-package\n   pip install \"your-package[extra]\"\n```\n\n### Key PyPA Concepts\n\n| Concept | What it means |\n|---|---|\n| **sdist** | Source distribution — your source + metadata; used when no wheel is available |\n| **wheel (.whl)** | Pre-built binary — pip extracts directly into site-packages; no build step |\n| **PEP 517/518** | Standard build system interface via `pyproject.toml [build-system]` table |\n| **PEP 621** | Standard `[project]` table in `pyproject.toml`; all modern backends support it |\n| **PEP 639** | `license` key as SPDX string (e.g., `\"MIT\"`, `\"Apache-2.0\"`) — not `{text = \"MIT\"}` |\n| **PEP 561** | `py.typed` empty marker file — tells mypy/IDEs this package ships type information |\n\nFor complete CI workflow and publishing setup, see `references/ci-publishing.md`.\n\n---\n\n## 6. Project Structure Templates\n\n### A. src/ Layout (Recommended default for new projects)\n\n```\nyour-package/\n├── src/\n│   └── your_package/\n│       ├── __init__.py           # Public API: __all__, __version__\n│       ├── py.typed              # PEP 561 marker — EMPTY FILE\n│       ├── core.py               # Primary implementation\n│       ├── client.py             # (API client type) or remove\n│       ├── cli.py                # (CLI type) click/typer commands, or remove\n│       ├── config.py             # Settings / configuration dataclass\n│       ├── exceptions.py         # Custom exception hierarchy\n│       ├── models.py             # Data classes, Pydantic models, TypedDicts\n│       ├── utils.py              # Internal helpers (prefix _utils if private)\n│       ├── types.py              # Shared type aliases and TypeVars\n│       └── backends/             # (Plugin pattern) — remove if not needed\n│           ├── __init__.py       # Protocol / ABC interface definition\n│           ├── memory.py         # Default zero-dep implementation\n│           └── redis.py          # Optional heavy implementation\n├── tests/\n│   ├── __init__.py\n│   ├── conftest.py               # Shared fixtures\n│   ├── unit/\n│   │   ├── __init__.py\n│   │   ├── test_core.py\n│   │   ├── test_config.py\n│   │   └── test_models.py\n│   ├── integration/\n│   │   ├── __init__.py\n│   │   └── test_backends.py\n│   └── e2e/                      # Optional: end-to-end tests\n│       └── __init__.py\n├── docs/                         # Optional: mkdocs or sphinx\n├── scripts/\n│   └── scaffold.py\n├── .github/\n│   ├── workflows/\n│   │   ├── ci.yml\n│   │   └── publish.yml\n│   └── ISSUE_TEMPLATE/\n│       ├── bug_report.md\n│       └── feature_request.md\n├── .pre-commit-config.yaml\n├── pyproject.toml\n├── CHANGELOG.md\n├── CONTRIBUTING.md\n├── SECURITY.md\n├── LICENSE\n├── README.md\n└── .gitignore\n```\n\n### B. Flat Layout (Small / focused packages)\n\n```\nyour-package/\n├── your_package/         # ← at root, not inside src/\n│   ├── __init__.py\n│   ├── py.typed\n│   └── ... (same internal structure)\n├── tests/\n└── ... (same top-level files)\n```\n\n### C. Namespace / Monorepo Layout (Multiple related packages)\n\n```\nyour-org/\n├── packages/\n│   ├── your-org-core/\n│   │   ├── src/your_org/core/\n│   │   └── pyproject.toml\n│   ├── your-org-http/\n│   │   ├── src/your_org/http/\n│   │   └── pyproject.toml\n│   └── your-org-cli/\n│       ├── src/your_org/cli/\n│       └── pyproject.toml\n├── .github/workflows/\n└── README.md\n```\n\nEach sub-package has its own `pyproject.toml`. They share the `your_org` namespace via PEP 420\nimplicit namespace packages (no `__init__.py` in the namespace root).\n\n### Internal Module Guidelines\n\n| File | Purpose | When to include |\n|---|---|---|\n| `__init__.py` | Public API surface; re-exports; `__version__` | Always |\n| `py.typed` | PEP 561 typed-package marker (empty) | Always |\n| `core.py` | Primary class / main logic | Always |\n| `config.py` | Settings dataclass or Pydantic model | When configurable |\n| `exceptions.py` | Exception hierarchy (`YourBaseError` → specifics) | Always |\n| `models.py` | Data models / DTOs / TypedDicts | When data-heavy |\n| `utils.py` | Internal helpers (not part of public API) | As needed |\n| `types.py` | Shared `TypeVar`, `TypeAlias`, `Protocol` definitions | When complex typing |\n| `cli.py` | CLI entry points (click/typer) | CLI type only |\n| `backends/` | Plugin/strategy pattern | When swappable implementations |\n| `_compat.py` | Python version compatibility shims | When 3.9–3.13 compat needed |\n\n---\n\n## 7. Versioning Strategy\n\n### PEP 440 — The Standard\n\n```\nCanonical form:  N[.N]+[{a|b|rc}N][.postN][.devN]\n\nExamples:\n  1.0.0          Stable release\n  1.0.0a1        Alpha (pre-release)\n  1.0.0b2        Beta\n  1.0.0rc1       Release candidate\n  1.0.0.post1    Post-release (e.g., packaging fix only)\n  1.0.0.dev1     Development snapshot (not for PyPI)\n```\n\n### Semantic Versioning (recommended)\n\n```\nMAJOR.MINOR.PATCH\n\nMAJOR: Breaking API change (remove/rename public function/class/arg)\nMINOR: New feature, fully backward-compatible\nPATCH: Bug fix, no API change\n```\n\n### Dynamic versioning with setuptools_scm (recommended for git-tag workflows)\n\n```bash\n# How it works:\ngit tag v1.0.0          →  installed version = 1.0.0\ngit tag v1.1.0          →  installed version = 1.1.0\n(commits after tag)     →  version = 1.1.0.post1  (suffix stripped for PyPI)\n\n# In code — NEVER hardcode when using setuptools_scm:\nfrom importlib.metadata import version, PackageNotFoundError\ntry:\n    __version__ = version(\"your-package\")\nexcept PackageNotFoundError:\n    __version__ = \"0.0.0-dev\"    # Fallback for uninstalled dev checkouts\n```\n\nRequired `pyproject.toml` config:\n```toml\n[tool.setuptools_scm]\nversion_scheme = \"post-release\"\nlocal_scheme   = \"no-local-version\"   # Prevents +g<hash> from breaking PyPI uploads\n```\n\n**Critical:** always set `fetch-depth: 0` in every CI checkout step. Without full git history,\n`setuptools_scm` cannot find tags and the build version silently falls back to `0.0.0+dev`.\n\n### Static versioning (flit, hatchling manual, poetry)\n\n```python\n# your_package/__init__.py\n__version__ = \"1.0.0\"    # Update this before every release\n```\n\n### Version specifier best practices for dependencies\n\n```toml\n# In [project] dependencies:\n\"httpx>=0.24\"            # Minimum version — PREFERRED for libraries\n\"httpx>=0.24,<1.0\"       # Upper bound only when a known breaking change exists\n\"httpx==0.27.0\"          # Pin exactly ONLY in applications, NOT libraries\n\n# NEVER do this in a library — it breaks dependency resolution for users:\n# \"httpx~=0.24.0\"        # Too tight\n# \"httpx==0.27.*\"        # Fragile\n```\n\n### Version bump → release flow\n\n```bash\n# 1. Update CHANGELOG.md — move [Unreleased] entries to [x.y.z] - YYYY-MM-DD\n# 2. Commit the changelog\ngit add CHANGELOG.md\ngit commit -m \"chore: prepare release vX.Y.Z\"\n# 3. Tag and push — this triggers publish.yml automatically\ngit tag vX.Y.Z\ngit push origin main --tags\n# 4. Monitor GitHub Actions → verify on https://pypi.org/project/your-package/\n```\n\nFor complete pyproject.toml templates for all four backends, see `references/pyproject-toml.md`.\n\n---\n\n## Where to Go Next\n\nAfter understanding decisions and structure:\n\n1. **Set up `pyproject.toml`** → `references/pyproject-toml.md`\n   All four backend templates (setuptools+scm, hatchling, flit, poetry), full tool configs,\n   `py.typed` setup, versioning config.\n\n2. **Write your library code** → `references/library-patterns.md`\n   OOP/SOLID principles, type hints (PEP 484/526/544/561), core class design, factory functions,\n   `__init__.py`, plugin/backend pattern, CLI entry point.\n\n3. **Add tests and code quality** → `references/testing-quality.md`\n   `conftest.py`, unit/backend/async tests, parametrize, ruff/mypy/pre-commit setup.\n\n4. **Set up CI/CD and publish** → `references/ci-publishing.md`\n   `ci.yml`, `publish.yml` with Trusted Publishing (OIDC, no API tokens), CHANGELOG format,\n   release checklist.\n\n5. **Polish for community/OSS** → `references/community-docs.md`\n   README sections, docstring format, CONTRIBUTING, SECURITY, issue templates, anti-patterns\n   table, and master release checklist.\n\n6. **Design backends, config, transport, CLI** → `references/architecture-patterns.md`\n   Backend system (plugin/strategy pattern), Settings dataclass, HTTP transport layer,\n   CLI with click/typer, backend injection rules.\n\n7. **Choose and implement a versioning strategy** → `references/versioning-strategy.md`\n   PEP 440 canonical forms, SemVer rules, pre-release identifiers, setuptools_scm deep-dive,\n   flit static versioning, decision engine (DEFAULT/BEGINNER/MINIMAL).\n\n8. **Govern releases and secure the publish pipeline** → `references/release-governance.md`\n   Branch strategy, branch protection rules, OIDC Trusted Publishing setup, tag author\n   validation in CI, tag format enforcement, full governed `publish.yml`.\n\n9. **Simplify tooling with Ruff** → `references/tooling-ruff.md`\n   Ruff-only setup replacing black/isort/flake8, mypy config, pre-commit hooks,\n   asyncio_mode=auto (remove @pytest.mark.asyncio), migration guide.","tags":["python","pypi","package","builder","awesome","copilot","github","agent-skills","agents","custom-agents","github-copilot","hacktoberfest"],"capabilities":["skill","source-github","skill-python-pypi-package-builder","topic-agent-skills","topic-agents","topic-awesome","topic-custom-agents","topic-github-copilot","topic-hacktoberfest","topic-prompt-engineering"],"categories":["awesome-copilot"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/github/awesome-copilot/python-pypi-package-builder","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add github/awesome-copilot","source_repo":"https://github.com/github/awesome-copilot","install_from":"skills.sh"}},"qualityScore":"0.700","qualityRationale":"deterministic score 0.70 from registry signals: · indexed on github topic:agent-skills · 30743 github stars · SKILL.md body (17,790 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-22T00:52:15.247Z","embedding":null,"createdAt":"2026-04-18T21:50:44.481Z","updatedAt":"2026-04-22T00:52:15.247Z","lastSeenAt":"2026-04-22T00:52:15.247Z","tsv":"'-2.0':1236 '/project/your-package/':1913 '/search/':710 '/simple/':1134 '0':1760 '0.0.0':1724,1783 '0.24':1812,1819 '0.24.0':1852 '0.27':1856 '0.27.0':1831 '1':147,150,366,829,1068,1863,1933 '1.0':1820 '1.0.0':1609,1612,1618,1621,1625,1634,1685,1795 '1.1.0':1691,1696 '2':159,163,521,1082,1875,1954 '3':173,177,722,1103,1889,1978 '3.13':1588 '3.9':1587 '4':187,191,830,860,1115,1905,1991 '420':1481 '440':38,235,302,420,515,1595,2063 '484/526/544/561':1965 '5':200,204,732,1042,1138,2011 '517/518':1203 '561':507,1241,1288,1512 '6':213,217,1153,1262,2032 '621':1215 '639':1227 '7':227,230,1591,2054 '8':2083 '9':2112 'a1':1613 'abc':455,1345 'accident':749 'action':410,1147,1908 'add':451,673,1880,1979 'agent':84 'ai':83 'alias':1332 'all-in-on':895 'alpha':1614 'also':478 'alway':1509,1518,1524,1538,1755 'anti':285,2025 'anti-pattern':284,2024 'apach':1235 'api':439,559,568,578,626,1283,1296,1503,1555,1647,1663,2005 'appli':122,462 'applic':1836 'argument':592 'arrow':562 'artifact':1089 'ask':648 'asyncio':340,2130 'auth':574 'author':323,2102 'auto':342,930,2132 'auto-discov':929 'automat':872,981,1896 'avail':707,1185 'avoid':713 'b':1406,1603 'b2':1619 'back':1781 'backend':30,104,189,194,248,290,298,473,862,960,966,968,1223,1335,1575,1921,1940,2034,2039,2051 'backward':1657 'backward-compat':1656 'bash':1676,1862 'battl':56 'battle-test':55 'best':974,1803 'beta':1620 'binari':1191 'black':601 'black/isort':334 'black/isort/flake8':2123 'bolton':564 'boto3':583 'bound':1822 'branch':317,319,2092,2094 'break':1646,1751,1827,1846 'bug':1660 'bug_report.md':1396 'build':12,29,60,172,188,193,388,472,483,530,861,901,1080,1083,1086,1200,1205,1211,1777 'build-backend-decis':192 'build-system':1210 'builder':5,51 'built':1097,1190 'bump':1859 'c':919,972,1434 'c/cython/fortran':953 'candid':1624 'cannot':1772 'canon':210,1049,1598,2064 'cerberus':633 'chang':1648,1664,1828 'changelog':276,1878,2007 'changelog.md':1400,1865,1881 'check':706,1106,1108 'checklist':278,288,2010,2031 'checkout':1730,1764 'choos':470,2055 'chore':1885 'ci':108,493,1255,1763,2105 'ci.yml':271,1392,1998 'ci/cd':1994 'class':260,571,608,622,1318,1521,1967 'classifi':430 'cli':130,264,297,395,588,662,1302,1460,1568,1572,1975,2037,2048 'cli.py':1301,1567 'click':598 'click/typer':1304,1571,2050 'client':569,1297 'client.py':1295 'code':96,534,753,1057,1072,1703,1958,1982 'combin':636,656 'command':365,590,1305 'commit':77,339,407,1692,1876,1883,2128 'communiti':80 'community-readi':79 'community/oss':2014 'comparison':967 'compat':1114,1584,1589,1658 'compat.py':1581 'complet':54,1037,1254,1915 'complex':739,787,994,1565 'concept':1169,1170 'config':254,293,336,923,928,943,971,1733,1949,1953,2035,2125 'config.py':1308,1525 'configur':1310,1532 'conftest.py':266,1361,1985 'contribut':282,2020 'contributing.md':1401 'contributor':737,837 'control':1075 'core':259,543,1448,1966 'core.py':1292,1519 'cover':26,146,244 'creat':98,377,494 'critic':1754 'custom':1313 'data':132,619,1317,1540,1546 'data-heavi':1545 'dataclass':457,1311,1527,2044 'dd':1874 'decis':102,111,116,162,167,176,181,190,195,314,524,540,646,671,725,726,863,864,1930,2080 'deep':310,2075 'deep-div':309,2074 'default':825,1270,1349 'default/beginner/minimal':2082 'definit':1347,1563 'dep':548,615,900,1032,1352 'depend':1806,1810,1847 'depth':1759 'deriv':871 'describ':1078 'design':261,464,1968,2033 'dev':1725,1729,1784 'dev1':1635 'develop':755,1636 'devn':1607 'direct':1194 'directori':357 'discov':931 'dist':1091,1107,1125,1142 'distinct':538 'distribut':1094,1098,1176 'dive':311,2076 'django':617 'doc':1383 'docstr':281,2018 'dtos':1542 'dynam':42,237,1665 'e.g':658,777,805,1233,1630 'e2e':1374 'empti':1243,1290,1517 'end':7,9,1051,1053,1377,1379 'end-to-end':6,1050,1376 'enforc':2108 'engin':315,2081 'entir':88,356 'entri':545,663,1569,1868,1976 'everi':101,225,1061,1762,1799 'exact':1833 'exampl':549,1608 'except':1314,1534,1721 'exceptions.py':1312,1533 'exist':443,1829 'export':1507 'extens':399,920,954,964,973 'extra':1166 'extract':1193 'factori':262,1969 'fail':720 'fall':1780 'fallback':1144,1726 'fast':937,1007 'featur':1654 'feature_request.md':1397 'fetch':1758 'fetch-depth':1757 'field':1025 'file':89,100,143,241,360,761,779,1245,1291,1433,1495 'find':1773 'first':76,721,1118 'fix':1632,1661 'fixtur':1363 'flask':618 'flat':184,783,789,832,849,852,1407 'flit':35,198,312,476,926,1009,1787,1945,2077 'flow':203,208,1045,1054,1861 'focus':775,1410 'folder':174,179,723 'folder-structure-decis':178 'follow':114,446 'form':1599,2065 'format':2008,2019,2107 'four':28,247,1036,1920,1939 'fragil':1857 'framework':398,605,614 'framework.plugin':613 'full':222,962,1767,1947,2109 'fulli':1655 'function':556,591,623,1970 'function/class/arg':1651 'futur':820 'g':1749 'generat':354 'generic':635 'git':44,516,874,881,979,990,1076,1673,1680,1686,1768,1879,1882,1897,1900 'git-tag':43,989,1672 'github':409,1146,1390,1907 'github/workflows':1463 'gitignor':1405 'go':1926 'govern':2084,2110 'grade':21,70 'grow':796 'guid':58,2136 'guidelin':1494 'hardcod':1705 'hatchl':34,197,475,940,995,1788,1944 'heavi':1356,1547 'help':505 'helper':557,780,1324,1550 'hierarchi':1315,1535 'hint':258,453,1963 'histori':1769 'hook':609,2129 'http':1454,2045 'httpie':603 'httpx':580,1811,1818,1830,1851,1855 'human':563 'hyphen':694 'identifi':168,525,2071 'implement':680,1294,1353,1357,1580,2057 'implicit':1482 'import':558,577,625,700,750,1712 'importlib.metadata':1711 'includ':1499 'index':1130 'index-url':1129 'inform':1252 'init':1012,1280,1342,1359,1365,1371,1381,1422,1486,1500,1971 'inject':299,2052 'insid':1420 'instal':392,719,1060,1128,1155,1157,1162,1683,1689 'instruct':85 'integr':1031,1370 'interfac':1207,1346 'intern':733,1323,1426,1492,1549 'invalid':326 'issu':1394,2022 'itertool':567 'keep':851 'key':547,1167,1229 'known':1826 'larg':766,834 'layer':294,296,2047 'layout':103,223,358,746,784,790,811,823,833,839,1268,1408,1437 'level':1432 'librari':23,72,133,385,461,489,552,621,698,705,835,1817,1838,1844,1957 'licens':1228,1403 'like':482 'line':94 'lint':14,62,403 'load':156,369 'local':1742,1746 'logic':576,1523 'lowercas':693 'm':1085,1884 'main':1522,1903 'major':858,1645 'major.minor.patch':1644 'manag':1033 'mani':641,836 'manifest.in':428 'manual':996,1143,1789 'marker':1244,1289,1516 'marshmallow':632 'master':287,2029 'mean':1173 'medium':786 'memory.py':1348 'metadata':1079,1109,1179 'method':573 'migrat':791,847,853,2135 'minim':561,922 'minimum':1813 'minor':1652 'mit':1234,1239 'mix':634 'mkdoc':1385 'mm':1873 'mode':341,2131 'model':1320,1530,1541 'models.py':1316,1539 'modern':447,936,1008,1222 'modul':553,734,774,831,1021,1493 'monitor':1906 'monorepo':186,846,1436 'more-itertool':565 'move':1866 'multipl':736,799,840,1438 'must':956,1063 'my-python-librari':695 'myorg.db':807 'myorg.http':806 'mypi':335,404,2124 'mypy/ides':1247 'n':1600,1601,1605 'name':348,352,688,691,701 'namespac':804,845,1435,1478,1483,1490 'namespace/monorepo':810 'nativ':963 'navig':139 'need':869,948,1341,1557,1590 'never':1704,1839 'new':817,1002,1272,1653 'next':857,1927 'no-local-vers':1744 'numpi':629 'oidc':321,437,1152,2003,2097 'old':848 'one':364,778,803,843,898 'oop/sol':47 'oop/solid':256,463,1960 'openai':587 'option':226,628,983,1355,1375,1384 'order':119 'org':1443,1447,1453,1459,1477 'origin':1902 'packag':4,50,126,160,165,202,207,351,383,444,449,469,497,522,550,645,654,687,716,730,742,776,801,841,914,951,1022,1044,1137,1160,1165,1198,1249,1276,1279,1411,1414,1416,1440,1444,1468,1484,1515,1631,1720 'package-type-decis':164 'package/__init__.py':1793 'packagenotfounderror':1714,1722 'panda':630 'parametr':1988 'parser':593 'part':1552 'patch':1659 'pattern':107,286,465,539,544,676,681,1337,1577,1974,2026,2042 'pep':37,234,301,419,506,514,1202,1214,1226,1240,1287,1480,1511,1594,1964,2062 'phrase':481 'pin':1832 'pip':391,496,718,1102,1127,1156,1161,1192 'pip-instal':390 'pipelin':212,624,2090 'plugin':131,606,607,944,998,1336 'plugin/backend':1973 'plugin/strategy':292,1576,2041 'poetri':36,199,477,905,1023,1790,1946 'point':546,597,612,664,1570,1977 'polish':2012 'popular':715 'post':1628,1740 'post-releas':1627,1739 'post1':1626,1697 'postn':1606 'practic':1804 'pre':305,338,406,1189,1616,2069,2127 'pre-built':1188 'pre-commit':337,405,2126 'pre-commit-config.yaml':1398 'pre-releas':304,1615,2068 'prefer':924,938,1100,1815 'prefix':1325 'prepar':1886 'prevent':325,748,1748 'primari':667,1293,1520 'principl':1961 'privat':1328 'process':620 'produc':1087 'product':20,69 'production-grad':19,68 'project':214,219,414,759,767,818,850,909,987,1006,1217,1263,1273,1809 'project-structure-templ':218 'project.entry':596,611 'project.scripts':594 'protect':320,2095 'protocol':263,454,1344,1562 'public':1282,1502,1554,1650 'publish':17,66,211,274,380,431,436,487,501,520,902,1067,1117,1139,1151,1258,1996,2002,2089,2099 'publish.yml':272,1148,1393,1895,1999,2111 'pure':555,915,1004 'pure-python':1003 'purpos':828,1496 'push':1892,1901 'py':1013,1281,1343,1360,1366,1372,1382,1423,1487,1501,1972 'py.typed':252,427,1242,1286,1424,1510,1950 'pydant':631,1319,1529 'pypa':201,206,425,763,1043,1168 'pypa-packaging-flow':205 'pypa-recommend':762 'pypi':3,25,49,74,387,433,492,503,690,1113,1640,1701,1752 'pypi.org':709,1912 'pypi.org/project/your-package/':1911 'pypi.org/search/':708 'pyproject.toml':362,402,504,982,999,1014,1024,1026,1038,1077,1209,1220,1399,1450,1456,1462,1472,1732,1916,1936 'pytest':616 'pytest.mark.asyncio':2134 'python':2,22,48,71,125,346,382,413,448,460,468,485,513,586,697,699,704,916,1005,1084,1582,1791 'python-pypi-package-build':1 'qualiti':1983 'quick':138,812 'rc':1604 'rc1':1622 're':1506 're-export':1505 'read':86 'readi':81 'readm':280,1110,2016 'readme.md':1404,1464 'real':643 'real-world':642 'reason':747 'recommend':764,1149,1269,1643,1670 'record':429 'redis.py':1354 'refactor':441 'refer':240 'references/architecture-patterns.md':289,2038 'references/ci-publishing.md':270,1261,1997 'references/community-docs.md':279,2015 'references/library-patterns.md':255,686,1959 'references/pyproject-toml.md':245,1041,1923,1937 'references/release-governance.md':316,2091 'references/testing-quality.md':265,1984 'references/tooling-ruff.md':328,2117 'references/versioning-strategy.md':300,2061 'registr':610 'relat':800,1439 'releas':82,277,306,518,887,992,1119,1611,1617,1623,1629,1741,1800,1860,1887,2009,2030,2070,2085 'remov':1300,1307,1338,2133 'remove/rename':1649 'render':1111 'replac':333,2122 'repo':844 'repositori':1123 'request':582 'requir':1731 'resolut':1848 'retri':575 'rich':604 'root':760,1418,1491 'ruff':330,602,2116,2119 'ruff-on':329,2118 'ruff/mypy/pre-commit':269,1989 'rule':112,647,689,813,2053,2067,2096 'run':345 'safest':824 'scaffold':343,378 'scaffold.py':1389 'scheme':1738,1743 'scm':33,251,308,418,510,880,978,1669,1709,1736,1771,1943,2073 'script':344,1388 'sdist':1095,1174 'sdk':129,393,486,570,659 'secondari':674 'section':137,140,2017 'secur':283,2021,2087 'security.md':1402 'see':685,1040,1260,1922 'semant':40,1641 'semver':236,303,421,512,2066 'separ':756 'set':400,490,1309,1526,1756,1934,1992,2043 'setup':332,1259,1951,1990,2100,2121 'setup.py':947,984 'setuptool':31,32,196,250,307,417,474,509,878,879,958,976,977,1668,1708,1770,1942,2072 'shadow':714 'share':1330,1362,1474,1559 'shim':985,1585 'ship':1250 'silent':1779 'simpl':1018 'simplifi':2113 'singl':93,773,827,1020 'single-modul':772,1019 'single-purpos':826 'site':1197 'site-packag':1196 'situat':815 'size':821 'skill':10,52,121,148,152,158,367,371 'skill-python-pypi-package-builder' 'skill-trigg':151 'skills/python-pypi-package-builder/scripts/scaffold.py':347 'skip':136 'small':1409 'snapshot':1637 'sourc':757,970,1056,1069,1093,1175,1178 'source-github' 'spdx':1231 'spec':426 'specif':1537 'specifi':1802 'sphinx':1387 'src':182,745,793,822,838,855,1267,1277,1421 'src/your_org/cli':1461 'src/your_org/core':1449 'src/your_org/http':1455 'stabl':1610 'standard':450,908,1204,1216,1597 'start':712 'static':239,313,422,1785,2078 'step':1062,1201,1765 'strategi':106,229,233,318,1593,2060,2093 'string':1232 'strip':1699 'stripe':585 'stripe-python':584 'structur':175,180,215,220,670,724,1264,1427,1932 'stub':359 'sub':741,1467 'sub-packag':740,1466 'suffix':1698 'summari':814 'support':907,965,1224 'surfac':1504 'swappabl':1579 'system':291,945,1081,1206,1212,2040 'tabl':541,910,1213,1218,2027 'tag':45,322,327,517,875,882,980,991,1674,1681,1687,1694,1774,1890,1898,1904,2101,2106 'tar.gz':1092 'team':1029 'tell':1246 'templat':216,221,249,1039,1265,1395,1917,1941,2023 'test':13,57,61,268,1116,1358,1380,1428,1980,1987 'test.pypi.org':1133 'test.pypi.org/simple/':1132 'test_backends.py':1373 'test_config.py':1368 'test_core.py':1367 'test_models.py':1369 'testpypi':275,1124 'text':1238 'tight':1854 'token':440,2006 'toml':1734,1807 'tool':253,396,589,899,1948,2114 'tool.setuptools':1735 'top':678,1431 'top-level':1430 'topic-agent-skills' 'topic-agents' 'topic-awesome' 'topic-custom-agents' 'topic-github-copilot' 'topic-hacktoberfest' 'topic-prompt-engineering' 'transport':295,2036,2046 'tree':117,727,865,1070 'tri':1715 'trigger':149,153,368,479,1894 'trust':273,435,519,1150,2001,2098 'twine':1105,1121,1140 'two':1088 'type':64,127,161,166,257,452,508,523,536,542,657,668,675,684,1251,1298,1303,1331,1514,1566,1573,1962 'typealia':1561 'typed-packag':1513 'typeddict':1321,1543 'typer':600 'types.py':1329,1558 'typevar':1334,1560 'unclear':652 'underscor':702 'understand':415,424,1929 'understood':1065 'uninstal':752,1728 'unit':1364 'unit/backend/async':267,1986 'unknown':819 'unreleas':1867 'updat':1796,1864 'upload':1122,1141,1753 'upper':1821 'url':1131 'use':434,665,744,782,788,809,816,877,904,925,939,957,1180,1707 'user':374,528,650,868,892,1059,1154,1850 'util':128,394,551,1326 'utils.py':1322,1548 'v1.0.0':883,1682 'v1.1.0':1688 'v2':906 'valid':324,1104,2103 'vari':639,640 'verifi':717,1126,1909 'version':15,39,41,46,63,105,228,232,416,423,511,859,870,932,934,969,1010,1074,1285,1508,1583,1592,1642,1666,1684,1690,1695,1713,1716,1717,1723,1737,1747,1778,1786,1794,1801,1814,1858,1952,2059,2079 'versioning-strategi':231 'via':1208,1479 'vs':183,185,238 'vx.y.z':1888,1899 'want':375,893,1030 'wheel':1099,1183,1186 'whenev':372 'whl':1096,1187 'without':1766 'work':1679 'workflow':888,1256,1391,1675 'world':644 'write':91,532,1955 'x.y.z':1870 'yes':743,781,808,876,903,921,935,955,986 'your-org':1441 'your-org-c':1457 'your-org-cor':1445 'your-org-http':1451 'your-packag':1135,1158,1163,1274,1412,1718 'your-package-nam':349 'yourbaseerror':1536 'yyyi':1872 'yyyy-mm-dd':1871 'zero':927,942,1351 'zero-config':941 'zero-dep':1350","prices":[{"id":"7536cfbf-0963-40eb-a7b2-f777debb6791","listingId":"014aeafe-6bf2-421f-83d2-7e44e25706b0","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"github","category":"awesome-copilot","install_from":"skills.sh"},"createdAt":"2026-04-18T21:50:44.481Z"}],"sources":[{"listingId":"014aeafe-6bf2-421f-83d2-7e44e25706b0","source":"github","sourceId":"github/awesome-copilot/python-pypi-package-builder","sourceUrl":"https://github.com/github/awesome-copilot/tree/main/skills/python-pypi-package-builder","isPrimary":false,"firstSeenAt":"2026-04-18T21:50:44.481Z","lastSeenAt":"2026-04-22T00:52:15.247Z"}],"details":{"listingId":"014aeafe-6bf2-421f-83d2-7e44e25706b0","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"github","slug":"python-pypi-package-builder","github":{"repo":"github/awesome-copilot","stars":30743,"topics":["agent-skills","agents","ai","awesome","custom-agents","github-copilot","hacktoberfest","prompt-engineering"],"license":"mit","html_url":"https://github.com/github/awesome-copilot","pushed_at":"2026-04-21T22:20:21Z","description":"Community-contributed instructions, agents, skills, and configurations to help you make the most of GitHub Copilot.","skill_md_sha":"e7b4a3841bcc244179fedebcb1dc15e06dcafb64","skill_md_path":"skills/python-pypi-package-builder/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/github/awesome-copilot/tree/main/skills/python-pypi-package-builder"},"layout":"multi","source":"github","category":"awesome-copilot","frontmatter":{"name":"python-pypi-package-builder","description":"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."},"skills_sh_url":"https://skills.sh/github/awesome-copilot/python-pypi-package-builder"},"updatedAt":"2026-04-22T00:52:15.247Z"}}