calkit-python 0.32.11__tar.gz → 0.33.1__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.
Files changed (274) hide show
  1. {calkit_python-0.32.11 → calkit_python-0.33.1}/.gitignore +7 -0
  2. {calkit_python-0.32.11 → calkit_python-0.33.1}/.pre-commit-config.yaml +2 -0
  3. calkit_python-0.33.1/.prettierignore +10 -0
  4. calkit_python-0.33.1/.yarnrc.yml +2 -0
  5. {calkit_python-0.32.11 → calkit_python-0.33.1}/CONTRIBUTING.md +18 -0
  6. {calkit_python-0.32.11 → calkit_python-0.33.1}/Makefile +22 -3
  7. {calkit_python-0.32.11 → calkit_python-0.33.1}/PKG-INFO +13 -2
  8. calkit_python-0.33.1/babel.config.js +1 -0
  9. calkit_python-0.33.1/calkit/__init__.py +49 -0
  10. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/import_.py +200 -3
  11. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/main.py +45 -75
  12. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/new.py +6 -5
  13. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/core.py +63 -2
  14. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/dvc.py +86 -0
  15. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/git.py +2 -1
  16. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/invenio.py +22 -10
  17. calkit_python-0.33.1/calkit/jupyterlab/routes.py +1343 -0
  18. calkit_python-0.33.1/calkit/labextension/package.json +217 -0
  19. calkit_python-0.33.1/calkit/labextension/schemas/calkit/package.json.orig +212 -0
  20. calkit_python-0.33.1/calkit/labextension/schemas/calkit/plugin.json +44 -0
  21. calkit_python-0.33.1/calkit/labextension/static/502.9a2c5772a15466e923ef.js +1 -0
  22. calkit_python-0.33.1/calkit/labextension/static/695.2c41003a452d43d2b358.js +1 -0
  23. calkit_python-0.33.1/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +1 -0
  24. calkit_python-0.33.1/calkit/labextension/static/909.bc803769ea27551457d9.js +1 -0
  25. calkit_python-0.33.1/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +2 -0
  26. calkit_python-0.33.1/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +9 -0
  27. calkit_python-0.33.1/calkit/labextension/static/remoteEntry.bc3529435b6f02f41e8d.js +1 -0
  28. calkit_python-0.33.1/calkit/labextension/static/style.js +4 -0
  29. calkit_python-0.33.1/calkit/labextension/static/third-party-licenses.json +52 -0
  30. calkit_python-0.33.1/calkit/tests/cli/test_import.py +25 -0
  31. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_main.py +9 -4
  32. calkit_python-0.33.1/calkit/tests/jupyterlab/__init__.py +0 -0
  33. calkit_python-0.33.1/calkit/tests/jupyterlab/test_routes.py +16 -0
  34. calkit_python-0.33.1/calkit/tests/models/__init__.py +0 -0
  35. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_check.py +2 -4
  36. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_core.py +11 -2
  37. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_dvc.py +11 -0
  38. calkit_python-0.33.1/conftest.py +8 -0
  39. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/cloud-integration.md +3 -0
  40. calkit_python-0.33.1/docs/img/calkit-no-bg.png +0 -0
  41. calkit_python-0.33.1/docs/img/jupyterlab/all-green.png +0 -0
  42. calkit_python-0.33.1/docs/img/jupyterlab/collect-data-stale.png +0 -0
  43. calkit_python-0.33.1/docs/img/jupyterlab/new-env.png +0 -0
  44. calkit_python-0.33.1/docs/img/jupyterlab/new-notebook.png +0 -0
  45. calkit_python-0.33.1/docs/img/jupyterlab/pipeline-badge.png +0 -0
  46. calkit_python-0.33.1/docs/jupyterlab.md +85 -0
  47. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/notebooks.md +3 -0
  48. calkit_python-0.33.1/install.json +5 -0
  49. calkit_python-0.33.1/jest.config.js +42 -0
  50. calkit_python-0.33.1/jupyter-config/server-config/calkit.json +7 -0
  51. {calkit_python-0.32.11 → calkit_python-0.33.1}/mkdocs.yml +2 -0
  52. calkit_python-0.33.1/package.json +212 -0
  53. calkit_python-0.33.1/pyproject.toml +162 -0
  54. calkit_python-0.33.1/schema/plugin.json +44 -0
  55. calkit_python-0.33.1/src/__tests__/useQueries.spec.ts +163 -0
  56. calkit_python-0.33.1/src/calkit-config.ts +130 -0
  57. calkit_python-0.33.1/src/cell-output-marker.ts +128 -0
  58. calkit_python-0.33.1/src/components/commit-dialog.tsx +233 -0
  59. calkit_python-0.33.1/src/components/environment-editor.tsx +819 -0
  60. calkit_python-0.33.1/src/components/notebook-registration.tsx +379 -0
  61. calkit_python-0.33.1/src/components/notebook-toolbar.tsx +1398 -0
  62. calkit_python-0.33.1/src/components/pipeline-status-bar.tsx +174 -0
  63. calkit_python-0.33.1/src/components/project-info-editor.tsx +218 -0
  64. calkit_python-0.33.1/src/components/sidebar-settings.tsx +80 -0
  65. calkit_python-0.33.1/src/components/sidebar.tsx +2079 -0
  66. calkit_python-0.33.1/src/components/stage-editor.tsx +692 -0
  67. calkit_python-0.33.1/src/feature-flags.ts +172 -0
  68. calkit_python-0.33.1/src/file-browser-menu.ts +327 -0
  69. calkit_python-0.33.1/src/hooks/__tests__/useQueries.test.tsx +356 -0
  70. calkit_python-0.33.1/src/hooks/useQueries.ts +438 -0
  71. calkit_python-0.33.1/src/icons.ts +41 -0
  72. calkit_python-0.33.1/src/index.ts +504 -0
  73. calkit_python-0.33.1/src/io-tracker.ts +218 -0
  74. calkit_python-0.33.1/src/pipeline-state.ts +89 -0
  75. calkit_python-0.33.1/src/queryClient.ts +15 -0
  76. calkit_python-0.33.1/src/request.ts +59 -0
  77. calkit_python-0.33.1/src/shims-mainmenu.d.ts +10 -0
  78. calkit_python-0.33.1/style/base.css +7 -0
  79. calkit_python-0.33.1/style/cell-output-marker.css +23 -0
  80. calkit_python-0.33.1/style/environment-editor.css +539 -0
  81. calkit_python-0.33.1/style/environment-selector.css +78 -0
  82. calkit_python-0.33.1/style/img/calkit-no-bg.png +0 -0
  83. calkit_python-0.33.1/style/index.css +5 -0
  84. calkit_python-0.33.1/style/index.js +2 -0
  85. calkit_python-0.33.1/style/notebook-toolbar.css +729 -0
  86. calkit_python-0.33.1/style/pipeline-status-bar.css +88 -0
  87. calkit_python-0.33.1/style/sidebar.css +1256 -0
  88. calkit_python-0.33.1/test/dvc-md5-dir/osx-arm64.txt +70 -0
  89. calkit_python-0.33.1/tsconfig.json +25 -0
  90. calkit_python-0.33.1/tsconfig.test.json +3 -0
  91. calkit_python-0.33.1/ui-tests/.gitignore +5 -0
  92. calkit_python-0.33.1/ui-tests/README.md +167 -0
  93. calkit_python-0.33.1/ui-tests/jupyter_server_test_config.py +13 -0
  94. calkit_python-0.33.1/ui-tests/package.json +15 -0
  95. calkit_python-0.33.1/ui-tests/playwright.config.js +14 -0
  96. calkit_python-0.33.1/ui-tests/tests/calkit.spec.ts +360 -0
  97. calkit_python-0.33.1/ui-tests/yarn.lock +5977 -0
  98. {calkit_python-0.32.11 → calkit_python-0.33.1}/uv.lock +546 -405
  99. calkit_python-0.33.1/yarn.lock +11371 -0
  100. calkit_python-0.32.11/.github/FUNDING.yml +0 -16
  101. calkit_python-0.32.11/.github/workflows/docs.yml +0 -31
  102. calkit_python-0.32.11/.github/workflows/format.yml +0 -13
  103. calkit_python-0.32.11/.github/workflows/publish-test.yml +0 -49
  104. calkit_python-0.32.11/.github/workflows/publish.yml +0 -48
  105. calkit_python-0.32.11/.github/workflows/test.yml +0 -78
  106. calkit_python-0.32.11/calkit/__init__.py +0 -20
  107. calkit_python-0.32.11/pyproject.toml +0 -108
  108. {calkit_python-0.32.11 → calkit_python-0.33.1}/.python-version +0 -0
  109. {calkit_python-0.32.11 → calkit_python-0.33.1}/CITATION.cff +0 -0
  110. {calkit_python-0.32.11 → calkit_python-0.33.1}/CODE_OF_CONDUCT.md +0 -0
  111. {calkit_python-0.32.11 → calkit_python-0.33.1}/LICENSE +0 -0
  112. {calkit_python-0.32.11 → calkit_python-0.33.1}/README.md +0 -0
  113. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/__main__.py +0 -0
  114. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/calc.py +0 -0
  115. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/check.py +0 -0
  116. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/__init__.py +0 -0
  117. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/check.py +0 -0
  118. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/cloud.py +0 -0
  119. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/config.py +0 -0
  120. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/core.py +0 -0
  121. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/describe.py +0 -0
  122. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/latex.py +0 -0
  123. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/list.py +0 -0
  124. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/notebooks.py +0 -0
  125. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/office.py +0 -0
  126. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/overleaf.py +0 -0
  127. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/slurm.py +0 -0
  128. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cli/update.py +0 -0
  129. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/cloud.py +0 -0
  130. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/conda.py +0 -0
  131. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/config.py +0 -0
  132. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/datasets.py +0 -0
  133. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/docker.py +0 -0
  134. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/environments.py +0 -0
  135. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/github.py +0 -0
  136. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/gui.py +0 -0
  137. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/jupyter.py +0 -0
  138. {calkit_python-0.32.11/calkit/tests → calkit_python-0.33.1/calkit/jupyterlab}/__init__.py +0 -0
  139. /calkit_python-0.32.11/docs/img/calkit-no-bg.png → /calkit_python-0.33.1/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
  140. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/licenses.py +0 -0
  141. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/magics.py +0 -0
  142. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/matlab.py +0 -0
  143. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/models/__init__.py +0 -0
  144. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/models/core.py +0 -0
  145. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/models/io.py +0 -0
  146. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/models/iteration.py +0 -0
  147. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/models/pipeline.py +0 -0
  148. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/notebooks.py +0 -0
  149. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/office.py +0 -0
  150. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/ops.py +0 -0
  151. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/overleaf.py +0 -0
  152. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/pipeline.py +0 -0
  153. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/releases.py +0 -0
  154. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/server.py +0 -0
  155. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/__init__.py +0 -0
  156. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/core.py +0 -0
  157. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/__init__.py +0 -0
  158. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/article/paper.tex +0 -0
  159. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/core.py +0 -0
  160. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/jfm/jfm.bst +0 -0
  161. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/jfm/jfm.cls +0 -0
  162. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
  163. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/jfm/paper.tex +0 -0
  164. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/templates/latex/jfm/upmath.sty +0 -0
  165. {calkit_python-0.32.11/calkit/tests/cli → calkit_python-0.33.1/calkit/tests}/__init__.py +0 -0
  166. {calkit_python-0.32.11/calkit/tests/models → calkit_python-0.33.1/calkit/tests/cli}/__init__.py +0 -0
  167. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_check.py +0 -0
  168. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_config.py +0 -0
  169. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_latex.py +0 -0
  170. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_list.py +0 -0
  171. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_new.py +0 -0
  172. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_notebooks.py +0 -0
  173. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/cli/test_overleaf.py +0 -0
  174. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/models/test_iteration.py +0 -0
  175. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/models/test_pipeline.py +0 -0
  176. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_calc.py +0 -0
  177. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_conda.py +0 -0
  178. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_environments.py +0 -0
  179. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_git.py +0 -0
  180. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_invenio.py +0 -0
  181. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_jupyter.py +0 -0
  182. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_magics.py +0 -0
  183. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_notebooks.py +0 -0
  184. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_pipeline.py +0 -0
  185. {calkit_python-0.32.11 → calkit_python-0.33.1}/calkit/tests/test_templates.py +0 -0
  186. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/CNAME +0 -0
  187. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/apps.md +0 -0
  188. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/calculations.md +0 -0
  189. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/calkit-yaml.md +0 -0
  190. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/cli-reference.md +0 -0
  191. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/datasets.md +0 -0
  192. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/dependencies.md +0 -0
  193. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/environments.md +0 -0
  194. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/examples.md +0 -0
  195. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/governance.md +0 -0
  196. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/help.md +0 -0
  197. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/img/c-to-the-k-white.svg +0 -0
  198. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/img/calkit-fragmentation-compendium.png +0 -0
  199. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/img/connect-zenodo.png +0 -0
  200. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/img/jupyterlab-params.png +0 -0
  201. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/img/plos-osi-code-2024-03.png +0 -0
  202. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/img/vscode-nb-params.png +0 -0
  203. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/index.md +0 -0
  204. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/installation.md +0 -0
  205. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/local-server.md +0 -0
  206. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/overleaf.md +0 -0
  207. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/pipeline/index.md +0 -0
  208. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/pipeline/manual-steps.md +0 -0
  209. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/pipeline/running-and-logging.md +0 -0
  210. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/pipeline/slurm.md +0 -0
  211. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/quickstart.md +0 -0
  212. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/references.md +0 -0
  213. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/releases.md +0 -0
  214. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/adding-latex-pub-docker.md +0 -0
  215. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/conda-envs.md +0 -0
  216. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/existing-project.md +0 -0
  217. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/first-project.md +0 -0
  218. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/github-actions.md +0 -0
  219. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/actions-repo-secrets.png +0 -0
  220. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
  221. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
  222. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
  223. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
  224. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
  225. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
  226. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
  227. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
  228. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
  229. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
  230. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/push.png +0 -0
  231. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
  232. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
  233. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/chart-more-rows.png +0 -0
  234. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/create-project.png +0 -0
  235. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
  236. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/excel-chart.png +0 -0
  237. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/excel-data.png +0 -0
  238. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
  239. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/needs-clone.png +0 -0
  240. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/new-stage.png +0 -0
  241. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
  242. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
  243. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/status-more-rows.png +0 -0
  244. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
  245. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/untracked-data.png +0 -0
  246. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/updated-publication.png +0 -0
  247. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
  248. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/office/workflow-page.png +0 -0
  249. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/clone.png +0 -0
  250. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/create-project.png +0 -0
  251. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
  252. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
  253. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
  254. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/new-token.png +0 -0
  255. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/reclone.png +0 -0
  256. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
  257. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/quick-actions.png +0 -0
  258. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/img/run-proc.png +0 -0
  259. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/index.md +0 -0
  260. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/latex-codespaces.md +0 -0
  261. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/matlab.md +0 -0
  262. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/notebook-pipeline.md +0 -0
  263. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/office.md +0 -0
  264. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/openfoam.md +0 -0
  265. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/tutorials/procedures.md +0 -0
  266. {calkit_python-0.32.11 → calkit_python-0.33.1}/docs/version-control.md +0 -0
  267. {calkit_python-0.32.11 → calkit_python-0.33.1}/scripts/install.ps1 +0 -0
  268. {calkit_python-0.32.11 → calkit_python-0.33.1}/scripts/install.sh +0 -0
  269. {calkit_python-0.32.11 → calkit_python-0.33.1}/test/nb-julia.ipynb +0 -0
  270. {calkit_python-0.32.11 → calkit_python-0.33.1}/test/nb-params.ipynb +0 -0
  271. {calkit_python-0.32.11 → calkit_python-0.33.1}/test/nb-subdir.ipynb +0 -0
  272. {calkit_python-0.32.11 → calkit_python-0.33.1}/test/pipeline.ipynb +0 -0
  273. {calkit_python-0.32.11 → calkit_python-0.33.1}/test/script.py +0 -0
  274. {calkit_python-0.32.11 → calkit_python-0.33.1}/test/test-log.log +0 -0
