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.
.pyzfiles are platform-specific (Linux, macOS, Windows) becausecryptographycontains 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:
[[tool.uv.index]]entry withdefault = true[[tool.poetry.source]]entry withpriority = "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:
configurerejects 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
.pyzintegrity: When building.pyzlocally for air-gapped use, the build includes zip-slip protection that validates no archive entry escapes the staging directory. - Narrow config scope:
pypi-lockdownonly writesindex-urlto pip/uv config files. It does not modify global Python settings or install hooks.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
39179d2f0e9a985ad861686d66184d0d253fc07fc971236857129ae959fe73d7
|
|
| MD5 |
abdf95ba3d96b014674760e0fab262ba
|
|
| BLAKE2b-256 |
5ec5a6ef5609e212564cc62b4ba35fd4f56ef527ebd9b945d210a4b1741eaddd
|
Provenance
The following attestation bundles were made for pypi_lockdown-0.10.0.tar.gz:
Publisher:
release.yml on microsoft/pypi-lockdown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pypi_lockdown-0.10.0.tar.gz -
Subject digest:
39179d2f0e9a985ad861686d66184d0d253fc07fc971236857129ae959fe73d7 - Sigstore transparency entry: 1368340621
- Sigstore integration time:
-
Permalink:
microsoft/pypi-lockdown@81d53dc0c7ee578f32e45bf1f48fac6e34754a5f -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/microsoft
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@81d53dc0c7ee578f32e45bf1f48fac6e34754a5f -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5f3c03d87c488ced5d5fcc1cad35b2c230ae3c6af01d11b108e92a1721e6308
|
|
| MD5 |
48de06ae3e34b5635dc0b2485c33a9b6
|
|
| BLAKE2b-256 |
157e9ed2278dac5d65f3be1fd0278fc74be4a2cc2a1f307719284a42d40a508b
|
Provenance
The following attestation bundles were made for pypi_lockdown-0.10.0-py3-none-any.whl:
Publisher:
release.yml on microsoft/pypi-lockdown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pypi_lockdown-0.10.0-py3-none-any.whl -
Subject digest:
c5f3c03d87c488ced5d5fcc1cad35b2c230ae3c6af01d11b108e92a1721e6308 - Sigstore transparency entry: 1368340627
- Sigstore integration time:
-
Permalink:
microsoft/pypi-lockdown@81d53dc0c7ee578f32e45bf1f48fac6e34754a5f -
Branch / Tag:
refs/tags/v0.10.0 - Owner: https://github.com/microsoft
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@81d53dc0c7ee578f32e45bf1f48fac6e34754a5f -
Trigger Event:
push
-
Statement type: