Skip to content
Back to skills

Python Packaging

ASecurity

Package a Python project with a single pyproject.toml, a src layout, and a clean build/publish path to PyPI including entry points. Use when turning a script or library into an installable, distributable package.

  • 7 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 5, 2026
ai-agentspythonrustdockergitapibackend

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 5, 2026

npx -y skills add Amey-Thakur/AI-SKILLS --skill python-packaging --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Python Packaging?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Python Packaging
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/amey-thakur-python-packaging/badge)](https://www.skillsdirectory.com/skills/amey-thakur-python-packaging)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: python-packaging
description: Package a Python project with a single pyproject.toml, a src layout, and a clean build/publish path to PyPI including entry points. Use when turning a script or library into an installable, distributable package.
---

# Python packaging

A package is a build contract, not a folder of files. Declare metadata and
dependencies once in `pyproject.toml`, isolate importable code under `src/`,
and let a standard builder produce the artifacts you upload.

## Method

1. **Make pyproject.toml the single source of truth.** Put `[project]`
   metadata (name, version, `requires-python`, `dependencies`,
   `optional-dependencies`) and a `[build-system]` table naming your backend
   (hatchling, setuptools, flit, or pdm). Delete `setup.py` and `setup.cfg`
   unless a backend needs them; do not split config across files.
2. **Adopt the src layout.** Place the importable package at
   `src/mypkg/__init__.py`. This forces tests to run against the installed
   package, not the working tree, so a missing `package_data` or bad import
   fails locally instead of after publish. Configure the backend to find
   `src`.
3. **Manage version deliberately.** Either set `version` statically and bump
   it per release, or use `dynamic = ["version"]` with a scheme that reads a
   git tag (hatch-vcs, setuptools-scm). Follow semantic versioning and never
   reuse a version number; PyPI rejects re-uploads of an existing version.
4. **Declare entry points for executables and plugins.** A console command
   is `[project.scripts]` mapping `mytool = "mypkg.cli:main"`; that installs
   a wrapper on PATH without a manual shebang. Plugin discovery uses
   `[project.entry-points."group.name"]`. Package a CLI this way rather than
   shipping a loose script; see python-cli-tools.
5. **Build isolated artifacts.** Run `python -m build` to produce both an
   sdist (`.tar.gz`) and a wheel (`.whl`) in a clean environment. Check them
   with `twine check dist/*` and inspect the wheel contents to confirm no
   stray files or missing data.
6. **Publish through an isolated token, TestPyPI first.** Upload to TestPyPI
   with `twine upload -r testpypi dist/*`, install from there into a fresh
   venv, then upload to PyPI. Prefer a scoped API token or Trusted Publishing
   (OIDC from CI) over a password. Tag the release commit.

## Boundaries

- This is library and tool packaging. Application deployment (Docker images,
  lockfile-pinned installs, reproducibility) belongs to python-environments.
- Compiled extensions need platform wheels and often cibuildwheel; a single
  pure-Python wheel will not cover them.
- Do not publish secrets: audit the sdist, since it includes files a wheel
  omits and can leak `.env` or credentials if `MANIFEST`/excludes are wrong.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…