@@ -8,3 +8,10 @@ site
8
8
  .coverage*
9
9
  coverage.xml
10
10
  import.log
11
+ tsconfig.tsbuildinfo
12
+ lib
13
+ node_modules
14
+ .yarn
15
+ calkit/labextension
16
+ coverage
17
+ junit.xml
@@ -20,3 +20,5 @@ repos:
20
20
  hooks:
21
21
  - id: prettier
22
22
  exclude: calkit
23
+ args:
24
+ - --config=package.json
@@ -0,0 +1,10 @@
1
+ node_modules
2
+ **/node_modules
3
+ **/lib
4
+ **/package.json
5
+ !/package.json
6
+ calkit
7
+ .mypy_cache
8
+ .pytest_cache
9
+ .ruff_cache
10
+ .venv
@@ -0,0 +1,2 @@
1
+ nodeLinker: node-modules
2
+ enableScripts: false
@@ -31,6 +31,24 @@ This guide will help you get started.
31
31
  ```bash
32
32
  uv run pytest
33
33
  ```
34
+ 1. Install the Calkit CLI in dev mode:
35
+ ```sh
36
+ uv tool install -e .
37
+ ```
38
+ 1. Install the JupyterLab extension in development mode
39
+ (if working on the JupyterLab extension):
40
+ ```sh
41
+ uv run jupyter labextension develop . --overwrite
42
+ ```
43
+ 1. Start the JupyterLab extension TypeScript compiler in watch mode
44
+ (if working on the JupyterLab extension):
45
+ ```sh
46
+ make jlab-dev
47
+ ```
48
+ 1. Start JupyterLab:
49
+ ```sh
50
+ uv run jupyter lab
51
+ ```
34
52
 
