Skip to main content

Incremental PyPI Simple API caching mirror

Project description

PyTail

CI Release PyPI Python

pytail is a minimal incremental PyPI caching mirror.

It is no longer a devpi clone. The new server only does four things:

  • expose a valid Python Simple Repository API root at /simple/
  • lazily fetch and cache /simple/<project>/ from an upstream index
  • rewrite file links to a devpi-style root/pypi/+f/... path
  • serve cached project pages and cached files on later requests

Plan

  1. Implement the smallest Simple API surface that pip and uv actually need: root index, project index, normalized names, file links, and content negotiation for HTML vs JSON responses.
  2. Keep the cache incremental: do not mirror the full upstream project list, only remember projects that have already been requested.
  3. Use conditional project refresh: cache upstream project pages, preserve ETag, and refresh a project after a TTL with If-None-Match.
  4. Keep package files immutable: once a file URL is requested, cache it under +files/ and serve it from a stable devpi-style file route on later requests.
  5. Store the index in SQLite: project pages, file metadata, and known-project state live in SQLite, while package bytes live on disk.
  6. Handle concurrent requests safely inside one process: per-project and per-file locks avoid duplicate upstream fetches and duplicate downloads.
  7. Explicitly drop old devpi goals: no users, no ACLs, no upload API, no index inheritance, no replication, no snapshot format, no mirror whitelist, no web UI.

Spec Coverage

The implementation is intentionally narrow:

  • PEP 503 HTML Simple API for /simple/ and /simple/<project>/
  • PEP 691 JSON Simple API responses when Accept asks for application/vnd.pypi.simple.v1+json
  • preservation of requires-python, yanked, gpg-sig, dist-info-metadata, and core-metadata markers when they are present on the upstream project page
  • lazy local root index containing only already-cached projects

The implementation does not currently fetch or synthesize a full global upstream project list. That is deliberate: the root index is only a local catalogue of known projects, while project pages are fetched on demand.

Why This Is Enough

Package resolution for pip and uv depends primarily on per-project Simple API pages. A full pre-fetched mirror root is not required for normal dependency resolution as long as:

  • /simple/<normalized-project>/ is available and correct
  • file links are reachable
  • project metadata such as hashes and requires-python are preserved

Run

cargo run -- \
  --bind 127.0.0.1:3141 \
  --upstream-base-url https://pypi.org \
  --cache-dir .cache/pytail

Then point tools at it:

uv pip install --index-url http://127.0.0.1:3141/simple/ requests
pip install --index-url http://127.0.0.1:3141/simple/ requests

PyTorch wheel indexes are also exposed under /pytorch-wheels/, so a command that uses:

pip install torch --index-url https://download.pytorch.org/whl/cu126

can use the local caching endpoint instead:

pip install torch --index-url http://127.0.0.1:3141/pytorch-wheels/cu126

Configuration

  • --bind: listen address, default 127.0.0.1:3141
  • --upstream-base-url: upstream index origin, default https://pypi.org
  • --torch-url: PyTorch wheels upstream root, default https://download.pytorch.org/whl/
  • --cache-dir: local cache directory, default .cache/pytail
  • --project-cache-ttl-secs: refresh age for cached project pages, default 900
  • --request-timeout-secs: upstream HTTP timeout, default 15
  • --verbose: enable debug logging for pytail

Package

Build a Python wheel with maturin:

maturin build --release

Publish to PyPI:

maturin publish --release

The wheel installs the pytail command as a native Rust binary.

Cache Layout

<cache-dir>/
  index.sqlite3
  +files/
    root/
      pypi/
        +f/
          f0a/
            f3fc39e7459b0/
              gradio_client-1.0.2-py3-none-any.whl
          _url/
            <url-digest>/
              <filename>
  • SQLite stores project cache entries, parsed file rows, upstream ETag, and known project names
  • +files/root/pypi/+f/<first-3-sha256>/<next-13-sha256>/<filename> stores hashed files in the same shape as devpi's filesystem layout
  • +files/root/pypi/+f/_url/<url-digest>/<filename> is used only when an upstream file link does not provide a usable sha256 hash

Non-Goals

  • full PyPI mirroring
  • authentication or private indexes
  • package upload
  • merge of local and upstream package sources
  • replica mode or background synchronization

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

pytail-0.1.2.tar.gz (54.7 kB view details)

Uploaded Source

Built Distributions

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

pytail-0.1.2-py3-none-win_amd64.whl (2.3 MB view details)

Uploaded Python 3Windows x86-64

pytail-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.5 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

pytail-0.1.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl (4.5 MB view details)

Uploaded Python 3macOS 10.12+ universal2 (ARM64, x86-64)macOS 10.12+ x86-64macOS 11.0+ ARM64

File details

Details for the file pytail-0.1.2.tar.gz.

File metadata

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

File hashes

Hashes for pytail-0.1.2.tar.gz
Algorithm Hash digest
SHA256 6b518e1873aec7f4cace4088dc7eb9ee5887976ddecc3284cb5a9de5cb28563c
MD5 33bf028d219928ba53ee18f6c3734d27
BLAKE2b-256 1b355bc9a23f4000230511d198d7c889e070009e91a7e5dc87e6c7d993dd04b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytail-0.1.2.tar.gz:

Publisher: release.yml on AndPuQing/PyTail

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

File details

Details for the file pytail-0.1.2-py3-none-win_amd64.whl.

File metadata

  • Download URL: pytail-0.1.2-py3-none-win_amd64.whl
  • Upload date:
  • Size: 2.3 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pytail-0.1.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 856dace27cc4c6d47dabdb5f6c16ba21a3cb031d9c9f945cd68bcb23c249ac90
MD5 063d4d36969ab61dd6d1ca69872cd99b
BLAKE2b-256 a04cdee2a8ee5554c4aa5ea42cacbb78542d4005cf7808f90cc4f753ededd1d1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytail-0.1.2-py3-none-win_amd64.whl:

Publisher: release.yml on AndPuQing/PyTail

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

File details

Details for the file pytail-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pytail-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 fc64b9da25ed58a868b437b50a96a5a343a2e01cd6bf103a6671aa219caee076
MD5 81fc132efc928d33cc111d6a2d6739b6
BLAKE2b-256 4127f92b6fce4c2dc1f277ce771eb285254b7472fa13317fa24e96427630b2cc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytail-0.1.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on AndPuQing/PyTail

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

File details

Details for the file pytail-0.1.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl.

File metadata

File hashes

Hashes for pytail-0.1.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Algorithm Hash digest
SHA256 d2565415c6353b02575cd7d5e52b6ffc30dfcdbe369c4ba914e6af0bf531d8a0
MD5 6992f63b3f492a6c373d1988ca972594
BLAKE2b-256 4b53b6caa0d0f3fd05f7cbff6e3c55809a218b727c61ad96f732940b439a487a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pytail-0.1.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl:

Publisher: release.yml on AndPuQing/PyTail

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