Skip to main content

Bootstrap Python environments to use internal PyPI feeds

Project description

pypi-lockdown

CI PyPI Python License

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] [--ci] [--verify]
python -m pypi_lockdown verify INDEX_URL
python -m pypi_lockdown scaffold NAME INDEX_URL
Command Effect
configure Write pip/uv config files (default when omitted).
verify Test that the configured feed is reachable and authentication works.
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.
--ci Non-interactive CI mode: skip pyproject.toml modification and poetry instructions.
--verify After configuring, verify the feed is reachable and authentication works.

Auto-detect feed URL

When INDEX_URL is omitted, pypi-lockdown reads the current directory's pyproject.toml and looks for a configured feed:

  1. [[tool.uv.index]] entry with default = true
  2. [[tool.poetry.source]] entry with priority = "primary"

This means after initial setup, team members can simply run:

python -m pypi_lockdown

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.10.0.tar.gz (32.7 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.10.0-py3-none-any.whl (20.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: pypi_lockdown-0.10.0.tar.gz
  • Upload date:
  • Size: 32.7 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.10.0.tar.gz
Algorithm Hash digest
SHA256 39179d2f0e9a985ad861686d66184d0d253fc07fc971236857129ae959fe73d7
MD5 abdf95ba3d96b014674760e0fab262ba
BLAKE2b-256 5ec5a6ef5609e212564cc62b4ba35fd4f56ef527ebd9b945d210a4b1741eaddd

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypi_lockdown-0.10.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.10.0-py3-none-any.whl.

File metadata

  • Download URL: pypi_lockdown-0.10.0-py3-none-any.whl
  • Upload date:
  • Size: 20.6 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.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c5f3c03d87c488ced5d5fcc1cad35b2c230ae3c6af01d11b108e92a1721e6308
MD5 48de06ae3e34b5635dc0b2485c33a9b6
BLAKE2b-256 157e9ed2278dac5d65f3be1fd0278fc74be4a2cc2a1f307719284a42d40a508b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypi_lockdown-0.10.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