pytail 0.1.0__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -0,0 +1,146 @@
1
+ Metadata-Version: 2.4
2
+ Name: pytail
3
+ Version: 0.1.0
4
+ Classifier: Development Status :: 3 - Alpha
5
+ Classifier: Environment :: Console
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: Programming Language :: Rust
8
+ Classifier: Topic :: Software Development :: Build Tools
9
+ Classifier: Topic :: System :: Archiving :: Mirroring
10
+ Summary: Incremental PyPI Simple API caching mirror
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
13
+
14
+ # PyTail
15
+
16
+ `pytail` is a minimal incremental PyPI caching mirror.
17
+
18
+ It is no longer a `devpi` clone. The new server only does four things:
19
+
20
+ - expose a valid Python Simple Repository API root at `/simple/`
21
+ - lazily fetch and cache `/simple/<project>/` from an upstream index
22
+ - rewrite file links to a devpi-style `root/pypi/+f/...` path
23
+ - serve cached project pages and cached files on later requests
24
+
25
+ ## Plan
26
+
27
+ 1. Implement the smallest Simple API surface that `pip` and `uv` actually need:
28
+ root index, project index, normalized names, file links, and content negotiation
29
+ for HTML vs JSON responses.
30
+ 2. Keep the cache incremental:
31
+ do not mirror the full upstream project list, only remember projects that have
32
+ already been requested.
33
+ 3. Use conditional project refresh:
34
+ cache upstream project pages, preserve `ETag`, and refresh a project after a TTL
35
+ with `If-None-Match`.
36
+ 4. Keep package files immutable:
37
+ once a file URL is requested, cache it under `+files/` and serve it from a
38
+ stable devpi-style file route on later requests.
39
+ 5. Store the index in SQLite:
40
+ project pages, file metadata, and known-project state live in SQLite, while
41
+ package bytes live on disk.
42
+ 6. Handle concurrent requests safely inside one process:
43
+ per-project and per-file locks avoid duplicate upstream fetches and duplicate
44
+ downloads.
45
+ 7. Explicitly drop old `devpi` goals:
46
+ no users, no ACLs, no upload API, no index inheritance, no replication, no
47
+ snapshot format, no mirror whitelist, no web UI.
48
+
49
+ ## Spec Coverage
50
+
51
+ The implementation is intentionally narrow:
52
+
53
+ - PEP 503 HTML Simple API for `/simple/` and `/simple/<project>/`
54
+ - PEP 691 JSON Simple API responses when `Accept` asks for
55
+ `application/vnd.pypi.simple.v1+json`
56
+ - preservation of `requires-python`, `yanked`, `gpg-sig`,
57
+ `dist-info-metadata`, and `core-metadata` markers when they are present on the
58
+ upstream project page
59
+ - lazy local root index containing only already-cached projects
60
+
61
+ The implementation does not currently fetch or synthesize a full global upstream
62
+ project list. That is deliberate: the root index is only a local catalogue of
63
+ known projects, while project pages are fetched on demand.
64
+
65
+ ## Why This Is Enough
66
+
67
+ Package resolution for `pip` and `uv` depends primarily on per-project Simple API
68
+ pages. A full pre-fetched mirror root is not required for normal dependency
69
+ resolution as long as:
70
+
71
+ - `/simple/<normalized-project>/` is available and correct
72
+ - file links are reachable
73
+ - project metadata such as hashes and `requires-python` are preserved
74
+
75
+ ## Run
76
+
77
+ ```sh
78
+ cargo run -- \
79
+ --bind 127.0.0.1:3141 \
80
+ --upstream-base-url https://pypi.org \
81
+ --cache-dir .cache/pytail
82
+ ```
83
+
84
+ Then point tools at it:
85
+
86
+ ```sh
87
+ uv pip install --index-url http://127.0.0.1:3141/simple/ requests
88
+ pip install --index-url http://127.0.0.1:3141/simple/ requests
89
+ ```
90
+
91
+ ## Configuration
92
+
93
+ - `--bind`: listen address, default `127.0.0.1:3141`
94
+ - `--upstream-base-url`: upstream index origin, default `https://pypi.org`
95
+ - `--cache-dir`: local cache directory, default `.cache/pytail`
96
+ - `--project-cache-ttl-secs`: refresh age for cached project pages, default `900`
97
+ - `--request-timeout-secs`: upstream HTTP timeout, default `15`
98
+
99
+ ## Package
100
+
101
+ Build a Python wheel with `maturin`:
102
+
103
+ ```sh
104
+ maturin build --release
105
+ ```
106
+
107
+ Publish to PyPI:
108
+
109
+ ```sh
110
+ maturin publish --release
111
+ ```
112
+
113
+ The wheel installs the `pytail` command as a native Rust binary.
114
+
115
+ ## Cache Layout
116
+
117
+ ```text
118
+ <cache-dir>/
119
+ index.sqlite3
120
+ +files/
121
+ root/
122
+ pypi/
123
+ +f/
124
+ f0a/
125
+ f3fc39e7459b0/
126
+ gradio_client-1.0.2-py3-none-any.whl
127
+ _url/
128
+ <url-digest>/
129
+ <filename>
130
+ ```
131
+
132
+ - SQLite stores project cache entries, parsed file rows, upstream `ETag`, and
133
+ known project names
134
+ - `+files/root/pypi/+f/<first-3-sha256>/<next-13-sha256>/<filename>` stores
135
+ hashed files in the same shape as devpi's filesystem layout
136
+ - `+files/root/pypi/+f/_url/<url-digest>/<filename>` is used only when an
137
+ upstream file link does not provide a usable `sha256` hash
138
+
139
+ ## Non-Goals
140
+
141
+ - full PyPI mirroring
142
+ - authentication or private indexes
143
+ - package upload
144
+ - merge of local and upstream package sources
145
+ - replica mode or background synchronization
146
+
@@ -0,0 +1,5 @@
1
+ pytail-0.1.0.data/scripts/pytail.exe,sha256=_4DQie062xMUxCYPQf0uQ1YSFKlBnzvBi6QCz5i0IdY,3971072
2
+ pytail-0.1.0.dist-info/METADATA,sha256=3qmRQPfVGlV1nwvjmoPzCYKF_1mZeRJlRDJhOJSp7GM,4825
3
+ pytail-0.1.0.dist-info/WHEEL,sha256=fxUURV-tpz4EGoGaAcyzIZ0CMCngNhGnetS-bU4AaSg,94
4
+ pytail-0.1.0.dist-info/sboms/pytail.cyclonedx.json,sha256=IoHbmC6ApW8uhD0VNXhd4eGmIWk0sf5BeBUTCwD4ZVM,230304
5
+ pytail-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.13.3)
3
+ Root-Is-Purelib: false
4
+ Tag: py3-none-win_amd64