Skip to content

Python Packaging

Status: 🟢 Active  |  Owner: Python Guild

Package vs Application

Project Type Build Tool Distribution
Internal library / SDK Poetry + build Internal PyPI (Artifactory)
Service / application Poetry Docker image
CLI tool Poetry + pyproject.toml entry point Internal PyPI or Docker
Data science notebook N/A Not packaged — repo only

Building a Distributable Library

# pyproject.toml for a library
[tool.poetry]
name = "acme-shared-auth"
version = "1.2.0"
description = "Shared authentication middleware for ACME services"
authors = ["Platform Team <[email protected]>"]
readme = "README.md"
packages = [{include = "acme_shared_auth", from = "src"}]

[tool.poetry.dependencies]
python = "^3.10"
pydantic = "^2.0"

Use src/ layout for libraries to prevent accidental imports from the project root:

my-library/
├── src/
│   └── acme_shared_auth/
│       ├── __init__.py
│       └── middleware.py
├── tests/
├── pyproject.toml
└── README.md

Versioning

Library versions follow SemVer:

  • Patch (1.2.0 → 1.2.1): Bug fixes, no API changes.
  • Minor (1.2.x → 1.3.0): New features, backward compatible.
  • Major (1.x → 2.0.0): Breaking API changes — requires migration guide.

Use poetry version to bump:

poetry version patch   # 1.2.0 → 1.2.1
poetry version minor   # 1.2.1 → 1.3.0
poetry version major   # 1.3.0 → 2.0.0

Publishing to Internal PyPI

Publishing is automated via CI. Do not publish manually.

# .github/workflows/publish.yml
- name: Build and publish
  run: |
    poetry config repositories.internal ${{ vars.INTERNAL_PYPI_URL }}
    poetry config http-basic.internal ${{ secrets.PYPI_USER }} ${{ secrets.PYPI_TOKEN }}
    poetry build
    poetry publish --repository internal

Installing from Internal PyPI

Configure pip or Poetry to look at the internal registry:

# pyproject.toml
[[tool.poetry.source]]
name = "internal"
url = "https://pypi.acme.internal/simple/"
priority = "primary"

Entry Points for CLI Tools

[tool.poetry.scripts]
acme-deploy = "acme_deploy.cli:main"

This registers a acme-deploy command when the package is installed.

References


Last reviewed: 2025-Q4  |  Owner: Python Guild