calkit-python 0.35.2__tar.gz → 0.35.4__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 (284) hide show
  1. {calkit_python-0.35.2 → calkit_python-0.35.4}/.gitignore +2 -0
  2. {calkit_python-0.35.2 → calkit_python-0.35.4}/PKG-INFO +1 -1
  3. calkit_python-0.35.4/calkit/cli/main/__init__.py +2 -0
  4. calkit_python-0.35.2/calkit/cli/main.py → calkit_python-0.35.4/calkit/cli/main/core.py +5 -497
  5. calkit_python-0.35.4/calkit/cli/main/xr.py +680 -0
  6. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/detect.py +29 -5
  7. calkit_python-0.35.4/calkit/docker.py +470 -0
  8. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/environments.py +10 -0
  9. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/git.py +42 -4
  10. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/models/pipeline.py +1 -0
  11. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/overleaf.py +73 -14
  12. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/pipeline.py +1 -0
  13. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/releases.py +1 -1
  14. calkit_python-0.35.2/calkit/tests/cli/test_main.py → calkit_python-0.35.4/calkit/tests/cli/main/test_core.py +19 -601
  15. calkit_python-0.35.4/calkit/tests/cli/main/test_xr.py +726 -0
  16. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_overleaf.py +39 -0
  17. calkit_python-0.35.4/calkit/tests/models/__init__.py +0 -0
  18. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_detect.py +8 -0
  19. calkit_python-0.35.4/calkit/tests/test_docker.py +70 -0
  20. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_git.py +51 -0
  21. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_pipeline.py +6 -0
  22. calkit_python-0.35.4/calkit/tests/test_releases.py +44 -0
  23. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/pipeline/index.md +58 -0
  24. {calkit_python-0.35.2 → calkit_python-0.35.4}/uv.lock +3 -3
  25. calkit_python-0.35.2/calkit/docker.py +0 -69
  26. {calkit_python-0.35.2 → calkit_python-0.35.4}/.pre-commit-config.yaml +0 -0
  27. {calkit_python-0.35.2 → calkit_python-0.35.4}/.prettierignore +0 -0
  28. {calkit_python-0.35.2 → calkit_python-0.35.4}/.python-version +0 -0
  29. {calkit_python-0.35.2 → calkit_python-0.35.4}/.yarnrc.yml +0 -0
  30. {calkit_python-0.35.2 → calkit_python-0.35.4}/CITATION.cff +0 -0
  31. {calkit_python-0.35.2 → calkit_python-0.35.4}/CODE_OF_CONDUCT.md +0 -0
  32. {calkit_python-0.35.2 → calkit_python-0.35.4}/CONTRIBUTING.md +0 -0
  33. {calkit_python-0.35.2 → calkit_python-0.35.4}/LICENSE +0 -0
  34. {calkit_python-0.35.2 → calkit_python-0.35.4}/Makefile +0 -0
  35. {calkit_python-0.35.2 → calkit_python-0.35.4}/README.md +0 -0
  36. {calkit_python-0.35.2 → calkit_python-0.35.4}/babel.config.js +0 -0
  37. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/__init__.py +0 -0
  38. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/__main__.py +0 -0
  39. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/calc.py +0 -0
  40. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/check.py +0 -0
  41. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/__init__.py +0 -0
  42. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/check.py +0 -0
  43. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/cloud.py +0 -0
  44. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/config.py +0 -0
  45. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/core.py +0 -0
  46. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/describe.py +0 -0
  47. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/import_.py +0 -0
  48. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/latex.py +0 -0
  49. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/list.py +0 -0
  50. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/new.py +0 -0
  51. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/notebooks.py +0 -0
  52. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/office.py +0 -0
  53. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/overleaf.py +0 -0
  54. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/slurm.py +0 -0
  55. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cli/update.py +0 -0
  56. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/cloud.py +0 -0
  57. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/conda.py +0 -0
  58. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/config.py +0 -0
  59. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/core.py +0 -0
  60. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/datasets.py +0 -0
  61. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/dvc.py +0 -0
  62. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/fs.py +0 -0
  63. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/github.py +0 -0
  64. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/gui.py +0 -0
  65. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/invenio.py +0 -0
  66. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/julia.py +0 -0
  67. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/jupyter.py +0 -0
  68. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/jupyterlab/__init__.py +0 -0
  69. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/jupyterlab/routes.py +0 -0
  70. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/package.json +0 -0
  71. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/schemas/calkit/package.json.orig +0 -0
  72. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/schemas/calkit/plugin.json +0 -0
  73. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
  74. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
  75. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
  76. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/909.651be47ca47390b78a92.js +0 -0
  77. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
  78. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
  79. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
  80. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/remoteEntry.c091821b3d7f2d287a67.js +0 -0
  81. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/style.js +0 -0
  82. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/labextension/static/third-party-licenses.json +0 -0
  83. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/licenses.py +0 -0
  84. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/magics.py +0 -0
  85. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/matlab.py +0 -0
  86. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/models/__init__.py +0 -0
  87. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/models/core.py +0 -0
  88. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/models/io.py +0 -0
  89. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/models/iteration.py +0 -0
  90. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/notebooks.py +0 -0
  91. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/office.py +0 -0
  92. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/ops.py +0 -0
  93. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/server.py +0 -0
  94. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/__init__.py +0 -0
  95. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/core.py +0 -0
  96. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/__init__.py +0 -0
  97. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/article/paper.tex +0 -0
  98. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/core.py +0 -0
  99. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/jfm/jfm.bst +0 -0
  100. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/jfm/jfm.cls +0 -0
  101. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
  102. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/jfm/paper.tex +0 -0
  103. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/templates/latex/jfm/upmath.sty +0 -0
  104. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/__init__.py +0 -0
  105. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/__init__.py +0 -0
  106. {calkit_python-0.35.2/calkit/tests/jupyterlab → calkit_python-0.35.4/calkit/tests/cli/main}/__init__.py +0 -0
  107. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_check.py +0 -0
  108. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_config.py +0 -0
  109. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_import.py +0 -0
  110. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_latex.py +0 -0
  111. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_list.py +0 -0
  112. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_new.py +0 -0
  113. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/cli/test_notebooks.py +0 -0
  114. {calkit_python-0.35.2/calkit/tests/models → calkit_python-0.35.4/calkit/tests/jupyterlab}/__init__.py +0 -0
  115. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/jupyterlab/test_routes.py +0 -0
  116. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/models/test_iteration.py +0 -0
  117. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/models/test_pipeline.py +0 -0
  118. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_calc.py +0 -0
  119. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_check.py +0 -0
  120. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_conda.py +0 -0
  121. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_core.py +0 -0
  122. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_dvc.py +0 -0
  123. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_environments.py +0 -0
  124. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_fs.py +0 -0
  125. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_invenio.py +0 -0
  126. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_julia.py +0 -0
  127. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_jupyter.py +0 -0
  128. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_magics.py +0 -0
  129. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_matlab.py +0 -0
  130. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_notebooks.py +0 -0
  131. {calkit_python-0.35.2 → calkit_python-0.35.4}/calkit/tests/test_templates.py +0 -0
  132. {calkit_python-0.35.2 → calkit_python-0.35.4}/conftest.py +0 -0
  133. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/CNAME +0 -0
  134. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/apps.md +0 -0
  135. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/calculations.md +0 -0
  136. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/calkit-yaml.md +0 -0
  137. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/cli-reference.md +0 -0
  138. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/cloud-integration.md +0 -0
  139. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/datasets.md +0 -0
  140. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/dependencies.md +0 -0
  141. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/environments.md +0 -0
  142. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/examples.md +0 -0
  143. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/governance.md +0 -0
  144. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/help.md +0 -0
  145. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/c-to-the-k-white.svg +0 -0
  146. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/calkit-fragmentation-compendium.png +0 -0
  147. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/calkit-no-bg.png +0 -0
  148. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/connect-zenodo.png +0 -0
  149. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/jupyterlab/all-green.png +0 -0
  150. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/jupyterlab/collect-data-stale.png +0 -0
  151. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/jupyterlab/new-env.png +0 -0
  152. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/jupyterlab/new-notebook.png +0 -0
  153. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/jupyterlab/pipeline-badge.png +0 -0
  154. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/jupyterlab-params.png +0 -0
  155. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/plos-osi-code-2024-03.png +0 -0
  156. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/img/vscode-nb-params.png +0 -0
  157. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/index.md +0 -0
  158. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/installation.md +0 -0
  159. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/jupyterlab.md +0 -0
  160. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/local-server.md +0 -0
  161. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/notebooks.md +0 -0
  162. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/overleaf.md +0 -0
  163. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/pipeline/manual-steps.md +0 -0
  164. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/pipeline/running-and-logging.md +0 -0
  165. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/pipeline/slurm.md +0 -0
  166. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/quickstart.md +0 -0
  167. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/references.md +0 -0
  168. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/releases.md +0 -0
  169. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/reproducibility.md +0 -0
  170. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/adding-latex-pub-docker.md +0 -0
  171. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/conda-envs.md +0 -0
  172. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/existing-project.md +0 -0
  173. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/first-project.md +0 -0
  174. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/github-actions.md +0 -0
  175. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/actions-repo-secrets.png +0 -0
  176. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
  177. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
  178. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
  179. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
  180. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
  181. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
  182. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
  183. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
  184. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
  185. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
  186. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/push.png +0 -0
  187. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
  188. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
  189. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/chart-more-rows.png +0 -0
  190. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/create-project.png +0 -0
  191. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
  192. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/excel-chart.png +0 -0
  193. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/excel-data.png +0 -0
  194. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
  195. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/needs-clone.png +0 -0
  196. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/new-stage.png +0 -0
  197. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
  198. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
  199. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/status-more-rows.png +0 -0
  200. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
  201. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/untracked-data.png +0 -0
  202. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/updated-publication.png +0 -0
  203. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
  204. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/office/workflow-page.png +0 -0
  205. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/clone.png +0 -0
  206. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/create-project.png +0 -0
  207. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
  208. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
  209. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
  210. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/new-token.png +0 -0
  211. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/reclone.png +0 -0
  212. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
  213. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/quick-actions.png +0 -0
  214. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/img/run-proc.png +0 -0
  215. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/index.md +0 -0
  216. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/jupyterlab.md +0 -0
  217. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/latex-codespaces.md +0 -0
  218. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/matlab.md +0 -0
  219. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/notebook-pipeline.md +0 -0
  220. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/office.md +0 -0
  221. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/openfoam.md +0 -0
  222. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/tutorials/procedures.md +0 -0
  223. {calkit_python-0.35.2 → calkit_python-0.35.4}/docs/version-control.md +0 -0
  224. {calkit_python-0.35.2 → calkit_python-0.35.4}/install.json +0 -0
  225. {calkit_python-0.35.2 → calkit_python-0.35.4}/jest.config.js +0 -0
  226. {calkit_python-0.35.2 → calkit_python-0.35.4}/jupyter-config/server-config/calkit.json +0 -0
  227. {calkit_python-0.35.2 → calkit_python-0.35.4}/mkdocs.yml +0 -0
  228. {calkit_python-0.35.2 → calkit_python-0.35.4}/package.json +0 -0
  229. {calkit_python-0.35.2 → calkit_python-0.35.4}/pyproject.toml +0 -0
  230. {calkit_python-0.35.2 → calkit_python-0.35.4}/schema/plugin.json +0 -0
  231. {calkit_python-0.35.2 → calkit_python-0.35.4}/scripts/install.ps1 +0 -0
  232. {calkit_python-0.35.2 → calkit_python-0.35.4}/scripts/install.sh +0 -0
  233. {calkit_python-0.35.2 → calkit_python-0.35.4}/scripts/make-calk9.sh +0 -0
  234. {calkit_python-0.35.2 → calkit_python-0.35.4}/scripts/sync-docs.py +0 -0
  235. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/__tests__/useQueries.spec.ts +0 -0
  236. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/calkit-config.ts +0 -0
  237. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/cell-output-marker.ts +0 -0
  238. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/commit-dialog.tsx +0 -0
  239. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/environment-editor.tsx +0 -0
  240. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/notebook-registration.tsx +0 -0
  241. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/notebook-toolbar.tsx +0 -0
  242. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/pipeline-status-bar.tsx +0 -0
  243. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/project-info-editor.tsx +0 -0
  244. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/sidebar-settings.tsx +0 -0
  245. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/sidebar.tsx +0 -0
  246. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/components/stage-editor.tsx +0 -0
  247. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/feature-flags.ts +0 -0
  248. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/file-browser-menu.ts +0 -0
  249. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/hooks/__tests__/useQueries.test.tsx +0 -0
  250. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/hooks/useQueries.ts +0 -0
  251. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/icons.ts +0 -0
  252. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/index.ts +0 -0
  253. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/io-tracker.ts +0 -0
  254. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/pipeline-state.ts +0 -0
  255. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/queryClient.ts +0 -0
  256. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/request.ts +0 -0
  257. {calkit_python-0.35.2 → calkit_python-0.35.4}/src/shims-mainmenu.d.ts +0 -0
  258. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/base.css +0 -0
  259. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/cell-output-marker.css +0 -0
  260. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/environment-editor.css +0 -0
  261. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/environment-selector.css +0 -0
  262. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/img/calkit-no-bg.png +0 -0
  263. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/index.css +0 -0
  264. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/index.js +0 -0
  265. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/notebook-toolbar.css +0 -0
  266. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/pipeline-status-bar.css +0 -0
  267. {calkit_python-0.35.2 → calkit_python-0.35.4}/style/sidebar.css +0 -0
  268. {calkit_python-0.35.2 → calkit_python-0.35.4}/test/dvc-md5-dir/osx-arm64.txt +0 -0
  269. {calkit_python-0.35.2 → calkit_python-0.35.4}/test/nb-julia.ipynb +0 -0
  270. {calkit_python-0.35.2 → calkit_python-0.35.4}/test/nb-params.ipynb +0 -0
  271. {calkit_python-0.35.2 → calkit_python-0.35.4}/test/nb-subdir.ipynb +0 -0
  272. {calkit_python-0.35.2 → calkit_python-0.35.4}/test/pipeline.ipynb +0 -0
  273. {calkit_python-0.35.2 → calkit_python-0.35.4}/test/script.py +0 -0
  274. {calkit_python-0.35.2 → calkit_python-0.35.4}/test/test-log.log +0 -0
  275. {calkit_python-0.35.2 → calkit_python-0.35.4}/tsconfig.json +0 -0
  276. {calkit_python-0.35.2 → calkit_python-0.35.4}/tsconfig.test.json +0 -0
  277. {calkit_python-0.35.2 → calkit_python-0.35.4}/ui-tests/.gitignore +0 -0
  278. {calkit_python-0.35.2 → calkit_python-0.35.4}/ui-tests/README.md +0 -0
  279. {calkit_python-0.35.2 → calkit_python-0.35.4}/ui-tests/jupyter_server_test_config.py +0 -0
  280. {calkit_python-0.35.2 → calkit_python-0.35.4}/ui-tests/package.json +0 -0
  281. {calkit_python-0.35.2 → calkit_python-0.35.4}/ui-tests/playwright.config.js +0 -0
  282. {calkit_python-0.35.2 → calkit_python-0.35.4}/ui-tests/tests/calkit.spec.ts +0 -0
  283. {calkit_python-0.35.2 → calkit_python-0.35.4}/ui-tests/yarn.lock +0 -0
  284. {calkit_python-0.35.2 → calkit_python-0.35.4}/yarn.lock +0 -0
