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.
📖 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.
.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]] |
| 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:
[[tool.uv.index]]entry withdefault = true[[tool.poetry.source]]entry withpriority = "primary"[tool.hatch.envs.default.env-vars]forPIP_INDEX_URLorUV_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:
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/hatch config files. It does not modify global Python settings or install hooks.
License
MIT
Metadata
Release files for pypi-lockdown 0.11.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pypi_lockdown-0.11.0.tar.gz | 40.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pypi_lockdown-0.11.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 62.8 kB
Release files / pypi_lockdown-0.11.0.tar.gz
| Download URL | pypi_lockdown-0.11.0.tar.gz |
|---|---|
| Size | 40.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fd03093c114393555014d8b00f38a55515517c387bc0ced996168edabd2c669b
|
|
BLAKE2b-256 checksum How to use checksums |
152ce948d1503a6691199b98e9f8ed09089543cc9843b87f742fa44acaa5a9aa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 16, 2026.
Transparency logRelease files / pypi_lockdown-0.11.0-py3-none-any.whl
| Download URL | pypi_lockdown-0.11.0-py3-none-any.whl |
|---|---|
| Size | 22.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f4e713f9f051e7974d3e0793bc407855ff522f4e0c85edaa7276be634d45d538
|
|
BLAKE2b-256 checksum How to use checksums |
b7daeaf9e3492ec022b7048523bf89c6964bbd410a1d7f7d30b65e21971d5bab
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 16, 2026.
Transparency log