---
url: /en/artifact/pypi.md
description: >
  Guide for configuring credentials and using the CNB PyPI artifact registry to
  upload and install Python packages, covering local development and CI pipeline
  workflows.
---
The PyPI Artifact Registry is used for storing and distributing Python packages,
supporting developers in uploading, managing, and installing various Python third-party libraries and tools.

## Prerequisites

1. [Create Artifact Registry](./intro.md#creating-an-artifact-registry)
2. [Obtain Artifact Registry Address](./intro.md#obtaining-the-artifact-registry-address)
3. [Create Access Token](./intro.md#creating-an-access-token)

## Local Development

### Configure Pull Credentials

* Option 1: Add pip source configuration in `~/.pip/pip.conf` (MacOS/Linux) or `%HOME%\pip\pip.ini` (Windows)

```INI
[global]
# YOUR_TOKEN: Access token password; REPO_URL: Artifact Registry address
# Example: index-url = https://cnb:<YOUR_TOKEN>@pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
index-url = https://cnb:<YOUR_TOKEN>@<REPO_URL>
```

* Option 2: You can also use command-line setup

```shell
# YOUR_TOKEN: Access token password; REPO_URL: Artifact Registry address
# Example: pip config set global.index-url
#   https://cnb:<YOUR_TOKEN>@pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
pip config set global.index-url https://cnb:<YOUR_TOKEN>@<REPO_URL>
```

### Configure Push Credentials

#### twine configuration

Add the following configuration in `~/.pypirc` file

```INI
[distutils]
index-servers =
  cnb-pypi-repo
[cnb-pypi-repo]
# Artifact Registry address
repository: <REPO_URL>
username: cnb
# Access token password
password: <YOUR_TOKEN>
```

Example:

```INI
[distutils]
index-servers =
  cnb-pypi-repo
[cnb-pypi-repo]
repository: https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
username: cnb
password: "<YOUR_TOKEN>"
```

#### poetry configuration

Run the following commands

```shell
poetry config http-basic.cnb-pypi-repo cnb <YOUR_TOKEN> # Access token password
poetry config repositories.cnb-pypi-repo <REPO_URL> # Artifact Registry address
```

Example:

```shell
poetry config http-basic.cnb-pypi-repo cnb <YOUR_TOKEN>
poetry config repositories.cnb-pypi-repo https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
```

### Pull Artifacts

```shell
#Example 1: pip install requests
#Example 2: Pull a specific version pip install requests==2.30.1
pip install <PACKAGE_NAME>

# Example, pull from a temporary source
#   pip install -i https://cnb:<YOUR_TOKEN>@pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple requests
pip install -i https://cnb:<YOUR_TOKEN>@<REPO_URL> <PACKAGE_NAME>

```

### Build and Push Artifacts

#### twine

```shell
python -m build
twine upload -r cnb-pypi-repo dist/*
```

#### poetry

```shell
poetry build
poetry publish -r cnb-pypi-repo
```

## Cloud Native Build

Cloud Native Build supports two methods for token usage,
see \[Using Tokens in Cloud Native Build and Workspaces]
(./intro.md#using-tokens-in-cloud-native-build-and-cloud-native-development).

### Pull Artifacts

Configure the pip source with `CNB_TOKEN` and install the package:

```yaml title=".cnb.yml"
main:
  push:
    - docker:
        image: docker.cnb.cool/examples/language/python-3:latest
      stages:
        - name: Pull artifacts
          script:
            - pip config set global.index-url
              https://cnb:${CNB_TOKEN}@pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
            - pip install requests
```

### Push Artifacts

Core pattern: trigger on `tag_push` event to update version and publish.

#### twine

```yaml title=".cnb.yml"
$:
  tag_push:
    - docker:
        image: docker.cnb.cool/examples/language/python-3:latest
      stages:
        - name: Build & Upload to repository
          script:
            - export TWINE_USERNAME=${CNB_TOKEN_USER_NAME}
            - export TWINE_PASSWORD=${CNB_TOKEN}
            - export TWINE_REPOSITORY_URL=https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
            - python -m build
            - twine upload dist/*
```

#### poetry

```yaml title=".cnb.yml"
$:
  tag_push:
    - docker:
        image: docker.cnb.cool/examples/language/python-3:latest
      stages:
        - name: Build & Upload to repository
          script:
            - export POETRY_HTTP_BASIC_CNB_PYPI_REPO_USERNAME=${CNB_TOKEN_USER_NAME}
            - export POETRY_HTTP_BASIC_CNB_PYPI_REPO_PASSWORD=${CNB_TOKEN}
            - poetry config repositories.cnb-pypi-repo https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
            - poetry build
            - poetry publish -r cnb-pypi-repo
```

If using secret repository files, replace `${CNB_TOKEN}` etc. with `${USER_NAME}`/`${PASS_WORD}`.

## Workspaces

Workspaces supports two methods for token usage,
see \[Using Tokens in Cloud Native Build and Workspaces]
(./intro.md#using-tokens-in-cloud-native-build-and-cloud-native-development).

### Prerequisites

Add the following configuration in `.cnb.yml` file

```yaml title=".cnb.yml"
$:
  vscode:
    - docker:
        image: docker.cnb.cool/examples/language/python-3:latest
      services:
        - vscode
        - docker
```

### Configure Pull Credentials

Enter the following commands in the Workspaces TERMINAL:

```shell
# Option 1: Using built-in CNB_TOKEN (recommended)
pip config set global.index-url https://cnb:${CNB_TOKEN}@pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
# Option 2: Using the secret repository file
# pip config set global.index-url
#   https://${USER_NAME}:${PASS_WORD}@pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
```

### Configure Push Credentials

Enter the following commands in the Workspaces TERMINAL

#### twine

```shell
# Option 1: Using built-in CNB_TOKEN (recommended)
export TWINE_USERNAME=${CNB_TOKEN_USER_NAME}
export TWINE_PASSWORD="${CNB_TOKEN}"
export TWINE_REPOSITORY_URL=https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
# Option 2: Using the secret repository file
# export TWINE_USERNAME="${USER_NAME}"
# export TWINE_PASSWORD="${PASS_WORD}"
# export TWINE_REPOSITORY_URL=https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
```

#### poetry

```shell
# Option 1: Using built-in CNB_TOKEN (recommended)
export POETRY_HTTP_BASIC_CNB_PYPI_REPO_USERNAME=${CNB_TOKEN_USER_NAME}
export POETRY_HTTP_BASIC_CNB_PYPI_REPO_PASSWORD="${CNB_TOKEN}"
poetry config repositories.cnb-pypi-repo https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
# Option 2: Using the secret repository file
# export POETRY_HTTP_BASIC_CNB_PYPI_REPO_USERNAME="${USER_NAME}"
# export POETRY_HTTP_BASIC_CNB_PYPI_REPO_PASSWORD="${PASS_WORD}"
# poetry config repositories.cnb-pypi-repo https://pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple
```

### Pull Artifacts

```shell
# Example 1: pip install requests
# Example 2: pip install requests==2.30.1
# Example 3: Pull from a temporary source
pip install -i https://cnb:${CNB_TOKEN}@pypi.cnbprod.alpha.qq.com/cnb/pypi-repo/-/packages/simple requests
```

### Build and Push Artifacts

#### twine

```shell
python -m build
twine upload -r cnb-pypi-repo dist/*
```

#### poetry

```shell
poetry build
poetry publish -r cnb-pypi-repo
```

## FAQ

### Q: Why do I get a 409 error when uploading?

A: The package name and version already exist. Set the "Version Overwrite
Strategy" to "Allow overwriting of existing versions", or change the
package version and re-upload.

### Q: Why do I get a 400 error when uploading?

A: The artifact filename does not comply with PyPI specifications. Please check and fix it before re-uploading.

### Q: What PyPI artifact formats does CNB support?

A: Only wheel and sdist formats are supported. Older formats such as egg or exe will be rejected.

## More Usage

For more PyPI usage, please refer to the [PyPI official documentation](https://pypi.org/).