@@ -17,3 +17,5 @@ coverage
17
17
  junit.xml
18
18
  calk9
19
19
  dist
20
+ *.vsix
21
+ vscode-ext/out
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calkit-python
3
- Version: 0.35.2
3
+ Version: 0.35.4
4
4
  Summary: Reproducibility simplified.
5
5
  Project-URL: Homepage, https://calkit.org
6
6
  Project-URL: Issues, https://github.com/calkit/calkit/issues
@@ -0,0 +1,2 @@
1
+ from . import xr # noqa: F401
2
+ from .core import * # noqa: F403
@@ -1,4 +1,4 @@
1
- """Main CLI app."""
1
+ """Core functionality in the main namespace of the CLI."""
2
2
 
3
3
  from __future__ import annotations
4
4
 
@@ -1325,10 +1325,11 @@ def run(
1325
1325
  if failed:
1326
1326
  raise_error("Pipeline failed")
1327
1327
  else:
1328
+ _enc = sys.stdout.encoding or "utf-8"
1328
1329
  typer.echo(
1329
1330
  "Pipeline completed successfully ✅".encode(
1330
- "utf-8", errors="replace"
1331
- )
1331
+ _enc, errors="replace"
1332
+ ).decode(_enc)
1332
1333
  )
1333
1334
  if save_after_run or save_message is not None:
