calkit-python 0.45.1__py3-none-any.whl → 0.45.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 (23) hide show
  1. calkit/cli/main/core.py +12 -3
  2. calkit/dvc/core.py +54 -0
  3. calkit/tests/cli/main/test_core.py +19 -0
  4. calkit/tests/cli/main/test_subprojects.py +101 -0
  5. {calkit_python-0.45.1.dist-info → calkit_python-0.45.2.dist-info}/METADATA +1 -1
  6. {calkit_python-0.45.1.dist-info → calkit_python-0.45.2.dist-info}/RECORD +23 -23
  7. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/etc/jupyter/jupyter_server_config.d/calkit.json +0 -0
  8. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/package.json +0 -0
  9. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig +0 -0
  10. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json +0 -0
  11. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js +0 -0
  12. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js +0 -0
  13. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js +0 -0
  14. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/909.6d8285ce7c45878ac508.js +0 -0
  15. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js +0 -0
  16. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
  17. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png +0 -0
  18. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/remoteEntry.d7a43c7948f690d37d19.js +0 -0
  19. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/style.js +0 -0
  20. {calkit_python-0.45.1.data → calkit_python-0.45.2.data}/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json +0 -0
  21. {calkit_python-0.45.1.dist-info → calkit_python-0.45.2.dist-info}/WHEEL +0 -0
  22. {calkit_python-0.45.1.dist-info → calkit_python-0.45.2.dist-info}/entry_points.txt +0 -0
  23. {calkit_python-0.45.1.dist-info → calkit_python-0.45.2.dist-info}/licenses/LICENSE +0 -0
