Skip to main content

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.

📖 Full setup guide — covers uv, pip, conda, CI pipelines, Docker, GitHub Actions, and devcontainers.

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]]
Hatch project (if [tool.hatch] exists) ./pyproject.toml [tool.hatch.envs.default.env-vars]

When run inside a project directory (containing pyproject.toml), the tool offers to configure uv, Poetry, and Hatch settings directly in the project file — including keyring-provider and index URLs with the __token__@ prefix that uv requires for keyring authentication. Hatch configuration is only written when an existing [tool.hatch] section is detected.

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 and uv config files, and optionally update project pyproject.toml for Poetry/Hatch (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"
  3. [tool.hatch.envs.default.env-vars] for PIP_INDEX_URL or UV_DEFAULT_INDEX

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/hatch config files. It does not modify global Python settings or install hooks.

License

MIT

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.11.0.tar.gz (40.1 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.11.0-py3-none-any.whl (22.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for pypi_lockdown-0.11.0.tar.gz
Algorithm Hash digest
SHA256 fd03093c114393555014d8b00f38a55515517c387bc0ced996168edabd2c669b
MD5 8f2c6b6f89500d91cdbd2cdbc8bedb94
BLAKE2b-256 152ce948d1503a6691199b98e9f8ed09089543cc9843b87f742fa44acaa5a9aa

See more details on using hashes here.

Provenance

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

File metadata

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

File hashes

Hashes for pypi_lockdown-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f4e713f9f051e7974d3e0793bc407855ff522f4e0c85edaa7276be634d45d538
MD5 ef248b710f619421651e7a9cbd53470d
BLAKE2b-256 b7daeaf9e3492ec022b7048523bf89c6964bbd410a1d7f7d30b65e21971d5bab

See more details on using hashes here.

Provenance

The following attestation bundles were made for pypi_lockdown-0.11.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 Sentry Error logging StatusPage Status page