1334
1335
  if save_message is None:
@@ -1888,499 +1889,6 @@ def run_in_env(
1888
1889
  raise_error("Environment kind not supported")
1889
1890
 
1890
1891
 
1891
- @app.command(name="xr")
1892
- def execute_and_record(
1893
- cmd: Annotated[
1894
- list[str],
1895
- typer.Argument(
1896
- help="Command to execute and record. "
1897
- "If the first argument is a script, notebook or LaTeX file, "
1898
- "it will be treated as a stage with that file as "
1899
- "the target. Any command, including arguments, is supported."
1900
- ),
1901
- ],
1902
- environment: Annotated[
1903
- str | None,
1904
- typer.Option(
1905
- "--environment",
1906
- "-e",
1907
- help="Name of or path the spec file for the environment to use.",
1908
- ),
1909
- ] = None,
1910
- inputs: Annotated[
1911
- list[str],
1912
- typer.Option(
1913
- "--input",
1914
- "-i",
1915
- help="Input paths to record.",
1916
- ),
1917
- ] = [],
1918
- outputs: Annotated[
1919
- list[str],
1920
- typer.Option(
1921
- "--output",
1922
- "-o",
1923
- help="Output paths to record.",
1924
- ),
1925
- ] = [],
1926
- no_detect_io: Annotated[
1927
- bool,
1928
- typer.Option(
1929
- "--no-detect-io",
1930
- help=(
1931
- "Don't attempt to detect inputs and outputs from the command, "
1932
- "script, or notebook."
1933
- ),
1934
- ),
1935
- ] = False,
1936
- stage_name: Annotated[
1937
- str | None,
1938
- typer.Option(
1939
- "--stage",
1940
- help=(
1941
- "Name of the DVC stage to create for this command. If not "
1942
- "provided, a name will be generated automatically."
1943
- ),
1944
- ),
1945
- ] = None,
1946
- dry_run: Annotated[
1947
- bool,
1948
- typer.Option(
1949
- "--dry-run",
1950
- "-d",
1951
- help=(
1952
- "Print the environment and stage that would be created "
1953
- "without modifying calkit.yaml or executing the command."
1954
- ),
1955
- ),
1956
- ] = False,
1957
- force: Annotated[
1958
- bool,
1959
- typer.Option(
1960
- "--force",
1961
- "-f",
1962
- help="Force running stage even if it's up-to-date.",
1963
- ),
1964
- ] = False,
1965
- verbose: Annotated[
1966
- bool, typer.Option("--verbose", "-v", help="Print verbose output.")
1967
- ] = False,
1968
- ):
1969
- """Execute a command and if successful, record in the pipeline."""
1970
- import io
1971
- import shlex
1972
-
1973
- from calkit.detect import (
1974
- detect_io,
1975
- generate_stage_name,
1976
- )
1977
- from calkit.environments import detect_env_for_stage
1978
- from calkit.models.io import PathOutput
1979
- from calkit.models.pipeline import (
1980
- JuliaCommandStage,
1981
- JuliaScriptStage,
1982
- JupyterNotebookStage,
1983
- LatexStage,
1984
- MatlabCommandStage,
1985
- MatlabScriptStage,
1986
- PythonScriptStage,
1987
- RScriptStage,
1988
- ShellCommandStage,
1989
- ShellScriptStage,
1990
- )
1991
- from calkit.pipeline import stages_are_similar
1992
-
1993
- def _determine_output_storage(
1994
- path: str,
1995
- repo: git.Repo | None = None,
1996
- dvc_paths: list[str] | None = None,
1997
- ) -> str:
1998
- """Determine storage type (git or dvc) for an output path.
1999
-
2000
- Parameters
2001
- ----------
2002
- path : str
2003
- Path to check.
2004
- repo : git.Repo | None
2005
- Git repository. If None, only extension and size are checked.
2006
- dvc_paths : list[str] | None
2007
- List of paths tracked by DVC.
2008
-
2009
- Returns
2010
- -------
2011
- str
2012
- "git" or "dvc".
2013
- """
2014
- if dvc_paths is None:
2015
- dvc_paths = []
2016
- # If already tracked by git, use git
2017
- if repo is not None and repo.git.ls_files(path):
2018
- return "git"
2019
- # If already tracked by dvc, use dvc
2020
- if path in dvc_paths:
2021
- return "dvc"
2022
- # Check extension
2023
- if os.path.splitext(path)[-1] in DVC_EXTENSIONS:
2024
- return "dvc"
2025
- # Check size if file exists
2026
- if os.path.exists(path):
2027
- try:
2028
- if calkit.get_size(path) > DVC_SIZE_THRESH_BYTES:
2029
- return "dvc"
2030
- except (OSError, IOError):
2031
- # If we cannot determine file size (e.g., permission
2032
- # or I/O issues), fall back to the default "git"
2033
- # behavior below.
2034
- pass
2035
- # Default to git for small/unknown files
2036
- return "git"
2037
-
2038
- # First, read the pipeline before running so we can revert if the stage
2039
- # fails
2040
- ck_info = calkit.load_calkit_info()
2041
- ck_info_orig = deepcopy(ck_info)
2042
- pipeline = ck_info.get("pipeline", {})
2043
- stages = pipeline.get("stages", {})
2044
- # Strip and detect uv/pixi run prefix
2045
- if len(cmd) >= 2 and cmd[0] == "uv" and cmd[1] == "run":
2046
- if environment is None and os.path.isfile("pyproject.toml"):
2047
- environment = "pyproject.toml"
2048
- cmd = cmd[2:]
2049
- elif len(cmd) >= 2 and cmd[0] == "pixi" and cmd[1] == "run":
2050
- if environment is None and os.path.isfile("pixi.toml"):
2051
- environment = "pixi.toml"
2052
- cmd = cmd[2:]
2053
- # Guard against empty command after stripping uv/pixi run
2054
- if not cmd:
2055
- raise_error(
2056
- "No command specified after stripping environment prefix. "
2057
- "Usage: calkit xr [uv|pixi run] <command> [args]"
2058
- )
2059
- # Detect what kind of stage this is based on the command
2060
- # If the first argument is a notebook, we'll treat this as a notebook stage
2061
- # If the first argument is `python`, check that the second argument is a
2062
- # script, otherwise it's a shell-command stage
2063
- # If the first argument ends with .tex, we'll treat this as a LaTeX stage
2064
- first_arg = cmd[0]
2065
- stage = {}
2066
- language = None
2067
- if first_arg.endswith(".ipynb"):
2068
- cls = JupyterNotebookStage
2069
- stage["kind"] = "jupyter-notebook"
2070
- stage["notebook_path"] = first_arg
2071
- storage = calkit.notebooks.determine_storage(first_arg)
2072
- stage["html_storage"] = storage
2073
- stage["executed_ipynb_storage"] = storage
2074
- elif first_arg.endswith(".tex"):
2075
- cls = LatexStage
2076
- stage["kind"] = "latex"
2077
- stage["target_path"] = first_arg
2078
- language = "latex"
2079
- # Determine PDF storage based on whether it's already in git
2080
- pdf_path = first_arg.removesuffix(".tex") + ".pdf"
2081
- try:
2082
- repo = git.Repo(".")
2083
- if repo.git.ls_files(pdf_path):
2084
- stage["pdf_storage"] = "git"
2085
- else:
2086
- stage["pdf_storage"] = "dvc"
2087
- except InvalidGitRepositoryError:
2088
- # Not a git repo, default to dvc
2089
- stage["pdf_storage"] = "dvc"
2090
- elif first_arg == "python" and len(cmd) > 1 and cmd[1].endswith(".py"):
2091
- cls = PythonScriptStage
2092
- stage["kind"] = "python-script"
2093
- stage["script_path"] = cmd[1]
2094
- if len(cmd) > 2:
2095
- stage["args"] = cmd[2:]
2096
- language = "python"
2097
- elif first_arg.endswith(".py"):
2098
- cls = PythonScriptStage
2099
- stage["kind"] = "python-script"
2100
- stage["script_path"] = first_arg
2101
- if len(cmd) > 1:
2102
- stage["args"] = cmd[1:]
2103
- language = "python"
2104
- elif first_arg == "julia" and len(cmd) > 1 and cmd[1].endswith(".jl"):
2105
- cls = JuliaScriptStage
2106
- stage["kind"] = "julia-script"
2107
- stage["script_path"] = cmd[1]
2108
- if len(cmd) > 2:
2109
- stage["args"] = cmd[2:]
2110
- language = "julia"
2111
- elif first_arg.endswith(".jl"):
2112
- cls = JuliaScriptStage
2113
- stage["kind"] = "julia-script"
2114
- stage["script_path"] = first_arg
2115
- if len(cmd) > 1:
2116
- stage["args"] = cmd[1:]
2117
- language = "julia"
2118
- elif first_arg == "julia" and len(cmd) > 1:
2119
- cls = JuliaCommandStage
2120
- stage["kind"] = "julia-command"
2121
- stage["command"] = " ".join(cmd[1:])
2122
- language = "julia"
2123
- elif first_arg == "matlab" and len(cmd) > 1 and cmd[1].endswith(".m"):
2124
- cls = MatlabScriptStage
2125
- stage["kind"] = "matlab-script"
2126
- stage["script_path"] = cmd[1]
2127
- language = "matlab"
2128
- elif first_arg.endswith(".m"):
2129
- cls = MatlabScriptStage
2130
- stage["kind"] = "matlab-script"
2131
- stage["script_path"] = first_arg
2132
- language = "matlab"
2133
- elif first_arg == "matlab" and len(cmd) > 1:
2134
- cls = MatlabCommandStage
2135
- stage["kind"] = "matlab-command"
2136
- stage["command"] = " ".join(cmd[1:])
2137
- language = "matlab"
2138
- elif first_arg == "Rscript" and len(cmd) > 1 and cmd[1].endswith(".R"):
2139
- cls = RScriptStage
2140
- stage["kind"] = "r-script"
2141
- stage["script_path"] = cmd[1]
2142
- if len(cmd) > 2:
2143
- stage["args"] = cmd[2:]
2144
- language = "r"
2145
- elif first_arg.endswith(".R"):
2146
- cls = RScriptStage
2147
- stage["kind"] = "r-script"
2148
- stage["script_path"] = first_arg
2149
- if len(cmd) > 1:
2150
- stage["args"] = cmd[1:]
2151
- language = "r"
2152
- elif first_arg.endswith((".sh", ".bash", ".zsh")):
2153
- cls = ShellScriptStage
2154
- stage["kind"] = "shell-script"
2155
- stage["script_path"] = first_arg
2156
- if len(cmd) > 1:
2157
- stage["args"] = cmd[1:]
2158
- # Detect shell type from extension
2159
- if first_arg.endswith(".bash"):
2160
- stage["shell"] = "bash"
2161
- elif first_arg.endswith(".zsh"):
2162
- stage["shell"] = "zsh"
2163
- else:
2164
- stage["shell"] = "sh"
2165
- language = "shell"
2166
- else:
2167
- cls = ShellCommandStage
2168
- stage["kind"] = "shell-command"
2169
- stage["command"] = " ".join(shlex.quote(arg) for arg in cmd)
2170
- language = "shell"
2171
- # Create a stage name if one isn't provided and check for existing similar
2172
- # stages
2173
- if stage_name is None:
2174
- base_stage_name = generate_stage_name(cmd)
2175
- stage_name = base_stage_name
2176
- # If a stage with this name exists and is different, auto-increment
2177
- if stage_name in stages:
2178
- existing_stage = stages[stage_name]
2179
- if not stages_are_similar(existing_stage, stage):
2180
- # Find the next available increment
2181
- counter = 2
2182
- while f"{base_stage_name}-{counter}" in stages:
2183
- candidate_stage = stages[f"{base_stage_name}-{counter}"]
2184
- if stages_are_similar(candidate_stage, stage):
2185
- # Found a matching stage with this incremented name
2186
- stage_name = f"{base_stage_name}-{counter}"
2187
- break
2188
- counter += 1
2189
- else:
2190
- # No matching stage found, use the next available number
2191
- stage_name = f"{base_stage_name}-{counter}"
2192
- typer.echo(
2193
- f"Stage '{base_stage_name}' already exists with different "
2194
- f"configuration; using '{stage_name}' instead"
2195
- )
2196
- # Check if a similar stage already exists and reuse its environment if not
2197
- # specified
2198
- if stage_name in stages:
2199
- existing_stage = stages[stage_name]
2200
- if not stages_are_similar(existing_stage, stage):
2201
- raise_error(
2202
- f"A stage named '{stage_name}' already exists with "
2203
- "different configuration; "
2204
- f"Please specify a unique stage name with --stage"
2205
- )
2206
- return
2207
- # If no environment was specified and a similar stage exists,
2208
- # reuse its environment
2209
- if environment is None and "environment" in existing_stage:
2210
- environment = existing_stage["environment"]
2211
- typer.echo(
2212
- f"Reusing environment '{environment}' from existing "
2213
- f"stage '{stage_name}'"
2214
- )
2215
- # Detect or create environment for this stage
2216
- env_result = detect_env_for_stage(
2217
- stage=stage,
2218
- environment=environment,
2219
- ck_info=ck_info,
2220
- language=language,
2221
- )
2222
- # If we created an environment from dependencies, write the spec file
2223
- if env_result.created_from_dependencies and not dry_run:
2224
- typer.echo(
2225
- "No existing environment detected; "
2226
- "Attempting to create one based on detected dependencies"
2227
- )
2228
- if env_result.dependencies:
2229
- typer.echo(
2230
- f"Detected {language or 'code'} dependencies: "
2231
- f"{', '.join(env_result.dependencies)}"
2232
- )
2233
- if env_result.spec_path and env_result.spec_content is not None:
2234
- # Create the spec file
2235
- spec_dir = os.path.dirname(env_result.spec_path)
2236
- if spec_dir:
2237
- os.makedirs(spec_dir, exist_ok=True)
2238
- with open(env_result.spec_path, "w") as f:
2239
- f.write(env_result.spec_content)
2240
- typer.echo(f"Created environment spec: {env_result.spec_path}")
2241
- # Add environment to calkit.yaml if it doesn't exist
2242
- if not env_result.exists and not dry_run:
2243
- envs = ck_info.get("environments", {})
2244
- envs[env_result.name] = env_result.env
2245
- ck_info["environments"] = envs
2246
- with open("calkit.yaml", "w") as f:
2247
- calkit.ryaml.dump(ck_info, f)
2248
- ck_info = calkit.load_calkit_info()
2249
- env_name = env_result.name
2250
- stage["environment"] = env_name
2251
- # Detect inputs and outputs if not disabled
2252
- detected_inputs = []
2253
- detected_outputs = []
2254
- if not no_detect_io:
2255
- try:
2256
- io_info = detect_io(stage)
2257
- detected_inputs = io_info["inputs"]
2258
- detected_outputs = io_info["outputs"]
2259
- except Exception as e:
2260
- typer.echo(
2261
- f"Warning: Failed to detect inputs/outputs: {e}",
2262
- err=True,
2263
- )
2264
- # Initialize git repo and get DVC paths for storage determination
2265
- try:
2266
- repo = git.Repo(".")
2267
- except InvalidGitRepositoryError:
2268
- repo = None
2269
- dvc_paths = []
2270
- if repo is not None:
2271
- try:
2272
- dvc_paths = calkit.dvc.list_paths()
2273
- except Exception:
2274
- # DVC might not be initialized
2275
- pass
2276
- # Merge user-specified inputs/outputs with detected ones
2277
- # User-specified take precedence and detected ones are added if not already
2278
- # present
2279
- all_inputs = list(inputs) # Start with user-specified
2280
- for detected in detected_inputs:
2281
- if detected not in all_inputs:
2282
- all_inputs.append(detected)
2283
- # Convert detected outputs to PathOutput models with storage determination
2284
- detected_output_models: list[str | PathOutput] = []
2285
- for detected in detected_outputs:
2286
- storage = _determine_output_storage(detected, repo, dvc_paths)
2287
- detected_output_models.append(
2288
- PathOutput(
2289
- path=detected,
2290
- storage=storage, # type: ignore[arg-type]
2291
- )
2292
- )
2293
- # Merge outputs
2294
- all_outputs: list[str | PathOutput] = list(
2295
- outputs
2296
- ) # Start with user-specified
2297
- for detected in detected_output_models:
2298
- # Check if this output path is already present
2299
- detected_path = (
2300
- detected.path if isinstance(detected, PathOutput) else detected
2301
- )
2302
- already_present = False
2303
- for existing in all_outputs:
2304
- existing_path = (
2305
- existing.path if isinstance(existing, PathOutput) else existing
2306
- )
2307
- if existing_path == detected_path:
2308
- already_present = True
2309
- break
2310
- if not already_present:
2311
- all_outputs.append(detected)
2312
- # Add inputs and outputs to stage
2313
- if all_inputs:
2314
- stage["inputs"] = all_inputs
2315
- if all_outputs:
2316
- # Convert PathOutput objects to dicts for serialization
2317
- serialized_outputs = []
2318
- for output in all_outputs:
2319
- if isinstance(output, PathOutput):
2320
- serialized_outputs.append(
2321
- output.model_dump(exclude_unset=True)
2322
- )
2323
- else:
2324
- serialized_outputs.append(output)
2325
- stage["outputs"] = serialized_outputs
2326
- # Create the stage, write to calkit.yaml, and run it to see if
2327
- # it's successful
2328
- try:
2329
- cls.model_validate(stage)
2330
- except Exception as e:
2331
- raise_error(f"Failed to create stage: {e}")
2332
- # If dry-run, print environment and stage then return
2333
- if dry_run:
2334
- # Print environment info
2335
- if env_result.created_from_dependencies:
2336
- typer.echo("Environment (would be created):")
2337
- if env_result.spec_path and env_result.spec_content is not None:
2338
- typer.echo(f" Spec file: {env_result.spec_path}")
2339
- typer.echo(" Content:")
2340
- for line in env_result.spec_content.split("\n"):
2341
- typer.echo(f" {line}")
2342
- elif not env_result.exists:
2343
- typer.echo("Environment (would be added to calkit.yaml):")
2344
- yaml_output = io.StringIO()
2345
- calkit.ryaml.dump({env_result.name: env_result.env}, yaml_output)
2346
- for line in yaml_output.getvalue().rstrip().split("\n"):
2347
- typer.echo(f" {line}")
2348
- else:
2349
- typer.echo(f"Environment: {env_name} (already exists)")
2350
- # Print stage
2351
- typer.echo("\nStage (would be added to pipeline):")
2352
- yaml_output = io.StringIO()
2353
- calkit.ryaml.dump({stage_name: stage}, yaml_output)
2354
- for line in yaml_output.getvalue().rstrip().split("\n"):
2355
- typer.echo(f" {line}")
2356
- return
2357
- stages[stage_name] = stage
2358
- pipeline["stages"] = stages
2359
- ck_info["pipeline"] = pipeline
2360
- with open("calkit.yaml", "w") as f:
2361
- calkit.ryaml.dump(ck_info, f)
2362
- try:
2363
- # Format stage as YAML for display
2364
- yaml_output = io.StringIO()
2365
- calkit.ryaml.dump({stage_name: stage}, yaml_output)
2366
- # Indent YAML by 2 spaces
2367
- indented_yaml = "\n".join(
2368
- " " + line if line.strip() else line
2369
- for line in yaml_output.getvalue().rstrip().split("\n")
2370
- )
2371
- typer.echo(
2372
- f"Adding stage to pipeline and attempting to execute:"
2373
- f"\n{indented_yaml}"
2374
- )
2375
- run(targets=[stage_name], force=force, verbose=verbose)
2376
- except Exception as e:
2377
- # If the stage failed, write the old ck_info back to calkit.yaml to
2378
- # remove the stage that we added
2379
- with open("calkit.yaml", "w") as f:
2380
- calkit.ryaml.dump(ck_info_orig, f)
2381
- raise_error(f"Failed to execute stage: {e}")
2382
-
2383
-
2384
1892
  @app.command(name="runproc", help="Execute a procedure (alias for 'xproc').")
2385
1893
  @app.command(name="xproc", help="Execute a procedure.")
2386
1894
  def run_procedure(
@@ -2400,7 +1908,7 @@ def run_procedure(
2400
1908
  typer.echo(out, nl=False)
2401
1909
  time.sleep(dt)
2402
1910
  seconds -= dt
2403
- typer.echo()
1911
+ typer.echo("Done")
2404
1912
 
2405
1913
  def convert_value(value, dtype):
2406
1914
  if dtype == "int":