calkit-python 0.37.1__py3-none-any.whl → 0.37.2__py3-none-any.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.
Files changed (22) hide show
  1. calkit/dvc/zip.py +73 -9
  2. calkit/tests/dvc/test_zip.py +8 -1
  3. {calkit_python-0.37.1.dist-info → calkit_python-0.37.2.dist-info}/METADATA +1 -1
  4. {calkit_python-0.37.1.dist-info → calkit_python-0.37.2.dist-info}/RECORD +22 -22
  5. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/etc/jupyter/jupyter_server_config.d/calkit.json +0 -0
  6. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/install.json +0 -0
  7. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/package.json +0 -0
  8. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig +0 -0
  9. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json +0 -0
  10. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js +0 -0
  11. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js +0 -0
  12. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js +0 -0
  13. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/909.651be47ca47390b78a92.js +0 -0
  14. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js +0 -0
  15. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
  16. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png +0 -0
  17. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/remoteEntry.c091821b3d7f2d287a67.js +0 -0
  18. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/style.js +0 -0
  19. {calkit_python-0.37.1.data → calkit_python-0.37.2.data}/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json +0 -0
  20. {calkit_python-0.37.1.dist-info → calkit_python-0.37.2.dist-info}/WHEEL +0 -0
  21. {calkit_python-0.37.1.dist-info → calkit_python-0.37.2.dist-info}/entry_points.txt +0 -0
  22. {calkit_python-0.37.1.dist-info → calkit_python-0.37.2.dist-info}/licenses/LICENSE +0 -0
calkit/dvc/zip.py CHANGED
@@ -25,6 +25,7 @@ from tqdm import tqdm
25
25
  import calkit
26
26
  import calkit.git
27
27
  from calkit.core import DVC_SIZE_THRESH_BYTES
28
+ from calkit.dvc.core import run_dvc_command
28
29
 
29
30
  LOCAL_DIR = ".calkit/local"
30
31
  ZIPS_DIR = ".calkit/zip"
@@ -38,6 +39,12 @@ ZIP_CANDIDATE_AVG_FILE_SIZE_BYTES = 10_000_000 # 10 MB
38
39
  # Minimum number of files a directory must contain to be a zip candidate;
39
40
  # a single large file is better tracked directly by DVC
40
41
  ZIP_CANDIDATE_MIN_FILE_COUNT = 10
42
+ # Favor speed for dvc-zip by default; users can tune 0..9 via env var
43
+ # CALKIT_DVC_ZIP_COMPRESS_LEVEL
44
+ ZIP_COMPRESS_LEVEL = 1
45
+ # Use Python zipfile by default; set CALKIT_DVC_ZIP_USE_SYSTEM=1 to try
46
+ # the system zip/unzip tools instead (may be faster for very large files)
47
+ ZIP_USE_SYSTEM_CLI = False
41
48
 
42
49
 
43
50
  def _check_local_dir() -> Path:
@@ -285,16 +292,59 @@ def get_zip_path(workspace_path: str) -> str:
285
292
  raise ValueError(f"No zip path defined for {workspace_path}")
286
293
 
287
294
 
295
+ def _get_zip_compress_level() -> int:
296
+ raw = os.getenv("CALKIT_DVC_ZIP_COMPRESS_LEVEL", str(ZIP_COMPRESS_LEVEL))
297
+ try:
298
+ level = int(raw)
299
+ except ValueError:
300
+ typer.echo(
301
+ "Invalid CALKIT_DVC_ZIP_COMPRESS_LEVEL value; "
302
+ f"using default {ZIP_COMPRESS_LEVEL}.",
303
+ err=True,
304
+ )
305
+ return ZIP_COMPRESS_LEVEL
306
+ return min(max(level, 0), 9)
307
+
308
+
309
+ def _should_use_system_zip_cli() -> bool:
310
+ raw = os.getenv("CALKIT_DVC_ZIP_USE_SYSTEM")
311
+ if raw is None:
312
+ return ZIP_USE_SYSTEM_CLI
313
+ return raw.strip().lower() not in {"0", "false", "no", "off"}
314
+
315
+
316
+ def _iter_files(path: str):
317
+ for foldername, _, filenames in os.walk(path):
318
+ for filename in filenames:
319
+ yield os.path.join(foldername, filename)
320
+
321
+
288
322
  def zip_(workspace_path: str, zip_path: str):
289
323
  """Zip a path."""
324
+ zip_path = os.path.abspath(zip_path)
290
325
  output_dir = os.path.dirname(zip_path)
