withcache 0.5.1__tar.gz → 0.5.2__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: withcache
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: Operator-curated, URL-keyed artifact cache for a small lab (CUDA/ROCm/DOCA/firmware)
5
5
  Project-URL: Homepage, https://github.com/safl/withcache
6
6
  Author-email: "Simon A. F. Lund" <safl@safl.dk>
@@ -2,7 +2,7 @@
2
2
  .name = .withcache_shim,
3
3
  // Zig requires a literal here; keep it in lockstep with the project's
4
4
  // single source (src/withcache/__init__.py) via `make bump` / `make version-check`.
5
- .version = "0.5.1",
5
+ .version = "0.5.2",
6
6
  .fingerprint = 0xd7d96c5ed212ccaa,
7
7
  .minimum_zig_version = "0.16.0",
8
8
  .paths = .{
@@ -12,6 +12,6 @@ All modules are stdlib-only and self-contained.
12
12
 
13
13
  from .client import blob_url, cache_base, is_cached, serve_url
14
14
 
15
- __version__ = "0.5.1"
15
+ __version__ = "0.5.2"
16
16
 
17
17
  __all__ = ["__version__", "blob_url", "cache_base", "is_cached", "serve_url"]
@@ -982,7 +982,7 @@ class Handler(http.server.BaseHTTPRequestHandler):
982
982
  <body><main class="container">
983
983
  <nav>
984
984
  <ul><li>
985
- <strong>withcache</strong> &nbsp;<small>cache-host</small>
985
+ <strong>withcache</strong>
986
986
  &nbsp;<small class="mono">v{html.escape(__version__)}</small>
987
987
  </li></ul>
988
988
  <ul>
@@ -996,7 +996,11 @@ class Handler(http.server.BaseHTTPRequestHandler):
996
996
  hx-indicator="#spin" hx-on::after-request="this.reset()">
997
997
  <fieldset role="group">
998
998
  <input type="url" name="url" placeholder="https://origin/path/artifact.tar.gz" required>
999
- <button type="submit">Fetch &amp; store</button>
999
+ <!-- white-space: nowrap so the label "Fetch & store" stays on
1000
+ one line; default flex-grow inside fieldset[role=group]
1001
+ shrinks the button to content width, which on a narrow
1002
+ viewport wrapped the ampersand to a second line. -->
1003
+ <button type="submit" style="white-space: nowrap;">Fetch &amp; store</button>
1000
1004
  </fieldset>
1001
1005
  </form>
1002
1006
 
@@ -1136,10 +1140,26 @@ class Handler(http.server.BaseHTTPRequestHandler):
1136
1140
  or '<tr><td colspan="4"><em>No misses recorded.</em></td></tr>'
1137
1141
  )
1138
1142
 
1143
+ # Build the per-row /b/ serve URL once; the cell wraps the
1144
+ # origin string in a link that GETs the cached bytes when
1145
+ # the operator clicks. Same path-encoded form the shim
1146
+ # generates so curl / wget / a browser save all end up
1147
+ # writing the correct output filename.
1148
+ def _serve_url_for(row: sqlite3.Row) -> str:
1149
+ origin = row["url"]
1150
+ token = base64.urlsafe_b64encode(origin.encode("utf-8")).decode("ascii").rstrip("=")
1151
+ # last path segment of the origin, fallback "download" so a
1152
+ # URL ending in / still serves with a usable filename.
1153
+ name = urllib.parse.urlsplit(origin).path.rsplit("/", 1)[-1] or "download"
1154
+ return f"/b/{token}/{urllib.parse.quote(name)}"
1155
+
1139
1156
  blob_rows = (
1140
1157
  "".join(
1141
1158
  f"""<tr>
1142
- <td class="url">{html.escape(b["url"])}</td>
1159
+ <td class="url">
1160
+ <a href="{_serve_url_for(b)}"
1161
+ title="Download the cached object">{html.escape(b["url"])}</a>
1162
+ </td>
1143
1163
  <td>{human_size(b["size"])}</td>
1144
1164
  <td class="num">{b["hits"]}</td>
1145
1165
  <td class="num">{b["misses"]}</td>
@@ -1167,12 +1187,22 @@ class Handler(http.server.BaseHTTPRequestHandler):
1167
1187
  <p><small>{nblobs} cached ({used}){full} &middot; {nmisses} pending miss(es)</small></p>
1168
1188
  {tab_style}
1169
1189
  <nav class="tabs"><ul>
1190
+ <li><a href="#tab-cached">Cached ({nblobs})</a></li>
1170
1191
  <li><a href="#tab-streams">Streams ({nstreams})</a></li>
1171
1192
  <li><a href="#tab-downloads">Downloads ({njobs})</a></li>
1172
1193
  <li><a href="#tab-misses">Misses ({nmisses})</a></li>
1173
- <li><a href="#tab-cached">Cached ({nblobs})</a></li>
1174
1194
  </ul></nav>
1175
1195
 
1196
+ <section id="tab-cached" class="tab">
1197
+ <figure><table class="striped">
1198
+ <thead><tr>
1199
+ <th>URL</th><th>Size</th><th class="num">Hits</th><th class="num">Misses</th>
1200
+ <th>SHA-256</th><th>Fetched</th><th>Action</th>
1201
+ </tr></thead>
1202
+ <tbody>{blob_rows}</tbody>
1203
+ </table></figure>
1204
+ </section>
1205
+
1176
1206
  <section id="tab-streams" class="tab">
1177
1207
  <figure><table class="striped">
1178
1208
  <thead><tr>
@@ -1203,16 +1233,6 @@ class Handler(http.server.BaseHTTPRequestHandler):
1203
1233
  </tr></thead>
1204
1234
  <tbody>{miss_rows}</tbody>
1205
1235
  </table></figure>
1206
- </section>
1207
-
1208
- <section id="tab-cached" class="tab">
1209
- <figure><table class="striped">
1210
- <thead><tr>
1211
- <th>URL</th><th>Size</th><th class="num">Hits</th><th class="num">Misses</th>
1212
- <th>SHA-256</th><th>Fetched</th><th>Action</th>
1213
- </tr></thead>
1214
- <tbody>{blob_rows}</tbody>
1215
- </table></figure>
1216
1236
  </section>"""
1217
1237
 
1218
1238
  def _stream_progress_cell(self, s: Stream) -> str:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes