Back in 2018 I wrote about adding support for PyPI mirrors to pipenv. Since then, I’ve switched to using Poetry for most of my Python projects.
In 2019, I opened python-poetry/poetry#1632 to propose PyPI mirror support in Poetry. The issue languished for a bit, and several attempts at addressing it were either abandoned or rejected. There were a couple of notable complications:
- Since Poetry does not simply wrap
pip, adding support for PyPI mirrors is more involved than just setting pip’s indexes.
- In python-poetry/poetry#1632, users expressed differing expectations for the feature. Some desired a mechanism to replace arbitrary repositories at the global scope, whereas others were strictly interested in replacing the use of pypi.org.
- Poetry’s maintainers wished to avoid introducing leaky abstractions.
Concerned about the suitability of a one-size-fits-all approach to mirror support, several participants in python-poetry/poetry#4944 discussed providing support through plugins, which were introduced in Poetry 1.2. In mid-October I released poetry-plugin-pypi-mirror, which focuses specifically on supporting mirrors of pypi.org.
To use poetry-plugin-pypi-mirror, it must first be installed —
poetry self add poetry-plugin-pypi-mirror should be sufficient for most users. Advanced plugin installation instructions are provided in Poetry’s documentation.
To use a mirror, environment variable
POETRY_PYPI_MIRROR_URL should be set to the appropriate URL.
POETRY_PYPI_MIRROR_URL=https://example.org/repository/pypi-proxy/simple/ poetry add pendulum
export POETRY_PYPI_MIRROR_URL=https://example.org/repository/pypi-proxy/simple/ poetry add cleo # uses mirror specified in first line poetry lock # also uses mirror specified in first line
POETRY_PYPI_MIRROR_URL can be set for the user, rather than before each use of
poetry-plugin-pypi-mirror works by replacing instances of Poetry’s internal PyPIRepository with a modified LegacyRepository configured to use the specified mirror. It preserves repository ordering, and uses the modified LegacyRepository to prevent source information from being written to poetry.lock.
The plugin cannot simply replace the URL in Poetry’s internal PyPIRepository with the URL of a mirror because pypi.org provides a non-standard API that is consumed by Poetry’s PyPIRepository. When interacting with pypi.org Poetry uses Warehouse’s non-standard JSON API to retrieve distribution metadata, and the PEP 691 JSON-based Simple API for all other purposes. When interacting with other repositories, the older PEP 503 Simple Repository API is used. The Poetry team intends to drop support for the Warehouse JSON API once PEP 658 (Serve Distribution Metadata in the Simple Repository API) is more widely adopted. This will likely simplify the implementation of the plugin.