Skip to main content
Version: 2.18 (deprecated)


How to distribute packages to a PyPi repository

The publish goal is currently in the experimental Python backend. Activate it with this config:

backend_packages.add = [

This will register a new repositories field on the python_distribution target type, so that when you run pants publish on such targets they will be packaged into wheels and/or sdists, and then published to the repositories specified in your BUILD files.

Python Repositories

When publishing a python_distribution, you need to tell Pants which repositories to publish to. That is done with a new repositories field on python_distribution targets.

# ...

Each repository is either a repository URL or, when prefixed with @, a reference to a repository configured in the .pypirc file.

Keep Secrets Secret

We strongly discourage the use of secrets verbatim in your configuration files.

It is better to provide the required secrets using environment variables when running pants publish. Or, better yet, to use keyring as described in the Twine documentation

Environment variables

Pants will pass certain configuration environment variables, through to Twine. If multiple repositories are involved in a single publish goal, you can distinguish them by adding an undersore and the repository name (upper-cased, and with hyphens replaced with underscores) as a suffix on the environment variable names:

  • TWINE_USERNAME_<repository>
  • TWINE_PASSWORD_<repository>
  • TWINE_REPOSITORY_URL_<repository>
# Ephemeral file
export TWINE_USERNAME_PRIVATE_REPO="accountname"
export TWINE_PASSWORD_PRIVATE_REPO="secretvalue"

Given the example BUILD and .pypirc files from the previous section, demo could be published with the following command:

$ { source ./secrets && pants publish src/python:demo }