Skip to main content

Python/PyPI

Publish Python packages to PyPI using Universal Release.

Detection​

Automatically detected when setup.py or pyproject.toml exists.

Configuration​

ecosystems:
python:
enabled: true
registry: https://upload.pypi.org/legacy/
validation:
build: true
test: true
lint: true

Credentials​

Store your PyPI token:

release secrets set PYPI_TOKEN

Get your token from pypi.org/manage/account/token.

Publishing​

# Publish with validation
release publish --ecosystem python

# Dry run
release publish --ecosystem python --dry-run

# Test PyPI
release publish --ecosystem python --registry https://test.pypi.org/legacy/

Configuration Formats​

[project]
name = "my-package"
version = "1.0.0"
description = "A brief description"
authors = [{ name = "Your Name", email = "you@example.com" }]
license = { text = "MIT" }
readme = "README.md"

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

setup.py (Legacy)​

from setuptools import setup

setup(
name="my-package",
version="1.0.0",
description="A brief description",
author="Your Name",
author_email="you@example.com",
packages=["my_package"],
)

Validation​

Universal Release validates:

  • βœ… pyproject.toml or setup.py exists
  • βœ… Build succeeds (python -m build)
  • βœ… Tests pass (pytest)
  • βœ… Linting passes (ruff check)
  • βœ… Package metadata is valid

Rollback​

PyPI does not support rollback or deletion. Once published, versions are permanent.

Best practice: Publish a new fixed version instead.

Best Practices​

Use pyproject.toml​

Modern Python projects should use pyproject.toml:

[project]
name = "my-package"
version = "1.0.0"
dependencies = [
"requests>=2.28.0",
]

[project.optional-dependencies]
dev = [
"pytest>=7.0.0",
"ruff>=0.1.0",
]

Include MANIFEST.in​

include README.md
include LICENSE
recursive-include my_package *.py

Version Management​

# Show current version
release version

# Bump version (updates pyproject.toml)
release version --bump patch

# Set specific version
release version --set 2.0.0

Test PyPI​

Test your package before publishing to production:

# Publish to Test PyPI
release publish --ecosystem python --registry https://test.pypi.org/legacy/

# Test installation
pip install --index-url https://test.pypi.org/simple/ my-package

Next Steps​