calkit/cli/main/core.py CHANGED
@@ -286,9 +286,18 @@ def init(
286
286
  needs_own_repo = True
287
287
  if needs_own_repo:
288
288
  subprocess.run(["git", "init"])
289
- result = calkit.dvc.init(force=force)
290
- if result != 0:
291
- raise_error("Failed to initialize DVC")
289
+ # A DVC repo can already exist here without a calkit.yaml, e.g., on
290
+ # platforms that set one up for us, so leave it alone rather than
291
+ # failing on DVC's refusal to initialize over an existing .dvc. The
292
+ # marker is .dvc/config, as elsewhere: a .dvc directory without one is
293
+ # an interrupted initialization, which has nothing worth keeping and
294
+ # which DVC will only initialize over with --force.
295
+ if os.path.isfile(os.path.join(".dvc", "config")) and not force:
296
+ typer.echo("DVC is already initialized")
297
+ else:
298
+ result = calkit.dvc.init(force=force or os.path.isdir(".dvc"))
299
+ if result != 0:
300
+ raise_error("Failed to initialize DVC")
292
301
  # Ensure autostage is enabled for DVC
293
302
  result = calkit.dvc.run_dvc_command(["config", "core.autostage", "true"])
294
303
  if result != 0:
calkit/dvc/core.py CHANGED
@@ -98,6 +98,60 @@ if sys.platform == "win32":
98
98
  _tolerate_lock_release_failures()
99
99
 
100
100
 
101
+ def _hash_dirs_inside_nested_repos() -> None:
102
+ """Make DVC hash directories that live inside nested DVC repos.
103
+
104
+ DVC's ``DvcIgnoreFilter`` prunes nested DVC repos (e.g. isolated
105
+ subprojects) when walking, so the parent never indexes a subproject's
106
+ ``dvc.yaml`` and ``.dvc`` files as its own. The same walk hashes directory
107
+ deps and outs, though, and the subrepo check is order-dependent:
108
+ ``_get_trie_pattern`` hands the starting directory's ``dnames`` to every
109
+ ancestor it visits, so a walk that starts inside the nested repo never
110
+ registers it, while the root-level index walk does. Whichever touches the
111
+ ignore trie first wins for the rest of the process. In practice a parent
112
+ stage depending on a directory inside an isolated subproject hashes it as
113
+ *empty* on ``status`` but not always on ``repro``, so ``dvc.lock`` and
114
+ ``dvc status`` disagree and the stage is forever stale (or, worse, changes
115
+ in the subproject go unnoticed).
116
+
117
+ A walk that starts at or below a nested repo can only be a caller hashing
118
+ that path (the index walk always starts at the repo root), and the caller
119
+ named the path deliberately, so its contents must be hashed. Such walks
120
+ are routed through DVC's ``ignore_subrepos=False`` trie, which is built
121
+ separately, is deterministic, and still honors every ``.dvcignore`` on
122
+ the way down, including the nested repo's own.
123
+ """
124
+ from dvc.ignore import DvcIgnoreFilter
125
+ from dvc.repo import Repo
126
+
127
+ original_walk = DvcIgnoreFilter.walk
128
+
129
+ def in_nested_repo(dvcignore: Any, path: str) -> bool:
130
+ fs = dvcignore.fs
131
+ root_dir = dvcignore.root_dir
132
+ current = fs.abspath(path)
133
+ if not fs.isin(current, root_dir):
134
+ return False
135
+ while current != root_dir:
136
+ if fs.exists(fs.join(current, Repo.DVC_DIR)):
137
+ return True
138
+ parent = fs.parent(current)
139
+ if parent == current:
140
+ return False
141
+ current = parent
142
+ return False
143
+
144
+ def walk(self: Any, fs: Any, path: str, **kwargs: Any) -> Any:
145
+ if "ignore_subrepos" not in kwargs and in_nested_repo(self, path):
146
+ kwargs["ignore_subrepos"] = False
147
+ return original_walk(self, fs, path, **kwargs)
148
+
149
+ DvcIgnoreFilter.walk = walk
150
+
151
+
152
+ _hash_dirs_inside_nested_repos()
153
+
154
+
101
155
  # Default seconds to wait for DVC's repo-level lock during a pipeline run.
102
156
  #
103
157
  # DVC's own default is only 3 seconds (``dvc.lock.DEFAULT_TIMEOUT``), after
@@ -149,6 +149,25 @@ def test_init(tmp_dir):
149
149
  # --force allows re-initialization without clobbering calkit.yaml
150
150
  subprocess.check_call(["calkit", "init", "--force"], cwd="sub")
151
151
  assert calkit.load_calkit_info(wdir="sub") == ck_info
152
+ # An existing DVC repo with no calkit.yaml is left alone rather than
153
+ # failing on DVC's refusal to initialize over an existing .dvc (#1013)
154
+ os.remove(os.path.join("sub", "calkit.yaml"))
155
+ assert os.path.isdir(os.path.join("sub", ".dvc"))
156
+ result = subprocess.run(
157
+ ["calkit", "init"],
158
+ cwd="sub",
159
+ capture_output=True,
160
+ text=True,
161
+ )
162
+ assert result.returncode == 0
163
+ assert "already initialized" in result.stdout.lower()
164
+ assert os.path.isfile(os.path.join("sub", "calkit.yaml"))
165
+ assert calkit.load_calkit_info(wdir="sub") == {}
166
+ # A .dvc directory left behind by an interrupted init has no config in
167
+ # it, so it is re-initialized rather than taken for a working repo
168
+ os.remove(os.path.join("sub", ".dvc", "config"))
169
+ subprocess.check_call(["calkit", "init"], cwd="sub")
170
+ assert os.path.isfile(os.path.join("sub", ".dvc", "config"))
152
171
  # --no-commit stages the initial files without committing, so a
153
172
  # bootstrap (as run by xr) can be rolled back by restoring files
154
173
  os.makedirs("nocommit")
@@ -4,6 +4,7 @@ import os
4
4
  import subprocess
5
5
 
6
6
  import calkit
7
+ import calkit.dvc
7
8
  import calkit.pipeline
8
9
 
9
10
 
@@ -375,6 +376,106 @@ def test_isolated_subproject_external_dep(tmp_dir):
375
376
  assert not status.is_stale
376
377
 
377
378
 
379
+ def test_isolated_subproject_dir_dep(tmp_dir):
380
+ # A parent stage depending on a *directory* inside an isolated
381
+ # subproject: DVC prunes nested repos when walking, so without calkit's
382
+ # workaround the directory hashes as empty on status (but not always on
383
+ # repro), leaving the stage forever stale and blind to subproject changes.
384
+ def write_sub(b_content):
385
+ # Create the output directory here, since mkdir -p doesn't work in
386
+ # cmd.exe on Windows
387
+ os.makedirs("sub/figs", exist_ok=True)
388
+ write_ck_info(
389
+ "sub/calkit.yaml",
390
+ {
391
+ "pipeline": {
392
+ "stages": {
393
+ "make-figs": make_stage(
394
+ "echo a > figs/a.txt && "
395
+ f"echo {b_content} > figs/b.txt",
396
+ outputs=[
397
+ {"path": "figs/a.txt", "storage": "git"},
398
+ {"path": "figs/b.txt", "storage": "git"},
399
+ ],
400
+ )
401
+ }
402
+ }
403
+ },
404
+ )
405
+ calkit.pipeline.to_dvc(wdir="sub", write=True, manage_gitignore=False)
406
+
407
+ subprocess.check_call(["calkit", "init"])
408
+ init_isolated_subproject("sub", {})
409
+ write_sub("b")
410
+ write_ck_info(
411
+ "calkit.yaml",
412
+ {
413
+ "subprojects": [{"path": "sub"}],
414
+ "pipeline": {
415
+ "stages": {
416
+ "consume": make_stage(
417
+ "cat sub/figs/* > parent.txt",
418
+ inputs=["sub/figs/"],
419
+ outputs=[{"path": "parent.txt", "storage": "git"}],
420
+ )
421
+ }
422
+ },
423
+ },
424
+ )
425
+ subprocess.check_call(["calkit", "run"])
426
+ # Windows' echo leaves trailing spaces, so compare tokens
427
+ with open("parent.txt") as f:
428
+ assert f.read().split() == ["a", "b"]
429
+ # The lock must record the directory's real contents, not an empty dir
430
+ with open("dvc.lock") as f:
431
+ lock = calkit.ryaml.load(f)
432
+ figs_dep = [
433
+ d
434
+ for d in lock["stages"]["consume"]["deps"]
435
+ if d["path"] == "sub/figs/"
436
+ ][0]
437
+ assert figs_dep["nfiles"] == 2
438
+ # And status must agree with the lock
439
+ status = calkit.pipeline.get_status(
440
+ check_environments=False, compile_to_dvc=False
441
+ )
442
+ assert not status.is_stale
443
+ # Hashing must not depend on whether the index walk (which registers the
444
+ # subrepo in DVC's ignore trie) ran first
445
+ repo = calkit.dvc.get_dvc_repo()
446
+ list(repo.index.stages)
447
+ found = sorted(
448
+ os.path.relpath(p)
449
+ for p in repo.dvcignore.find(repo.fs, os.path.abspath("sub/figs"))
450
+ )
451
+ assert found == [
452
+ os.path.join("sub", "figs", "a.txt"),
453
+ os.path.join("sub", "figs", "b.txt"),
454
+ ]
455
+ # The index walk still keeps the subproject's own pipeline out of the
456
+ # parent's index
457
+ assert {s.addressing for s in repo.index.stages} == {"sub", "consume"}
458
+ # A change inside the subproject propagates to the parent stage
459
+ write_sub("c")
460
+ subprocess.check_call(["calkit", "run"])
461
+ with open("parent.txt") as f:
462
+ assert f.read().split() == ["a", "c"]
463
+ status = calkit.pipeline.get_status(
464
+ check_environments=False, compile_to_dvc=False
465
+ )
466
+ assert not status.is_stale
467
+ # Editing a file in the directory makes the parent stage stale
468
+ with open("sub/figs/a.txt", "w") as f:
469
+ f.write("z\n")
470
+ status = calkit.pipeline.get_status(
471
+ check_environments=False, compile_to_dvc=False
472
+ )
473
+ assert status.is_stale
474
+ assert [
475
+ p.rstrip("/") for p in status.stale_stages["consume"].modified_inputs
476
+ ] == ["sub/figs"]
477
+
478
+
378
479
  def test_targeted_status_uses_full_subproject_status_for_stage_targets(
379
480
  tmp_dir, monkeypatch
380
481
  ):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: calkit-python
3
- Version: 0.45.1
3
+ Version: 0.45.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
@@ -54,10 +54,10 @@ calkit/cli/scheduler.py,sha256=GQf_Hw2qVSrFH4SzSQCOdbZzZ-n2EdKgR2NoqNIqWlw,53064
54
54
  calkit/cli/sync.py,sha256=UGen0Yey6BARooI5K83eiArw4YN2ZQcRQjCocaGy6E4,2539
55
55
  calkit/cli/update.py,sha256=4CbMxL3jS2l2mF32174IYLjN0DpoqCOag814UekKaVk,48411
56
56
  calkit/cli/main/__init__.py,sha256=qu1POZPyqs33ZKfasOxv_Wc-EzVcEgK3Dt_vwFL8Bi8,65
57
- calkit/cli/main/core.py,sha256=zQoqy6uy1__2CjJpc4xm8wq5KExXvEN5rgi0vDmk9Dw,152154
57
+ calkit/cli/main/core.py,sha256=VtLEXS7xIYvnucXx7vJwMBuSi_WsfGg7y7GorpGfrO4,152737
58
58
  calkit/cli/main/xr.py,sha256=cYQBNVlRTzp6ba3EwEwZylOxVpk9ThWhy6IAD7_ahWw,37594
59
59
  calkit/dvc/__init__.py,sha256=-B6tilCb_jw7QFmJ2srILez24wDhNKUzIBhZUMt01dE,381
60
- calkit/dvc/core.py,sha256=_viZIkl5qO6Bnipru0w2zaEc2xwXuEOSYCDvlDoEaU0,36282
60
+ calkit/dvc/core.py,sha256=0yfq_p3CrejFxGEl19za9M2ZdywByZPS4MtndK_R2Mo,38637
61
61
  calkit/dvc/zip.py,sha256=nf4EzOyc5nI_OA3M6S7wwZpL7N4EQz9yCf8FbnPjlxM,21857
62
62
  calkit/jupyterlab/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  calkit/jupyterlab/routes.py,sha256=sARrFjWnHVV-LunrgqO4DCt_x7XLhVPAqA1eaUFf7HQ,51443
@@ -142,9 +142,9 @@ calkit/tests/cli/test_scheduler.py,sha256=YfJi_fcRlQt1bdFyo3b8BFelA1PcH-wn5lAVXi
142
142
  calkit/tests/cli/test_sync.py,sha256=jmhfgoMIjdihIuu9UVyHSizBDTF0hlBt2VWqEdVkAKk,4375
143
143
  calkit/tests/cli/test_update.py,sha256=i7dsfrDVD-0VA7knspzbb-6UZWHgGPVkbB6CsT0czMM,14878
144
144
  calkit/tests/cli/main/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
- calkit/tests/cli/main/test_core.py,sha256=a22eVhjPeK4cyFIm9uAf_jOzDStJ-GRi7cKlxdQOY4E,92505
145
+ calkit/tests/cli/main/test_core.py,sha256=LFS-3p01qVWlmG4RmB5CcRqMRVfllk0eLibWIqMb27E,93415
146
146
  calkit/tests/cli/main/test_lock.py,sha256=1iX8iSbGtr4O9OkaAi4d3gP3_QzNl6Rr6HLtbEpS6iU,9847
147
- calkit/tests/cli/main/test_subprojects.py,sha256=RKWHKoqWLgJnsBBbD5Q-DJHQ5agZdOS7ahzfPzkr878,14942
147
+ calkit/tests/cli/main/test_subprojects.py,sha256=Qs5NvwhQEFlZUvAtOyCWN243PONz8N79np5HwlgUl7E,18709
148
148
  calkit/tests/cli/main/test_xr.py,sha256=iauAWKXdzaaRFu5W91l4ZdH_ZU3h2NAn3v5p-EhAbco,28798
149
149
  calkit/tests/dvc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
150
150
  calkit/tests/dvc/test_core.py,sha256=LCmtZO_vLkW4GHf8nfeZvouLifVIc3VuuArkdKf6vD8,18215
@@ -159,22 +159,22 @@ calkit/tests/models/test_pipeline.py,sha256=hglkTBry1ONKbzN1HmlpefbrqAbc-668C0MQ
159
159
  calkit/agent_skills/add-pipeline-stage/SKILL.md,sha256=kpYYb-rJsS4B9p1Ub3gL21irCG5ZZ4DvWZpdJeEwPZk,3772
160
160
  calkit/agent_skills/conventions/SKILL.md,sha256=osbAtYU0AwROZHgmOoQYbqYr3JwG_v-cJAmandm7yN4,9738
161
161
  calkit/agent_skills/create-pipeline/SKILL.md,sha256=2FGw1iDQVRk5FUq79GP3lPdgvgof2Wi1O9O-abGGtgs,5422
162
- calkit_python-0.45.1.data/data/etc/jupyter/jupyter_server_config.d/calkit.json,sha256=CWrZP--JDGz8fsvbAlKr_duTL1vDriGT48SL1YCtkY0,81
163
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/package.json,sha256=tYRdVVqmPBoUJzNrMc7Da9Lk-NB54vhnplKRSlOTMIE,6224
164
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig,sha256=NBG3t7gFYb6_2J-yPU29qS7Ck9pYgm8-wC5Q1LrzQeI,6082
165
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json,sha256=YSpIrwpwB-lQBk9Mwv-npedWTOOZreO6nlWZhqlWyGI,840
166
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js,sha256=mixXcqFUZukj7_jQVxHTavsYl7cdZv83sEe4phJgkh0,59893
167
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js,sha256=LEEAOkUtQ9KzWEHn-QFv5yGi70B-sBOnrvztzHr0Shw,223
168
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js,sha256=pCoEaqUQj1T4-zAc9SUd__9ZGm7uL2wHQve2xwL89NI,8156
169
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/909.6d8285ce7c45878ac508.js,sha256=bYKFznxFh4rFCPs8tWnbZgaFGp72DuPZGdkzYCoCaSU,114583
170
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js,sha256=n_a0yu_gE7l6fauyoXXv9BZ7ZEYt2387mTfs7CbLcs4,51939
171
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt,sha256=eNJ8gc9n9IF8nW1d9sI9niuHstYzjNz5vqXx9UgWSPc,249
172
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png,sha256=svHD7-cMtTnRITFwugwsVaB9nZ-h8A61ose8z32HiRE,24850
173
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/remoteEntry.d7a43c7948f690d37d19.js,sha256=16Q8eUj2kNN9Gaeoe3hOSEUPMJ5IUHQnJF1h9DRUIJY,8737
174
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/style.js,sha256=r89Jlk5v1drcwhCpv9FnC3Jig_JH4k24kZNIvxh6Htk,149
175
- calkit_python-0.45.1.data/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json,sha256=2BGdItLJwO3fAopLl4eJvp26TEwuscYC0-yFaF-LaLU,13683
176
- calkit_python-0.45.1.dist-info/METADATA,sha256=RpRntx5V2HE6ajwpb2e1Lw4vbvOMokNZKs9cC7NZl_A,12818
177
- calkit_python-0.45.1.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
178
- calkit_python-0.45.1.dist-info/entry_points.txt,sha256=2iQBBzjTAOdk66CwS-f3ecXXW5DjUqkG1KBRj8mHI1I,133
179
- calkit_python-0.45.1.dist-info/licenses/LICENSE,sha256=9ZamCaSUTZk9rcrnf-sWFKLOHr3ws-S_dgKMegW4nw8,1056
180
- calkit_python-0.45.1.dist-info/RECORD,,
162
+ calkit_python-0.45.2.data/data/etc/jupyter/jupyter_server_config.d/calkit.json,sha256=CWrZP--JDGz8fsvbAlKr_duTL1vDriGT48SL1YCtkY0,81
163
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/package.json,sha256=tYRdVVqmPBoUJzNrMc7Da9Lk-NB54vhnplKRSlOTMIE,6224
164
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig,sha256=NBG3t7gFYb6_2J-yPU29qS7Ck9pYgm8-wC5Q1LrzQeI,6082
165
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json,sha256=YSpIrwpwB-lQBk9Mwv-npedWTOOZreO6nlWZhqlWyGI,840
166
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/502.9a2c5772a15466e923ef.js,sha256=mixXcqFUZukj7_jQVxHTavsYl7cdZv83sEe4phJgkh0,59893
167
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/695.2c41003a452d43d2b358.js,sha256=LEEAOkUtQ9KzWEHn-QFv5yGi70B-sBOnrvztzHr0Shw,223
168
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/867.a42a046aa5108f54f8fb.js,sha256=pCoEaqUQj1T4-zAc9SUd__9ZGm7uL2wHQve2xwL89NI,8156
169
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/909.6d8285ce7c45878ac508.js,sha256=bYKFznxFh4rFCPs8tWnbZgaFGp72DuPZGdkzYCoCaSU,114583
170
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js,sha256=n_a0yu_gE7l6fauyoXXv9BZ7ZEYt2387mTfs7CbLcs4,51939
171
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt,sha256=eNJ8gc9n9IF8nW1d9sI9niuHstYzjNz5vqXx9UgWSPc,249
172
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/b2f1c3efe70cb539d121.png,sha256=svHD7-cMtTnRITFwugwsVaB9nZ-h8A61ose8z32HiRE,24850
173
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/remoteEntry.d7a43c7948f690d37d19.js,sha256=16Q8eUj2kNN9Gaeoe3hOSEUPMJ5IUHQnJF1h9DRUIJY,8737
174
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/style.js,sha256=r89Jlk5v1drcwhCpv9FnC3Jig_JH4k24kZNIvxh6Htk,149
175
+ calkit_python-0.45.2.data/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json,sha256=2BGdItLJwO3fAopLl4eJvp26TEwuscYC0-yFaF-LaLU,13683
176
+ calkit_python-0.45.2.dist-info/METADATA,sha256=Rr27zNPVQ_KH7uaw8FcHthxM9g6dHF_jsYw6aTp8qhA,12818
177
+ calkit_python-0.45.2.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
178
+ calkit_python-0.45.2.dist-info/entry_points.txt,sha256=2iQBBzjTAOdk66CwS-f3ecXXW5DjUqkG1KBRj8mHI1I,133
179
+ calkit_python-0.45.2.dist-info/licenses/LICENSE,sha256=9ZamCaSUTZk9rcrnf-sWFKLOHr3ws-S_dgKMegW4nw8,1056
180
+ calkit_python-0.45.2.dist-info/RECORD,,