35
53
  ### 3. Make your changes
36
54
 
@@ -32,14 +32,33 @@ test-cov: ## Test the code coverage with pytest.
32
32
  @echo "🚀 Testing code coverage with pytest"
33
33
  @uv run pytest --cov --cov-config=pyproject.toml
34
34
 
35
- .PHONY: docs-test
36
- docs-test: ## Test if documentation can be built without warnings or errors.
35
+ .PHONY: test-docs
36
+ test-docs: ## Test if documentation can be built without warnings or errors.
37
37
  @uv run mkdocs build -s
38
38
 
39
39
  .PHONY: docs
40
40
  docs: ## Build and serve the documentation.
41
- @uv run mkdocs serve
41
+ @uv run mkdocs serve --livereload
42
42
 
43
43
  .PHONY: import-profile
44
44
  import-profile: ## Profile the import time of the CLI.
45
45
  uv run python -X importtime -m calkit --help 2> import.log && uvx tuna import.log
46
+
47
+ .PHONY: jlab-dev
48
+ jlab-dev: ## Develop the JupyterLab extension.
49
+ uv run jlpm run watch
50
+
51
+ .PHONY: jlab
52
+ jlab: ## Build the JupyterLab extension.
53
+ uv run jlpm run build:prod
54
+
55
+ .PHONY: test-frontend
56
+ test-frontend: ## Run frontend unit tests with Jest.
57
+ @echo "🚀 Running frontend unit tests"
58
+ @uv run jlpm test
59
+
60
+ .PHONY: test-ui
61
+ test-ui: ## Run the JupyterLab UI integration tests.
62
+ @echo "🚀 Running JupyterLab UI tests with Playwright"
63
+ @uv run npm run build
64
+ @uv run --directory=ui-tests jlpm playwright test -u --reporter=list
@@ -1,15 +1,26 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calkit-python
3
- Version: 0.32.11
3
+ Version: 0.33.1
4
4
  Summary: Reproducibility simplified.
