Skip to main content

Bootstrap Python environments to use internal PyPI feeds

Project description

pypi-lockdown

Bootstrap a Python environment so that all packages are pulled from an internal, authenticated PyPI feed. Install this package first, then every subsequent pip install / uv add will use the configured feed — with artifacts-keyring handling credentials transparently.

Quick start

# 1. Create & activate a fresh environment
python -m venv .venv && source .venv/bin/activate   # venv (Linux / macOS)
python -m venv .venv && .venv\Scripts\activate       # venv (Windows)
conda create -n myenv python && conda activate myenv # conda

# 2. Install pypi-lockdown from the public feed
pip install pypi-lockdown \
    --index-url https://pkgs.dev.azure.com/ORG/PROJECT/_packaging/PUBLIC_FEED/pypi/simple/

# 3. Lock down the environment to use the authenticated feed
python -m pypi_lockdown \
    https://pkgs.dev.azure.com/ORG/PROJECT/_packaging/PRIVATE_FEED/pypi/simple/

# 4. Done — all future installs use the authenticated feed
pip install requests   # resolved from PRIVATE_FEED, authenticated via artifacts-keyring

Standalone .pyz (build locally)

For environments where you can't pip install first, you can build a standalone .pyz zipapp that bundles all dependencies:

pip install tox shiv
tox -e standalone -- linux-x86_64    # or macos-universal2, win-amd64
python dist/pypi-lockdown-linux-x86_64.pyz \
    https://pkgs.dev.azure.com/ORG/PROJECT/_packaging/PRIVATE_FEED/pypi/simple/

This writes pip/uv config files and installs artifacts-keyring-nofuss plus all its dependencies into the active environment — no network access to any package feed required.

.pyz files are platform-specific (Linux, macOS, Windows) because cryptography contains native extensions.

What it does

pypi-lockdown writes configuration files that redirect the default package index:

Tool Scope File written
pip environment (default) $VIRTUAL_ENV/pip.conf or $CONDA_PREFIX/pip.conf
pip user (fallback) ~/.config/pip/pip.conf (platform-aware)
uv user ~/.config/uv/uv.toml (platform-aware)
uv project (prompted) ./pyproject.toml [tool.uv] section
Poetry project (prompted) ./pyproject.toml [[tool.poetry.source]]

When run inside a project directory (containing pyproject.toml), the tool offers to configure uv and Poetry settings directly in the project file — including keyring-provider and index URLs with the __token__@ prefix that uv requires for keyring authentication.

Works with venv, conda, and any other environment manager that sets VIRTUAL_ENV or CONDA_PREFIX.

Platform-specific config paths

Tool Linux macOS Windows
pip ~/.config/pip/pip.conf ~/Library/Application Support/pip/pip.conf %APPDATA%\pip\pip.ini
uv ~/.config/uv/uv.toml ~/Library/Application Support/uv/uv.toml %APPDATA%\uv\uv.toml

Manual Poetry setup

If you run pypi-lockdown outside a project directory (no pyproject.toml), or decline the prompt, you can configure Poetry manually:

poetry source add --priority=primary internal https://pkgs.dev.azure.com/ORG/PROJECT/_packaging/FEED/pypi/simple/
poetry source add --priority=explicit PyPI

CLI reference

python -m pypi_lockdown [configure] INDEX_URL [--user]
python -m pypi_lockdown scaffold NAME INDEX_URL
Command Effect
configure Write pip/uv config files (default when omitted).
scaffold Generate a wrapper package that hardcodes a private feed URL.
Flag Effect
(none) Target the active environment; prompt to update pyproject.toml if present.
--user Write pip config to user home instead of the active environment.

Creating team-specific wrapper packages

Use scaffold to generate a small package that hardcodes your team's feed URL and depends on pypi-lockdown:

python -m pypi_lockdown scaffold ai4s-pypi-lockdown \
    https://pkgs.dev.azure.com/ai4s/ai4s/_packaging/ai4s-pypi/pypi/simple/

This creates a ready-to-publish package:

ai4s-pypi-lockdown/
├── pyproject.toml
├── tox.ini
└── src/ai4s_pypi_lockdown/
    ├── __init__.py
    └── __main__.py

Users of that wrapper only need:

pip install ai4s-pypi-lockdown --index-url https://pkgs.dev.azure.com/.../PUBLIC_FEED/pypi/simple/
python -m ai4s_pypi_lockdown

Scaffolded packages can also build their own standalone .pyz files:

cd ai4s-pypi-lockdown
tox -e standalone       # builds ai4s-pypi-lockdown-{platform}.pyz

Creating a release

Create a GitHub release — the CI workflow builds a wheel and sdist, attaches them to the release, and publishes to the ADO PyPI feed:

gh release create v1.0.0 --generate-notes

To build a standalone .pyz locally (e.g. for air-gapped environments):

pip install tox shiv
tox -e standalone -- linux-x86_64    # or macos-universal2, win-amd64

Security model

  • HTTPS required: configure rejects non-HTTPS index URLs — HTTP would expose credentials and package content to network observers.
  • Build provenance: Wheel and sdist releases are built in CI with signed build provenance — verify with gh attestation verify <file> --owner microsoft.
  • Standalone .pyz integrity: When building .pyz locally for air-gapped use, the build includes zip-slip protection that validates no archive entry escapes the staging directory.
  • Narrow config scope: pypi-lockdown only writes index-url to pip/uv config files. It does not modify global Python settings or install hooks.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pypi_lockdown-0.9.0.tar.gz (24.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pypi_lockdown-0.9.0-py3-none-any.whl (16.5 kB view details)

Uploaded Python 3

File details

Details for the file pypi_lockdown-0.9.0.tar.gz.

File metadata

  • Download URL: pypi_lockdown-0.9.0.tar.gz
  • Upload date:
  • Size: 24.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypi_lockdown-0.9.0.tar.gz
Algorithm Hash digest
SHA256 33da5712585c284e3755b4c1e6033b10a86cb94f1fc27ae455f40aa83af455a5
MD5 3fef470fa61c3fd9a6b8738bea64df11
BLAKE2b-256 ef5e85e909a712e1b8ec32d1e472b308a501d9c8e3ac2dbd66396ddacb4006d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypi_lockdown-0.9.0.tar.gz:

Publisher: release.yml on microsoft/pypi-lockdown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pypi_lockdown-0.9.0-py3-none-any.whl.

File metadata

  • Download URL: pypi_lockdown-0.9.0-py3-none-any.whl
  • Upload date:
  • Size: 16.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pypi_lockdown-0.9.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9d741f449092df6b8190510c3e27a5bd4f5bf53b5452458b0bf44c8e29534bd4
MD5 07bb3babba7ee60669ae53caa2383de4
BLAKE2b-256 0cb749616e68fb257d055fac1a36d5506fb8ff8a5b1a1a1a18eda068e0b4ef62

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypi_lockdown-0.9.0-py3-none-any.whl:

Publisher: release.yml on microsoft/pypi-lockdown

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page