Перейти к содержанию

Работа с PyPI

Proxy-репозиторий

curl -X POST https://save.example.com/api/v1/repos \
  -H "Content-Type: application/json" \
  -u "<username>:<password>" \
  -d '{
    "project": "backend",
    "name": "pypi-proxy",
    "format": "pypi",
    "repository_type": "proxy",
    "remote_url": "https://pypi.org/",
    "cache_ttl": 3600
  }'

Hosted-репозиторий

curl -X POST https://save.example.com/api/v1/repos \
  -H "Content-Type: application/json" \
  -u "<username>:<password>" \
  -d '{
    "project": "backend",
    "name": "pypi-hosted",
    "format": "pypi",
    "repository_type": "hosted"
  }'

После создания репозиторий доступен по URL https://save.example.com/pypi/<project>/<repository>/. Simple-индекс — по /simple/, загрузка пакета (twine-совместимый POST) — на корень репозитория.

Настройка клиента

pip

# Разовая установка через флаг --index-url
pip install --index-url https://save.example.com/pypi/<project>/pypi-proxy/simple/ <package>

# Постоянная конфигурация через pip.conf
cat > ~/.config/pip/pip.conf << EOF
[global]
index-url = https://USER:PASS@save.example.com/pypi/<project>/pypi-proxy/simple/
trusted-host = save.example.com
EOF

Расположение pip.conf

  • Linux/macOS: ~/.config/pip/pip.conf или ~/.pip/pip.conf
  • Windows: %APPDATA%\pip\pip.ini
  • В virtualenv: $VIRTUAL_ENV/pip.conf

Robot-аккаунты в CI

Для CI/CD используйте robot-аккаунт: username = sa$<robot-name>, password = <api-key>. Конфиг pip.conf не меняется — отличается только значение username. Подробнее — в общем разделе Аутентификация.

poetry

В pyproject.toml:

[[tool.poetry.source]]
name = "codescoring"
url = "https://save.example.com/pypi/<project>/pypi-proxy/simple/"
priority = "primary"

Credentials передаются через poetry config:

poetry config http-basic.codescoring <username> <password>

pipenv

В Pipfile:

[[source]]
url = "https://USER:PASS@save.example.com/pypi/<project>/pypi-proxy/simple/"
verify_ssl = true
name = "codescoring"

uv

uv pip install --index-url https://save.example.com/pypi/<project>/pypi-proxy/simple/ <package>

Или в pyproject.toml:

[[tool.uv.index]]
name = "codescoring"
url = "https://save.example.com/pypi/<project>/pypi-proxy/simple/"
default = true

Публикация (twine, hosted)

Загрузка пакетов в hosted-репозиторий — стандартным twine upload. URL-адрес публикации — корень репозитория (без /simple/).

# ~/.pypirc
[distutils]
index-servers = codescoring

[codescoring]
repository = https://save.example.com/pypi/<project>/pypi-hosted/
username = <username>
password = <password>
python -m build               # сгенерировать .whl и sdist в dist/
twine upload -r codescoring dist/*

Миграция URL репозитория

Сценарий использования: миграция репозитория PyPI с Nexus / Artifactory на CodeScoring.Save.

Источник URL в pip.conf до миграции URL в pip.conf после миграции
Nexus https://nexus.host.ru/repository/pypi-proxy/simple https://save.example.com/pypi/<project>/pypi-proxy/simple/
Artifactory https://jfrog.host.ru/artifactory/api/pypi/pypi-remote/simple https://save.example.com/pypi/<project>/pypi-proxy/simple/
Официальный репозиторий https://pypi.org/simple https://save.example.com/pypi/<project>/pypi-proxy/simple/

Параметры аутентификации (имя пользователя / пароль) и формат pip.conf сохраняются без изменений.

Устранение неполадок

Проверка простого индекса

curl -u "<username>:<password>" \
  https://save.example.com/pypi/<project>/pypi-proxy/simple/<package>/

Ответ — HTML-страница со списком ссылок на файлы пакета. Если страница пустая или возвращается 404 — пакет не закэширован и upstream его не вернул.

Состояние сервиса

curl https://save.example.com/health

Аудит по репозиторию

curl -u "<username>:<password>" \
  "https://save.example.com/api/v1/admin/audit?resource_type=repository&q=pypi-proxy&limit=50"
Страница была полезна?