5
5
  Project-URL: Homepage, https://calkit.org
6
6
  Project-URL: Issues, https://github.com/calkit/calkit/issues
7
7
  Project-URL: Repository, https://github.com/calkit/calkit
8
8
  Author-email: Pete Bachant <petebachant@gmail.com>
9
9
  License-File: LICENSE
10
+ Classifier: Framework :: Jupyter
11
+ Classifier: Framework :: Jupyter :: JupyterLab
12
+ Classifier: Framework :: Jupyter :: JupyterLab :: 4
13
+ Classifier: Framework :: Jupyter :: JupyterLab :: Extensions
14
+ Classifier: Framework :: Jupyter :: JupyterLab :: Extensions :: Prebuilt
10
15
  Classifier: License :: OSI Approved :: MIT License
11
16
  Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
12
18
  Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Programming Language :: Python :: 3.14
13
24
  Requires-Python: >=3.10
14
25
  Requires-Dist: arithmeval
15
26
  Requires-Dist: bibtexparser
@@ -34,7 +45,7 @@ Requires-Dist: pywin32; platform_system == 'Windows'
34
45
  Requires-Dist: requests
35
46
  Requires-Dist: sqlitedict>=2.1.0
36
47
  Requires-Dist: tqdm>=4.67.1
37
- Requires-Dist: typer==0.20.0
48
+ Requires-Dist: typer==0.21.1
38
49
  Requires-Dist: uvicorn
39
50
  Provides-Extra: data
40
51
  Requires-Dist: pandas>=2.2.3; extra == 'data'