291
326
  os.makedirs(output_dir, exist_ok=True)
292
- all_files = [
293
- os.path.join(foldername, filename)
294
- for foldername, _, filenames in os.walk(workspace_path)
295
- for filename in filenames
296
- ]
297
- with ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zip_file:
327
+ compress_level = _get_zip_compress_level()
328
+ if _should_use_system_zip_cli() and shutil.which("zip"):
329
+ try:
330
+ subprocess.run(
331
+ ["zip", "-q", f"-{compress_level}", "-r", zip_path, "."],
332
+ check=True,
333
+ cwd=workspace_path,
334
+ )
335
+ return
336
+ except Exception:
337
+ typer.echo(
338
+ "System zip failed; falling back to Python zipfile.",
339
+ err=True,
340
+ )
341
+ all_files = list(_iter_files(workspace_path))
342
+ with ZipFile(
343
+ zip_path,
344
+ "w",
345
+ compression=zipfile.ZIP_DEFLATED,
346
+ compresslevel=compress_level,
347
+ ) as zip_file:
298
348
  for file_path in tqdm(all_files, desc="Zipping", unit="file"):
299
349
  zip_file.write(
300
350
  file_path, os.path.relpath(file_path, workspace_path)
@@ -303,11 +353,25 @@ def zip_(workspace_path: str, zip_path: str):
303
353
 
304
354
  def unzip(workspace_path: str, zip_path: str):
305
355
  """Unzip from zip to workspace."""
356
+ zip_path = os.path.abspath(zip_path)
306
357
  input_dir = os.path.dirname(workspace_path)
307
358
  if input_dir:
308
359
  os.makedirs(input_dir, exist_ok=True)
360
+ if _should_use_system_zip_cli() and shutil.which("unzip"):
361
+ try:
362
+ os.makedirs(workspace_path, exist_ok=True)
363
+ subprocess.run(
364
+ ["unzip", "-oq", zip_path, "-d", workspace_path],
365
+ check=True,
366
+ )
367
+ return
368
+ except Exception:
369
+ typer.echo(
370
+ "System unzip failed; falling back to Python zipfile.",
371
+ err=True,
372
+ )
309
373
  with ZipFile(zip_path, "r") as zip_file:
310
- members = zip_file.namelist()
374
+ members = zip_file.infolist()
311
375
  for member in tqdm(members, desc="Unzipping", unit="file"):
312
376
  zip_file.extract(member, workspace_path)
313
377
 
@@ -407,7 +471,7 @@ def sync_one(
407
471
  if zip_deleted and direction == "to-zip":
408
472
  typer.echo(f"Rezipping '{workspace_path}' (zip was deleted)")
409
473
  zip_(workspace_path=workspace_path, zip_path=zip_path)
410
- subprocess.run(["dvc", "add", zip_path], check=True)
474
+ run_dvc_command(["add", zip_path])
411
475
  zip_hash = get_hash(zip_path)
412
476
  # Workspace was deleted but zip exists and direction is to-workspace:
413
477
  # restore workspace
@@ -429,7 +493,7 @@ def sync_one(
429
493
  if workspace_changed and (direction in ["to-zip", "both"]):
430
494
  typer.echo(f"Zipping '{workspace_path}' (workspace has changed)")
431
495
  zip_(workspace_path=workspace_path, zip_path=zip_path)
432
- subprocess.run(["dvc", "add", zip_path], check=True)
496
+ run_dvc_command(["add", zip_path])
433
497
  zip_hash = get_hash(zip_path)
434
498
  # If we unzip, we need to update the hash
435
499
  if zip_changed and (direction in ["to-workspace", "both"]):
@@ -200,7 +200,14 @@ def test_get_sync_status(tmp_dir):
200
200
 
201
201
 
202
202
  def test_sync_one(tmp_dir, monkeypatch):
203
- monkeypatch.setattr("calkit.dvc.zip.subprocess.run", lambda *_, **__: None)
203
+ real_run = calkit.dvc.zip.subprocess.run
204
+
205
+ def _run(cmd, *args, **kwargs):
206
+ if cmd and cmd[0] == "dvc":
207
+ return None
208
+ return real_run(cmd, *args, **kwargs)
209
+
210
+ monkeypatch.setattr("calkit.dvc.zip.subprocess.run", _run)
204
211
  # to-zip: zips input and writes sync record
205
212
  src = tmp_dir / "src"
206
213
  src.mkdir()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calkit-python
3
- Version: 0.37.1
3
+ Version: 0.37.2
4
4
  Summary: Reproducibility simplified.
5
5
  Project-URL: Homepage, https://calkit.org
6
6
  Project-URL: Issues, https://github.com/calkit/calkit/issues
@@ -47,7 +47,7 @@ calkit/cli/main/core.py,sha256=Ds9bhOww5p6vB85zKy_KvS_sS2g9fTyF_03KJH4Fb0o,92127
47
47
  calkit/cli/main/xr.py,sha256=-hiIS6Xr3RiVAFGgH19yqvyzbcAwnEyaVBUH-qDehxY,25575
48
48
  calkit/dvc/__init__.py,sha256=g_K9o7zVXS0d_6in8UqhPpkPfxXAjGGmjLVLl7k6Nd0,34
49
49
  calkit/dvc/core.py,sha256=relc7smVSQLVxpWjt_aCCbHZiWF8ZFD2nKckOjk96eE,18274
50
- calkit/dvc/zip.py,sha256=lt7kITGfeBs1Bw086V-GywTLgRtrHGXdp1krbU6J3D4,16514
50
+ calkit/dvc/zip.py,sha256=Rcf7oEbkuazGsPcvKVhdiRrqNMqRIIp9rmnOPidEhKU,18572
51
51
  calkit/jupyterlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
52
  calkit/jupyterlab/routes.py,sha256=vipSlBXVHIzdnZryNhZBpeTWnqcw2wGiOJYwO7Lxd_o,51010
53
53
  calkit/models/__init__.py,sha256=vGYF4MZBGzDk1BPBzpp1bRb59RCJ2Bj2kzHuVVRacug,120
@@ -99,29 +99,29 @@ calkit/tests/cli/main/test_core.py,sha256=ZRWujJmI2Dtr5FfQxUSXnNfpa-SagkV90y1dHU
99
99
  calkit/tests/cli/main/test_xr.py,sha256=UhtzJEjRiHgE_p_tdjGyYS7I9yy_Ubs2W2lSmLPpBLU,22386
100
100
  calkit/tests/dvc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
101
101
  calkit/tests/dvc/test_core.py,sha256=urN4FIPMVgYfVJxqzH1d7x0hpMI3h2KeArnslfFRDYI,4616
102
- calkit/tests/dvc/test_zip.py,sha256=HClb6kGg0MFnBrTHeMQsUje_syR9CgYT7YCtYK-Rw9w,11040
102
+ calkit/tests/dvc/test_zip.py,sha256=H6L3uJdUpsaNQcOPKnmRxMb5Imr_MaDQFoAnMrZMErU,11212
103
103
  calkit/tests/jupyterlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  calkit/tests/jupyterlab/test_routes.py,sha256=TEEyoHiKnzzKOkQsJcMPKdqpKFQ25yBCvVSquqe9nsE,408
105
105
  calkit/tests/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
106
  calkit/tests/models/test_iteration.py,sha256=vjuDKwyYQAV4w1qF9VJWQEHksq3KRd6gtT39_a-RhnI,644
107
107
  calkit/tests/models/test_pipeline.py,sha256=yefZIG0oHO3xBSwEc3BLx6JOuqKr8GwZvlx1eMcr6SI,9429
108
- calkit_python-0.37.1.data/data/etc/jupyter/jupyter_server_config.d/calkit.json,sha256=CWrZP--JDGz8fsvbAlKr_duTL1vDriGT48SL1YCtkY0,81
109
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/package.json,sha256=HWflZoLFLgne6BqHLI_cZTBzro050PoPTabnCp5NRQc,6651
110
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig,sha256=6w0b5y8LztEv2tErajJ5d39yBryld02crX0CG3zZFNs,6509
111
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json,sha256=YSpIrwpwB-lQBk9Mwv-npedWTOOZreO6nlWZhqlWyGI,840
112
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js,sha256=mixXcqFUZukj7_jQVxHTavsYl7cdZv83sEe4phJgkh0,59893
113
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js,sha256=LEEAOkUtQ9KzWEHn-QFv5yGi70B-sBOnrvztzHr0Shw,223
114
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js,sha256=pCoEaqUQj1T4-zAc9SUd__9ZGm7uL2wHQve2xwL89NI,8156
115
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/909.651be47ca47390b78a92.js,sha256=ZRvkfKRzkLeKkhSUg3qX-df9A80XTd0F0CPcXMfmb-Q,114572
116
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js,sha256=n_a0yu_gE7l6fauyoXXv9BZ7ZEYt2387mTfs7CbLcs4,51939
117
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt,sha256=eNJ8gc9n9IF8nW1d9sI9niuHstYzjNz5vqXx9UgWSPc,249
118
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png,sha256=svHD7-cMtTnRITFwugwsVaB9nZ-h8A61ose8z32HiRE,24850
119
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/remoteEntry.c091821b3d7f2d287a67.js,sha256=wJGCGz1_LSh6Z9lt5VFlfXs92iKQNlLUJshrAQl4ziw,8737
120
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/style.js,sha256=r89Jlk5v1drcwhCpv9FnC3Jig_JH4k24kZNIvxh6Htk,149
121
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json,sha256=2BGdItLJwO3fAopLl4eJvp26TEwuscYC0-yFaF-LaLU,13683
122
- calkit_python-0.37.1.data/data/share/jupyter/labextensions/calkit/install.json,sha256=DK9d8G-q-rMVlcT3rAeGIyo3REWKw6FySBZceLU9yaw,187
123
- calkit_python-0.37.1.dist-info/METADATA,sha256=5h2ujrZJV8kjw7XsrbZKLytWb95sZQv_9hntwAFJj_s,8777
124
- calkit_python-0.37.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
125
- calkit_python-0.37.1.dist-info/entry_points.txt,sha256=59JWYjwz2N3yBOk_9vYUzsMsSs-It1LW8gYE8NsTUJ4,113
126
- calkit_python-0.37.1.dist-info/licenses/LICENSE,sha256=9ZamCaSUTZk9rcrnf-sWFKLOHr3ws-S_dgKMegW4nw8,1056
127
- calkit_python-0.37.1.dist-info/RECORD,,
108
+ calkit_python-0.37.2.data/data/etc/jupyter/jupyter_server_config.d/calkit.json,sha256=CWrZP--JDGz8fsvbAlKr_duTL1vDriGT48SL1YCtkY0,81
109
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/package.json,sha256=HWflZoLFLgne6BqHLI_cZTBzro050PoPTabnCp5NRQc,6651
110
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig,sha256=6w0b5y8LztEv2tErajJ5d39yBryld02crX0CG3zZFNs,6509
111
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json,sha256=YSpIrwpwB-lQBk9Mwv-npedWTOOZreO6nlWZhqlWyGI,840
112
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js,sha256=mixXcqFUZukj7_jQVxHTavsYl7cdZv83sEe4phJgkh0,59893
113
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js,sha256=LEEAOkUtQ9KzWEHn-QFv5yGi70B-sBOnrvztzHr0Shw,223
114
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js,sha256=pCoEaqUQj1T4-zAc9SUd__9ZGm7uL2wHQve2xwL89NI,8156
115
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/909.651be47ca47390b78a92.js,sha256=ZRvkfKRzkLeKkhSUg3qX-df9A80XTd0F0CPcXMfmb-Q,114572
116
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js,sha256=n_a0yu_gE7l6fauyoXXv9BZ7ZEYt2387mTfs7CbLcs4,51939
117
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt,sha256=eNJ8gc9n9IF8nW1d9sI9niuHstYzjNz5vqXx9UgWSPc,249
118
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png,sha256=svHD7-cMtTnRITFwugwsVaB9nZ-h8A61ose8z32HiRE,24850
119
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/remoteEntry.c091821b3d7f2d287a67.js,sha256=wJGCGz1_LSh6Z9lt5VFlfXs92iKQNlLUJshrAQl4ziw,8737
120
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/style.js,sha256=r89Jlk5v1drcwhCpv9FnC3Jig_JH4k24kZNIvxh6Htk,149
121
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json,sha256=2BGdItLJwO3fAopLl4eJvp26TEwuscYC0-yFaF-LaLU,13683
122
+ calkit_python-0.37.2.data/data/share/jupyter/labextensions/calkit/install.json,sha256=DK9d8G-q-rMVlcT3rAeGIyo3REWKw6FySBZceLU9yaw,187
123
+ calkit_python-0.37.2.dist-info/METADATA,sha256=1w6BYdTyAKHWTh-mOZ6_3UFXRHlg9cE_f2Iof4qWQng,8777
124
+ calkit_python-0.37.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
125
+ calkit_python-0.37.2.dist-info/entry_points.txt,sha256=59JWYjwz2N3yBOk_9vYUzsMsSs-It1LW8gYE8NsTUJ4,113
126
+ calkit_python-0.37.2.dist-info/licenses/LICENSE,sha256=9ZamCaSUTZk9rcrnf-sWFKLOHr3ws-S_dgKMegW4nw8,1056
127
+ calkit_python-0.37.2.dist-info/RECORD,,