@@ -0,0 +1 @@
1
+ module.exports = require("@jupyterlab/testutils/lib/babel.config");
@@ -0,0 +1,49 @@
1
+ __version__ = "0.33.1"
2
+
3
+ from .core import * # noqa: F403, I001
4
+ from . import git # noqa: F401
5
+ from . import dvc # noqa: F401
6
+ from . import cloud # noqa: F401
7
+ from . import jupyter # noqa: F401
8
+ from . import config # noqa: F401
9
+ from . import models # noqa: F401
10
+ from . import office # noqa: F401
11
+ from . import templates # noqa: F401
12
+ from . import conda # noqa: F401
13
+ from . import calc # noqa: F401
14
+ from . import check # noqa: F401
15
+ from . import github # noqa: F401
16
+ from . import invenio # noqa: F401
17
+ from . import releases # noqa: F401
18
+ from . import licenses # noqa: F401
19
+ from . import overleaf # noqa: F401
20
+ from .notebooks import declare_notebook # noqa: F401
21
+ from .jupyterlab.routes import setup_route_handlers
22
+
23
+
24
+ def _jupyter_labextension_paths():
25
+ return [{"src": "labextension", "dest": "calkit"}]
26
+
27
+
28
+ def _jupyter_server_extension_points():
29
+ return [{"module": "calkit"}]
30
+
31
+
32
+ def _load_jupyter_server_extension(server_app):
33
+ """Registers the API handler to receive HTTP requests from the frontend
34
+ extension.
35
+
36
+ Parameters
37
+ ----------
38
+ server_app: jupyterlab.labapp.LabApp
39
+ JupyterLab application instance
40
+ """
41
+ import os
42
+
43
+ # Change to root_dir so all handlers work in the correct directory context
44
+ root_dir = server_app.root_dir
45
+ os.chdir(root_dir)
46
+ server_app.log.info(f"Changed working directory to {root_dir}")
47
+ setup_route_handlers(server_app.web_app)
48
+ name = "calkit"
49
+ server_app.log.info(f"Registered {name} server extension")
@@ -3,6 +3,8 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import base64
6
+ import fnmatch
7
+ import json
6
8
  import os
7
9
  import subprocess
8
10
  import sys
@@ -15,7 +17,9 @@ import typer
15
17
  from tqdm import tqdm
16
18
 
17
19
  import calkit
20
+ import calkit.invenio
18
21
  from calkit.cli import raise_error
22
+ from calkit.models.core import _ImportedFromProject
19
23
 
20
24
  import_app = typer.Typer(no_args_is_help=True)
21
25
 
@@ -32,11 +36,11 @@ def import_dataset(
32
36
  ),
33
37
  ],
34
38
  dest_path: Annotated[
35
- str,
39
+ str | None,
36
40
  typer.Argument(help="Output path at which to save."),
37
41
  ] = None,
38
42
  filter_paths: Annotated[
39
- list[str],
43
+ list[str] | None,
40
44
  typer.Option(
41
45
  "--filter-paths",
42
46
  help="Filter paths in target dataset if it's a folder.",
@@ -186,7 +190,7 @@ def import_dataset(
186
190
  title=resp.get("title"),
187
191
  description=resp.get("description"),
188
192
  stage=None,
189
- imported_from=calkit.models._ImportedFromProject(
193
+ imported_from=_ImportedFromProject(
190
194
  project=f"{owner_name}/{project_name}",
191
195
  path=path,
192
196
  git_rev=resp.get("git_rev"),
@@ -301,3 +305,196 @@ def import_environment(
301
305
  repo.git.add("calkit.yaml")
302
306
  if not no_commit and calkit.git.get_staged_files():
303
307
  repo.git.commit(["-m", f"Import environment {src}"])
308
+
309
+
310
+ @import_app.command(name="zenodo")
311
+ def import_from_zenodo(
312
+ src: Annotated[str, typer.Argument(help="Source URL or DOI.")],
313
+ dest_dir: Annotated[
314
+ str,
315
+ typer.Argument(
316
+ help="Destination folder. Will be created if it doesn't exist"
317
+ ),
318
+ ],
319
+ kind: Annotated[
320
+ str | None,
321
+ typer.Option(
322
+ "--kind",
323
+ "-k",
324
+ help=(
325
+ "What kind of artifact is being imported, "
326
+ "e.g., a figure, dataset, publication."
327
+ ),
328
+ ),
329
+ ] = None,
330
+ name_like: Annotated[
331
+ list[str],
332
+ typer.Option(
333
+ "--name-like",
334
+ help="Filter for file names like this. Glob patterns accepted.",
335
+ ),
336
+ ] = [],
337
+ name_not_like: Annotated[
338
+ list[str],
339
+ typer.Option(
340
+ "--name-not-like",
341
+ help="Exclude names matching pattern.",
342
+ ),
343
+ ] = [],
344
+ storage: Annotated[
345
+ str | None,
346
+ typer.Option(
347
+ "--storage",
348
+ help="Storage backend to use (Git or DVC). "
349
+ "If not specified, will be chosen based on size.",
350
+ ),
351
+ ] = None,
352
+ no_commit: Annotated[
353
+ bool,
354
+ typer.Option("--no-commit", help="Do not commit changes to project."),
355
+ ] = False,
356
+ ):
357
+ """Import files from a Zenodo record."""
358
+ # Ensure destination directory either doesn't exist or is empty
359
+ if os.path.isdir(dest_dir):
360
+ if os.listdir(dest_dir):
361
+ raise_error("Destination directory exists and is not empty")
362
+ if kind is not None and kind not in ["figure", "dataset", "publication"]:
363
+ raise_error(
364
+ "Invalid kind; must be one of 'figure', 'dataset', or "
365
+ "'publication'"
366
+ )
367
+ # Fetch information about the record
368
+ # First, extract the record ID from the src
369
+ if "zenodo.org/record/" in src:
370
+ try:
371
+ record_id = int(src.split("zenodo.org/record/")[1].split("/")[0])
372
+ except Exception:
373
+ raise_error("Could not parse Zenodo record ID from URL")
374
+ elif "10.5281/zenodo." in src:
375
+ try:
376
+ record_id = int(src.split("10.5281/zenodo.")[1])
377
+ except Exception:
378
+ raise_error("Could not parse Zenodo record ID from DOI")
379
+ else:
380
+ raise_error("Source must be a Zenodo URL or DOI")
381
+ typer.echo(f"Fetching info for Zenodo record {record_id}")
382
+ try:
383
+ record = calkit.invenio.get(
384
+ f"/records/{record_id}", service="zenodo", auth=False
385
+ )
386
+ except Exception as e:
387
+ raise_error(f"Could not fetch record info from Zenodo: {e}")
388
+ # Get download URLs
389
+ download_urls = calkit.invenio.get_download_urls(
390
+ record_id, service="zenodo", auth=False
391
+ )
392
+ # Filter download URLs
393
+ filtered_urls = {}
394
+ for fname, url in download_urls.items():
395
+ if name_like:
396
+ if not any(
397
+ fnmatch.fnmatch(fname, pattern) for pattern in name_like
398
+ ):
399
+ continue
400
+ if name_not_like:
401
+ if any(
402
+ fnmatch.fnmatch(fname, pattern) for pattern in name_not_like
403
+ ):
404
+ continue
405
+ filtered_urls[fname] = url
406
+ if not filtered_urls:
407
+ raise_error("No files matched the specified name filters")
408
+ # Download files
409
+ for fname, url in filtered_urls.items():
410
+ out_path = os.path.join(dest_dir, fname) # fname may include subdirs
411
+ os.makedirs(os.path.dirname(out_path), exist_ok=True)
412
+ typer.echo(f"Downloading {fname} to {out_path}")
413
+ resp = requests.get(url, stream=True)
414
+ try:
415
+ resp.raise_for_status()
416
+ except Exception as e:
417
+ raise_error(f"Failed to download {fname} from {url}: {e}")
418
+ with open(out_path, "wb") as f:
419
+ for chunk in resp.iter_content(chunk_size=8192):
420
+ f.write(chunk)
421
+ # Decide if this should be stored in Git or DVC
422
+ repo = git.Repo()
423
+ commit_paths = []
424
+ if storage is None:
425
+ if calkit.get_size(dest_dir) > calkit.DVC_SIZE_THRESH_BYTES:
426
+ res = subprocess.run(
427
+ [sys.executable, "-m", "dvc", "add"], check=False
428
+ )
429
+ if res.returncode != 0:
430
+ raise_error("Failed to DVC add")
431
+ # Git add the .dvc file
432
+ dvc_file = dest_dir + ".dvc"
433
+ repo.git.add(dvc_file)
434
+ commit_paths.append(dvc_file)
435
+ else:
436
+ repo.git.add(dest_dir)
437
+ commit_paths.append(dest_dir)
438
+ elif storage.lower() == "dvc":
439
+ res = subprocess.run(
440
+ [sys.executable, "-m", "dvc", "add", dest_dir], check=False
441
+ )
442
+ if res.returncode != 0:
443
+ raise_error("Failed to DVC add")
444
+ # Git add the .dvc file
445
+ dvc_file = dest_dir + ".dvc"
446
+ repo.git.add(dvc_file)
447
+ commit_paths.append(dvc_file)
448
+ elif storage.lower() == "git":
449
+ repo.git.add(dest_dir)
450
+ commit_paths.append(dest_dir)
451
+ else:
452
+ raise_error("Invalid storage option; must be 'git' or 'dvc'")
453
+ # Determine if we should put this in one of the calkit.yaml categories
454
+ if kind is not None:
455
+ ck_info = calkit.load_calkit_info()
456
+ items = ck_info.get(kind + "s", [])
457
+ item_record = {
458
+ "path": dest_dir,
459
+ "imported_from": {
460
+ "doi": record.get("doi"),
461
+ },
462
+ "title": record.get("metadata", {}).get("title"),
463
+ }
464
+ items.append(item_record)
465
+ ck_info[kind + "s"] = items
466
+ with open("calkit.yaml", "w") as f:
467
+ calkit.ryaml.dump(ck_info, f)
468
+ commit_paths.append("calkit.yaml")
469
+ # Save a record of this import in .calkit/imports.json
470
+ import_record = {
471
+ "from": "zenodo",
472
+ "record_id": record_id,
473
+ "src": src,
474
+ "dest_dir": dest_dir,
475
+ "timestamp": calkit.utcnow(),
476
+ "kind": kind,
477
+ "storage": storage,
478
+ "name_like": name_like,
479
+ "name_not_like": name_not_like,
480
+ }
481
+ os.makedirs(".calkit", exist_ok=True)
482
+ imports_fpath = os.path.join(".calkit", "imports.json")
483
+ commit_paths.append(imports_fpath)
484
+ if os.path.isfile(imports_fpath):
485
+ with open(imports_fpath) as f:
486
+ imports = json.load(f)
487
+ else:
488
+ imports = []
489
+ imports.append(import_record)
490
+ with open(imports_fpath, "w") as f:
491
+ json.dump(imports, f, indent=2)
492
+ # Commit if desired
493
+ if not no_commit:
494
+ repo = git.Repo()
495
+ repo.git.add(commit_paths)
496
+ if repo.git.diff(commit_paths + ["--staged"]):
497
+ repo.git.commit(
498
+ commit_paths
499
+ + ["-m", f"Import {src} from Zenodo to {dest_dir}"]
500
+ )
@@ -27,6 +27,13 @@ from typing_extensions import Annotated, Optional
27
27
  import calkit
28
28
  import calkit.matlab
29
29
  import calkit.pipeline
30
+ from calkit import (
31
+ AUTO_IGNORE_PATHS,
32
+ AUTO_IGNORE_PREFIXES,
33
+ AUTO_IGNORE_SUFFIXES,
34
+ DVC_EXTENSIONS,
35
+ DVC_SIZE_THRESH_BYTES,
36
+ )
30
37
  from calkit.cli import print_sep, raise_error, run_cmd, warn
31
38
  from calkit.cli.check import (
32
39
  check_app,
@@ -76,46 +83,6 @@ app.add_typer(overleaf_app, name="overleaf", help="Interact with Overleaf.")
76
83
  app.add_typer(cloud_app, name="cloud", help="Interact with a Calkit Cloud.")
77
84
  app.add_typer(slurm_app, name="slurm", help="Work with SLURM.")
78
85
 
79
- # Constants for version control auto-ignore
80
- AUTO_IGNORE_SUFFIXES = [
81
- ".DS_Store",
82
- ".env",
83
- ".pyc",
84
- ".synctex.gz",
85
- ".ipynb_checkpoints",
86
- ]
87
- AUTO_IGNORE_PATHS = [os.path.join(".dvc", "config.local")]
88
- AUTO_IGNORE_PREFIXES = [
89
- ".venv",
90
- "__pycache__",
91
- ".ipynb_checkpoints",
92
- ".calkit/overleaf/",
93
- ]
94
- # Constants for version control auto-add to DVC
95
- DVC_EXTENSIONS = [
96
- ".png",
97
- ".jpeg",
98
- ".jpg",
99
- ".gif",
100
- ".h5",
101
- ".parquet",
102
- ".pickle",
103
- ".mp4",
104
- ".avi",
105
- ".webm",
106
- ".pdf",
107
- ".xlsx",
108
- ".docx",
109
- ".pptx",
110
- ".xls",
111
- ".doc",
112
- ".ppt",
113
- ".nc",
114
- ".nc4",
115
- ".zarr",
116
- ]
117
- DVC_SIZE_THRESH_BYTES = 1_000_000
118
-
119
86
 
120
87
  def _to_shell_cmd(cmd: list[str]) -> str:
121
88
  """Join a command to be compatible with running at the shell.
@@ -891,9 +858,9 @@ def _stage_run_info_from_log_content(log_content: str) -> dict:
891
858
 
892
859
  @app.command(name="run")
893
860
  def run(
894
- targets: Optional[list[str]] = typer.Argument(
895
- default=None, help="Stages to run."
896
- ),
861
+ targets: Annotated[
862
+ list[str] | None, typer.Argument(help="Stages to run.")
863
+ ] = None,
897
864
  quiet: Annotated[
898
865
  bool, typer.Option("-q", "--quiet", help="Be quiet.")
899
866
  ] = False,
@@ -993,9 +960,11 @@ def run(
993
960
  no_run_cache: Annotated[
994
961
  bool, typer.Option("--no-run-cache", help="Ignore the run cache.")
995
962
  ] = False,
996
- save_log: Annotated[
963
+ save_logs: Annotated[
997
964
  bool,
998
- typer.Option("--log", "-l", help="Log the run."),
965
+ typer.Option(
966
+ "--log", "-l", help="Log the run and system information."
967
+ ),
999
968
  ] = False,
1000
969
  save_after_run: Annotated[
1001
970
  bool,
@@ -1031,7 +1000,7 @@ def run(
1031
1000
  help="Sync with Overleaf before and after running.",
1032
1001
  ),
1033
1002
  ] = False,
1034
- ):
1003
+ ) -> dict:
1035
1004
  """Check dependencies and run the pipeline."""
1036
1005
  import dvc.log
1037
1006
  import dvc.repo
@@ -1059,7 +1028,7 @@ def run(
1059
1028
  typer.echo("Getting system information")
1060
1029
  # Get system information
1061
1030
  system_info = calkit.get_system_info()
1062
- if save_log:
1031
+ if save_logs:
1063
1032
  # Save the system to .calkit/systems
1064
1033
  if verbose:
1065
1034
  typer.echo("Saving system information:")
@@ -1144,7 +1113,7 @@ def run(
1144
1113
  targets.append(dvc_stage_name)
1145
1114
  if not targets:
1146
1115
  raise_error("No stages found to run")
1147
- if save_log:
1116
+ if save_logs:
1148
1117
  # Get status of Git repo before running
1149
1118
  repo = git.Repo()
1150
1119
  git_rev = repo.head.commit.hexsha
@@ -1191,35 +1160,37 @@ def run(
1191
1160
  start_time_no_tz = calkit.utcnow(remove_tz=True)
1192
1161
  start_time = calkit.utcnow(remove_tz=False)
1193
1162
  run_id = uuid.uuid4().hex
1194
- if save_log:
1195
- log_fpath = os.path.join(
1196
- ".calkit",
1197
- "logs",
1198
- start_time_no_tz.isoformat(timespec="seconds").replace(":", "-")
1199
- + "-"
1200
- + run_id
1201
- + ".log",
1202
- )
1203
- if verbose:
1204
- typer.echo(f"Starting run ID: {run_id}")
1205
- typer.echo(f"Saving logs to {log_fpath}")
1206
- os.makedirs(os.path.dirname(log_fpath), exist_ok=True)
1207
- # Create a file handler for dvc.stage.run logger
1208
- file_handler = logging.FileHandler(log_fpath, mode="w")
1209
- file_handler.setLevel(logging.DEBUG)
1210
- formatter = logging.Formatter(
1211
- "%(asctime)s - %(levelname)s - %(message)s"
1212
- )
1213
- formatter.converter = time.gmtime # Use UTC time for asctime
1214
- file_handler.setFormatter(formatter)
1215
- dvc.log.logger.addHandler(file_handler)
1163
+ # Always log output, but only save systems/run data if specified
1164
+ log_fpath = os.path.join(
1165
+ ".calkit",
1166
+ "logs",
1167
+ start_time_no_tz.isoformat(timespec="seconds").replace(":", "-")
1168
+ + "-"
1169
+ + run_id
1170
+ + ".log",
1171
+ )
1172
+ if verbose:
1173
+ typer.echo(f"Starting run ID: {run_id}")
1174
+ typer.echo(f"Saving logs to {log_fpath}")
1175
+ os.makedirs(os.path.dirname(log_fpath), exist_ok=True)
1176
+ # Create a file handler for dvc.stage.run logger
1177
+ file_handler = logging.FileHandler(log_fpath, mode="w")
1178
+ file_handler.setLevel(logging.DEBUG)
1179
+ formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
1180
+ formatter.converter = time.gmtime # Use UTC time for asctime
1181
+ file_handler.setFormatter(formatter)
1182
+ dvc.log.logger.addHandler(file_handler)
1216
1183
  # Remove newline logging in dvc.repo.reproduce
1217
1184
  dvc.repo.reproduce.logger.setLevel(logging.ERROR)
1218
1185
  # Disable other misc DVC output
1219
1186
  dvc.ui.ui.write = lambda *args, **kwargs: None
1220
1187
  res = dvc_cli_main(["repro"] + args)
1221
1188
  failed = res != 0
1222
- if save_log:
1189
+ # Parse log to get timing
1190
+ with open(log_fpath, "r") as f:
1191
+ log_content = f.read()
1192
+ stage_run_info = _stage_run_info_from_log_content(log_content)
1193
+ if save_logs:
1223
1194
  # Get Git status after running
1224
1195
  git_changed_files_after = calkit.git.get_changed_files(repo=repo)
1225
1196
  git_staged_files_after = calkit.git.get_staged_files(repo=repo)
@@ -1228,10 +1199,6 @@ def run(
1228
1199
  dvc_status_after = dvc_repo.status()
1229
1200
  dvc_data_status_after = dvc_repo.data_status()
1230
1201
  dvc_data_status_after.pop("git", None) # Remove git status
1231
- # Parse log to get timing
1232
- with open(log_fpath, "r") as f:
1233
- log_content = f.read()
1234
- stage_run_info = _stage_run_info_from_log_content(log_content)
1235
1202
  # Save run information to a file
1236
1203
  if verbose:
1237
1204
  typer.echo("Saving run info")
@@ -1269,6 +1236,8 @@ def run(
1269
1236
  os.makedirs(os.path.dirname(run_info_fpath), exist_ok=True)
1270
1237
  with open(run_info_fpath, "w") as f:
1271
1238
  json.dump(run_info, f, indent=2)
1239
+ else:
1240
+ os.remove(log_fpath)
1272
1241
  os.environ.pop("CALKIT_PIPELINE_RUNNING", None)
1273
1242
  if failed:
1274
1243
  raise_error("Pipeline failed")
@@ -1291,6 +1260,7 @@ def run(
1291
1260
  no_commit=False,
1292
1261
  no_push=not save_after_run,
1293
1262
  )
1263
+ return {"dvc_stages": dvc_stages, "stage_run_info": stage_run_info}
1294
1264
 
1295
1265
 
1296
1266
  @app.command(name="manual-step", help="Execute a manual step.")
@@ -1246,7 +1246,7 @@ def new_uv_venv(
1246
1246
  ] = ".venv",
1247
1247
  python_version: Annotated[
1248
1248
  str | None, typer.Option("--python", "-p", help="Python version.")
1249
- ] = "3.13",
1249
+ ] = "3.14",
1250
1250
  description: Annotated[
1251
1251
  str | None, typer.Option("--description", help="Description.")
1252
1252
  ] = None,
@@ -1274,7 +1274,6 @@ def new_uv_venv(
1274
1274
  raise_error("Output path already exists (use -f to overwrite)")
1275
1275
  elif packages is None and not os.path.isfile(path):
1276
1276
  raise_error("If path doesn't exist, packages must be specified")
1277
- repo = git.Repo()
1278
1277
  # Add environment to Calkit info
1279
1278
  ck_info = calkit.load_calkit_info()
1280
1279
  # If environments is a list instead of a dict, reformulate it
@@ -1301,7 +1300,6 @@ def new_uv_venv(
1301
1300
  _check_path_dir(path)
1302
1301
  with open(path, "w") as f:
1303
1302
  f.write(packages_txt)
1304
- repo.git.add(path)
1305
1303
  typer.echo("Adding environment to calkit.yaml")
1306
1304
  env = dict(path=path, kind="uv-venv", prefix=prefix)
1307
1305
  if python_version is not None:
@@ -1312,10 +1310,13 @@ def new_uv_venv(
1312
1310
  ck_info["environments"] = envs
1313
1311
  with open("calkit.yaml", "w") as f:
1314
1312
  ryaml.dump(ck_info, f)
1315
- repo.git.add("calkit.yaml")
1313
+ if not no_commit:
1314
+ repo = git.Repo()
1315
+ repo.git.add(path)
1316
+ repo.git.add("calkit.yaml")
1316
1317
  if not no_check:
1317
1318
  env_lock_fpath = check_environment(env_name=name)
1318
- if env_lock_fpath is not None:
1319
+ if env_lock_fpath is not None and not no_commit:
1319
1320
  repo.git.add(env_lock_fpath)
1320
1321
  if not no_commit and repo.git.diff("--staged"):
1321
1322
  repo.git.commit(["-m", f"Add uv venv {name}"])