calkit-python 0.38.4__tar.gz → 0.39.0__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 (328) hide show
  1. {calkit_python-0.38.4 → calkit_python-0.39.0}/AGENTS.md +4 -0
  2. {calkit_python-0.38.4 → calkit_python-0.39.0}/PKG-INFO +1 -1
  3. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/check.py +1 -2
  4. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/check.py +1 -3
  5. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/config.py +1 -2
  6. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/core.py +16 -1
  7. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/import_.py +4 -8
  8. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/list.py +1 -3
  9. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/main/core.py +118 -35
  10. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/main/xr.py +2 -2
  11. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/new.py +22 -54
  12. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/overleaf.py +5 -5
  13. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/update.py +5 -12
  14. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/core.py +6 -16
  15. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/dvc/core.py +1 -2
  16. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/dvc/zip.py +1 -3
  17. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/git.py +18 -4
  18. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/jupyterlab/routes.py +5 -6
  19. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/notebooks.py +1 -3
  20. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/pipeline.py +374 -48
  21. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/releases.py +1 -3
  22. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/server.py +17 -15
  23. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/main/test_core.py +74 -0
  24. calkit_python-0.39.0/calkit/tests/cli/main/test_subprojects.py +298 -0
  25. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/dvc/test_core.py +1 -1
  26. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_pipeline.py +193 -0
  27. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/cli-reference.md +6 -4
  28. calkit_python-0.39.0/docs/subprojects.md +18 -0
  29. {calkit_python-0.38.4 → calkit_python-0.39.0}/mkdocs.yml +1 -0
  30. {calkit_python-0.38.4 → calkit_python-0.39.0}/.claude-plugin/marketplace.json +0 -0
  31. {calkit_python-0.38.4 → calkit_python-0.39.0}/.gitignore +0 -0
  32. {calkit_python-0.38.4 → calkit_python-0.39.0}/.pre-commit-config.yaml +0 -0
  33. {calkit_python-0.38.4 → calkit_python-0.39.0}/.prettierignore +0 -0
  34. {calkit_python-0.38.4 → calkit_python-0.39.0}/.python-version +0 -0
  35. {calkit_python-0.38.4 → calkit_python-0.39.0}/.vscode/launch.json +0 -0
  36. {calkit_python-0.38.4 → calkit_python-0.39.0}/.vscode/tasks.json +0 -0
  37. {calkit_python-0.38.4 → calkit_python-0.39.0}/.yarnrc.yml +0 -0
  38. {calkit_python-0.38.4 → calkit_python-0.39.0}/CITATION.cff +0 -0
  39. {calkit_python-0.38.4 → calkit_python-0.39.0}/CODE_OF_CONDUCT.md +0 -0
  40. {calkit_python-0.38.4 → calkit_python-0.39.0}/CONTRIBUTING.md +0 -0
  41. {calkit_python-0.38.4 → calkit_python-0.39.0}/LICENSE +0 -0
  42. {calkit_python-0.38.4 → calkit_python-0.39.0}/Makefile +0 -0
  43. {calkit_python-0.38.4 → calkit_python-0.39.0}/README.md +0 -0
  44. {calkit_python-0.38.4 → calkit_python-0.39.0}/agent-plugin/.claude-plugin/plugin.json +0 -0
  45. {calkit_python-0.38.4 → calkit_python-0.39.0}/agent-plugin/skills/add-pipeline-stage/SKILL.md +0 -0
  46. {calkit_python-0.38.4 → calkit_python-0.39.0}/agent-plugin/skills/conventions/SKILL.md +0 -0
  47. {calkit_python-0.38.4 → calkit_python-0.39.0}/agent-plugin/skills/create-pipeline/SKILL.md +0 -0
  48. {calkit_python-0.38.4 → calkit_python-0.39.0}/babel.config.js +0 -0
  49. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/__init__.py +0 -0
  50. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/__main__.py +0 -0
  51. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/calc.py +0 -0
  52. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/__init__.py +0 -0
  53. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/cloud.py +0 -0
  54. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/describe.py +0 -0
  55. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/dev.py +0 -0
  56. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/latex.py +0 -0
  57. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/main/__init__.py +0 -0
  58. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/notebooks.py +0 -0
  59. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/office.py +0 -0
  60. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cli/slurm.py +0 -0
  61. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/cloud.py +0 -0
  62. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/conda.py +0 -0
  63. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/config.py +0 -0
  64. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/datasets.py +0 -0
  65. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/detect.py +0 -0
  66. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/docker.py +0 -0
  67. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/dvc/__init__.py +0 -0
  68. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/environments.py +0 -0
  69. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/fs.py +0 -0
  70. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/github.py +0 -0
  71. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/gui.py +0 -0
  72. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/invenio.py +0 -0
  73. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/julia.py +0 -0
  74. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/jupyter.py +0 -0
  75. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/jupyterlab/__init__.py +0 -0
  76. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/package.json +0 -0
  77. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/schemas/calkit/package.json.orig +0 -0
  78. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/schemas/calkit/plugin.json +0 -0
  79. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
  80. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
  81. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
  82. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/909.e3f9cc3408834a7fdcc3.js +0 -0
  83. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
  84. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
  85. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
  86. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/remoteEntry.65469af996e7a96aa983.js +0 -0
  87. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/style.js +0 -0
  88. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/labextension/static/third-party-licenses.json +0 -0
  89. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/licenses.py +0 -0
  90. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/magics.py +0 -0
  91. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/matlab.py +0 -0
  92. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/models/__init__.py +0 -0
  93. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/models/core.py +0 -0
  94. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/models/io.py +0 -0
  95. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/models/iteration.py +0 -0
  96. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/models/pipeline.py +0 -0
  97. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/office.py +0 -0
  98. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/ops.py +0 -0
  99. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/overleaf.py +0 -0
  100. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/__init__.py +0 -0
  101. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/core.py +0 -0
  102. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/__init__.py +0 -0
  103. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/article/paper.tex +0 -0
  104. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/core.py +0 -0
  105. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/jfm/jfm.bst +0 -0
  106. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/jfm/jfm.cls +0 -0
  107. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
  108. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/jfm/paper.tex +0 -0
  109. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/templates/latex/jfm/upmath.sty +0 -0
  110. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/__init__.py +0 -0
  111. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/__init__.py +0 -0
  112. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/main/__init__.py +0 -0
  113. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/main/test_xr.py +0 -0
  114. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_check.py +0 -0
  115. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_cloud.py +0 -0
  116. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_config.py +0 -0
  117. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_import.py +0 -0
  118. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_latex.py +0 -0
  119. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_list.py +0 -0
  120. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_new.py +0 -0
  121. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_notebooks.py +0 -0
  122. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_overleaf.py +0 -0
  123. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/cli/test_update.py +0 -0
  124. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/dvc/__init__.py +0 -0
  125. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/dvc/test_zip.py +0 -0
  126. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/jupyterlab/__init__.py +0 -0
  127. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/jupyterlab/test_routes.py +0 -0
  128. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/models/__init__.py +0 -0
  129. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/models/test_iteration.py +0 -0
  130. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/models/test_pipeline.py +0 -0
  131. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_calc.py +0 -0
  132. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_check.py +0 -0
  133. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_cloud.py +0 -0
  134. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_conda.py +0 -0
  135. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_core.py +0 -0
  136. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_detect.py +0 -0
  137. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_docker.py +0 -0
  138. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_environments.py +0 -0
  139. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_fs.py +0 -0
  140. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_git.py +0 -0
  141. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_invenio.py +0 -0
  142. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_julia.py +0 -0
  143. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_jupyter.py +0 -0
  144. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_magics.py +0 -0
  145. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_matlab.py +0 -0
  146. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_notebooks.py +0 -0
  147. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_releases.py +0 -0
  148. {calkit_python-0.38.4 → calkit_python-0.39.0}/calkit/tests/test_templates.py +0 -0
  149. {calkit_python-0.38.4 → calkit_python-0.39.0}/conftest.py +0 -0
  150. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/CNAME +0 -0
  151. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/ai-tools.md +0 -0
  152. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/apps.md +0 -0
  153. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/calculations.md +0 -0
  154. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/calkit-yaml.md +0 -0
  155. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/cloud-integration.md +0 -0
  156. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/datasets.md +0 -0
  157. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/dependencies.md +0 -0
  158. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/environments.md +0 -0
  159. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/examples.md +0 -0
  160. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/governance.md +0 -0
  161. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/help.md +0 -0
  162. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/c-to-the-k-white.svg +0 -0
  163. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/calkit-fragmentation-compendium.png +0 -0
  164. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/calkit-no-bg.png +0 -0
  165. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/connect-zenodo.png +0 -0
  166. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/jupyterlab/all-green.png +0 -0
  167. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/jupyterlab/collect-data-stale.png +0 -0
  168. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/jupyterlab/new-env.png +0 -0
  169. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/jupyterlab/new-notebook.png +0 -0
  170. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/jupyterlab/pipeline-badge.png +0 -0
  171. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/jupyterlab-params.png +0 -0
  172. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/plos-osi-code-2024-03.png +0 -0
  173. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/img/vscode-nb-params.png +0 -0
  174. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/index.md +0 -0
  175. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/installation.md +0 -0
  176. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/jupyterlab.md +0 -0
  177. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/local-server.md +0 -0
  178. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/notebooks.md +0 -0
  179. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/overleaf.md +0 -0
  180. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/pipeline/index.md +0 -0
  181. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/pipeline/manual-steps.md +0 -0
  182. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/pipeline/running-and-logging.md +0 -0
  183. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/pipeline/slurm.md +0 -0
  184. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/quickstart.md +0 -0
  185. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/references.md +0 -0
  186. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/releases.md +0 -0
  187. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/reproducibility.md +0 -0
  188. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/adding-latex-pub-docker.md +0 -0
  189. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/conda-envs.md +0 -0
  190. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/existing-project.md +0 -0
  191. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/first-project.md +0 -0
  192. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/github-actions.md +0 -0
  193. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/actions-repo-secrets.png +0 -0
  194. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
  195. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
  196. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
  197. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
  198. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
  199. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
  200. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
  201. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
  202. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
  203. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
  204. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/push.png +0 -0
  205. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
  206. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
  207. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/chart-more-rows.png +0 -0
  208. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/create-project.png +0 -0
  209. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
  210. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/excel-chart.png +0 -0
  211. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/excel-data.png +0 -0
  212. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
  213. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/needs-clone.png +0 -0
  214. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/new-stage.png +0 -0
  215. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
  216. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
  217. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/status-more-rows.png +0 -0
  218. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
  219. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/untracked-data.png +0 -0
  220. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/updated-publication.png +0 -0
  221. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
  222. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/office/workflow-page.png +0 -0
  223. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/clone.png +0 -0
  224. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/create-project.png +0 -0
  225. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
  226. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
  227. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
  228. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/new-token.png +0 -0
  229. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/reclone.png +0 -0
  230. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
  231. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/quick-actions.png +0 -0
  232. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/run-proc.png +0 -0
  233. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/vscode-slurm-notebook/create-calkit-env.png +0 -0
  234. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/vscode-slurm-notebook/create-inner-env.png +0 -0
  235. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/vscode-slurm-notebook/create-new-calkit-env.png +0 -0
  236. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/vscode-slurm-notebook/select-calkit-env.png +0 -0
  237. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/vscode-slurm-notebook/slurm-job-running.png +0 -0
  238. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/vscode-slurm-notebook/slurm-launch-options.png +0 -0
  239. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/img/vscode-slurm-notebook/starting-slurm-job.png +0 -0
  240. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/index.md +0 -0
  241. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/jupyterlab.md +0 -0
  242. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/latex-codespaces.md +0 -0
  243. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/matlab.md +0 -0
  244. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/notebook-pipeline.md +0 -0
  245. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/office.md +0 -0
  246. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/openfoam.md +0 -0
  247. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/procedures.md +0 -0
  248. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/tutorials/vscode-slurm-notebook.md +0 -0
  249. {calkit_python-0.38.4 → calkit_python-0.39.0}/docs/version-control.md +0 -0
  250. {calkit_python-0.38.4 → calkit_python-0.39.0}/install.json +0 -0
  251. {calkit_python-0.38.4 → calkit_python-0.39.0}/jest.config.js +0 -0
  252. {calkit_python-0.38.4 → calkit_python-0.39.0}/jupyter-config/server-config/calkit.json +0 -0
  253. {calkit_python-0.38.4 → calkit_python-0.39.0}/package.json +0 -0
  254. {calkit_python-0.38.4 → calkit_python-0.39.0}/pyproject.toml +0 -0
  255. {calkit_python-0.38.4 → calkit_python-0.39.0}/schema/plugin.json +0 -0
  256. {calkit_python-0.38.4 → calkit_python-0.39.0}/scripts/generate-docs-references.py +0 -0
  257. {calkit_python-0.38.4 → calkit_python-0.39.0}/scripts/install.ps1 +0 -0
  258. {calkit_python-0.38.4 → calkit_python-0.39.0}/scripts/install.sh +0 -0
  259. {calkit_python-0.38.4 → calkit_python-0.39.0}/scripts/make-calk9.sh +0 -0
  260. {calkit_python-0.38.4 → calkit_python-0.39.0}/scripts/sync-docs.py +0 -0
  261. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/__tests__/useQueries.spec.ts +0 -0
  262. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/calkit-config.ts +0 -0
  263. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/cell-output-marker.ts +0 -0
  264. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/commit-dialog.tsx +0 -0
  265. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/environment-editor.tsx +0 -0
  266. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/notebook-registration.tsx +0 -0
  267. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/notebook-toolbar.tsx +0 -0
  268. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/pipeline-status-bar.tsx +0 -0
  269. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/project-info-editor.tsx +0 -0
  270. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/sidebar-settings.tsx +0 -0
  271. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/sidebar.tsx +0 -0
  272. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/components/stage-editor.tsx +0 -0
  273. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/feature-flags.ts +0 -0
  274. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/file-browser-menu.ts +0 -0
  275. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/hooks/__tests__/useQueries.test.tsx +0 -0
  276. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/hooks/useQueries.ts +0 -0
  277. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/icons.ts +0 -0
  278. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/index.ts +0 -0
  279. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/io-tracker.ts +0 -0
  280. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/pipeline-state.ts +0 -0
  281. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/queryClient.ts +0 -0
  282. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/request.ts +0 -0
  283. {calkit_python-0.38.4 → calkit_python-0.39.0}/src/shims-mainmenu.d.ts +0 -0
  284. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/base.css +0 -0
  285. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/cell-output-marker.css +0 -0
  286. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/environment-editor.css +0 -0
  287. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/environment-selector.css +0 -0
  288. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/img/calkit-no-bg.png +0 -0
  289. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/index.css +0 -0
  290. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/index.js +0 -0
  291. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/notebook-toolbar.css +0 -0
  292. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/pipeline-status-bar.css +0 -0
  293. {calkit_python-0.38.4 → calkit_python-0.39.0}/style/sidebar.css +0 -0
  294. {calkit_python-0.38.4 → calkit_python-0.39.0}/test/dvc-md5-dir/osx-arm64.txt +0 -0
  295. {calkit_python-0.38.4 → calkit_python-0.39.0}/test/nb-julia.ipynb +0 -0
  296. {calkit_python-0.38.4 → calkit_python-0.39.0}/test/nb-params.ipynb +0 -0
  297. {calkit_python-0.38.4 → calkit_python-0.39.0}/test/nb-subdir.ipynb +0 -0
  298. {calkit_python-0.38.4 → calkit_python-0.39.0}/test/pipeline.ipynb +0 -0
  299. {calkit_python-0.38.4 → calkit_python-0.39.0}/test/script.py +0 -0
  300. {calkit_python-0.38.4 → calkit_python-0.39.0}/test/test-log.log +0 -0
  301. {calkit_python-0.38.4 → calkit_python-0.39.0}/tsconfig.json +0 -0
  302. {calkit_python-0.38.4 → calkit_python-0.39.0}/tsconfig.test.json +0 -0
  303. {calkit_python-0.38.4 → calkit_python-0.39.0}/ui-tests/.gitignore +0 -0
  304. {calkit_python-0.38.4 → calkit_python-0.39.0}/ui-tests/README.md +0 -0
  305. {calkit_python-0.38.4 → calkit_python-0.39.0}/ui-tests/jupyter_server_test_config.py +0 -0
  306. {calkit_python-0.38.4 → calkit_python-0.39.0}/ui-tests/package.json +0 -0
  307. {calkit_python-0.38.4 → calkit_python-0.39.0}/ui-tests/playwright.config.js +0 -0
  308. {calkit_python-0.38.4 → calkit_python-0.39.0}/ui-tests/tests/calkit.spec.ts +0 -0
  309. {calkit_python-0.38.4 → calkit_python-0.39.0}/ui-tests/yarn.lock +0 -0
  310. {calkit_python-0.38.4 → calkit_python-0.39.0}/uv.lock +0 -0
  311. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/.gitignore +0 -0
  312. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/.vscodeignore +0 -0
  313. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/CHANGELOG.md +0 -0
  314. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/LICENSE +0 -0
  315. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/README.md +0 -0
  316. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/images/calkit-no-bg.png +0 -0
  317. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/package-lock.json +0 -0
  318. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/package.json +0 -0
  319. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/scripts/set-proposed-api.js +0 -0
  320. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/src/environments.ts +0 -0
  321. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/src/extension.ts +0 -0
  322. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/src/notebooks.ts +0 -0
  323. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/src/test/environments.test.ts +0 -0
  324. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/src/test/kernel-selection.test.ts +0 -0
  325. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/src/test/notebooks.test.ts +0 -0
  326. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/src/types.ts +0 -0
  327. {calkit_python-0.38.4 → calkit_python-0.39.0}/vscode-ext/tsconfig.json +0 -0
  328. {calkit_python-0.38.4 → calkit_python-0.39.0}/yarn.lock +0 -0
@@ -21,3 +21,7 @@ Agents should never make commits to Git.
21
21
 
22
22
  Prefer tests that include multiple scenarios to comprehensively test
23
23
  a feature in one function over many different test functions.
24
+
25
+ Do not write docstrings in test functions.
26
+
27
+ For prose, only use one space after punctuation.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calkit-python
3
- Version: 0.38.4
3
+ Version: 0.39.0
4
4
  Summary: Reproducibility simplified.
5
5
  Project-URL: Homepage, https://calkit.org
6
6
  Project-URL: Issues, https://github.com/calkit/calkit/issues
@@ -174,14 +174,13 @@ def check_reproducibility(
174
174
  wdir: str = ".", log_func: Callable | None = None
175
175
  ) -> ReproCheck:
176
176
  """Check the reproducibility of a project."""
177
- import git
178
177
  from git.exc import InvalidGitRepositoryError
179
178
 
180
179
  res = dict()
181
180
  if log_func is None:
182
181
  log_func = print
183
182
  try:
184
- git.Repo(wdir)
183
+ calkit.git.get_repo(wdir)
185
184
  res["is_git_repo"] = True
186
185
  except InvalidGitRepositoryError:
187
186
  res["is_git_repo"] = False
@@ -1292,9 +1292,7 @@ def check_env_vars(
1292
1292
  dotenv_path=".env", key_to_set=name, value_to_set=value
1293
1293
  )
1294
1294
  # Ensure that .env is ignored by git
1295
- import git
1296
-
1297
- repo = git.Repo()
1295
+ repo = calkit.git.get_repo()
1298
1296
  if not repo.ignored(".env"):
1299
1297
  typer.echo("Adding .env to .gitignore")
1300
1298
  with open(".gitignore", "a") as f:
@@ -92,7 +92,6 @@ def setup_remote(
92
92
  """Setup the Calkit cloud as the default DVC remote and store a token in
93
93
  the local config.
94
94
  """
95
- import git
96
95
  from git.exc import InvalidGitRepositoryError
97
96
 
98
97
  from calkit.dvc import configure_remote, set_remote_auth
@@ -113,7 +112,7 @@ def setup_remote(
113
112
  except (ValueError, RuntimeError) as e:
114
113
  raise_error(f"Failed to set up DVC remote: {e}")
115
114
  if not no_commit:
116
- repo = git.Repo()
115
+ repo = calkit.git.get_repo()
117
116
  repo.git.add(".dvc/config")
118
117
  if ".dvc/config" in calkit.git.get_staged_files():
119
118
  typer.echo("Committing changes to DVC config")
@@ -46,10 +46,25 @@ def complete_stage_names(
46
46
  ryaml = ruamel.yaml.YAML()
47
47
  with open("calkit.yaml") as f:
48
48
  info = ryaml.load(f) or {}
49
+ candidates: list[str] = []
49
50
  stages = info.get("pipeline", {}).get("stages", {})
51
+ candidates.extend(stages.keys())
52
+ for sp_cfg in info.get("subprojects", []):
53
+ if not isinstance(sp_cfg, dict) or not sp_cfg.get("path"):
54
+ continue
55
+ sp_path = sp_cfg["path"]
56
+ sp_calkit = os.path.join(sp_path, "calkit.yaml")
57
+ sp_name = os.path.basename(sp_path.rstrip("/"))
58
+ candidates.append(sp_name)
59
+ if os.path.isfile(sp_calkit):
60
+ with open(sp_calkit) as f:
61
+ sp_info = ryaml.load(f) or {}
62
+ sp_stages = sp_info.get("pipeline", {}).get("stages", {})
63
+ for stage in sp_stages:
64
+ candidates.append(f"{sp_name}:{stage}")
50
65
  return [
51
66
  CompletionItem(name)
52
- for name in stages
67
+ for name in candidates
53
68
  if name.startswith(incomplete)
54
69
  ]
55
70
  except Exception:
@@ -72,7 +72,6 @@ def import_dataset(
72
72
 
73
73
  Currently only supports datasets kept in DVC, not Git.
74
74
  """
75
- import git
76
75
  import requests
77
76
  from tqdm import tqdm
78
77
 
@@ -95,7 +94,7 @@ def import_dataset(
95
94
  raise_error("A dataset already exists in this project at this path")
96
95
  elif overwrite and ds_dest_path in ds_paths:
97
96
  datasets = [ds for ds in datasets if ds["path"] != ds_dest_path]
98
- repo = git.Repo()
97
+ repo = calkit.git.get_repo()
99
98
  # Obtain, save, and commit the .dvc file for the dataset, or if this is
100
99
  # kept in Git, just download the files and commit them here
101
100
  typer.echo("Fetching import info")
@@ -261,8 +260,6 @@ def import_environment(
261
260
  ] = False,
262
261
  ) -> None:
263
262
  """Import an environment from another project."""
264
- import git
265
-
266
263
  raise_error(
267
264
  "This command is not yet implemented; "
268
265
  "please thumbs-up this issue if you'd like to see "
@@ -317,7 +314,7 @@ def import_environment(
317
314
  ck_info["environments"] = environments
318
315
  with open("calkit.yaml", "w") as f:
319
316
  calkit.ryaml.dump(ck_info, f)
320
- repo = git.Repo()
317
+ repo = calkit.git.get_repo()
321
318
  repo.git.add("calkit.yaml")
322
319
  if not no_commit and calkit.git.get_staged_files():
323
320
  repo.git.commit(["-m", f"Import environment {src}"])
@@ -371,7 +368,6 @@ def import_from_zenodo(
371
368
  ] = False,
372
369
  ):
373
370
  """Import files from a Zenodo record."""
374
- import git
375
371
  import requests
376
372
 
377
373
  from calkit.dvc import run_dvc_command
@@ -440,7 +436,7 @@ def import_from_zenodo(
440
436
  for chunk in resp.iter_content(chunk_size=8192):
441
437
  f.write(chunk)
442
438
  # Decide if this should be stored in Git or DVC
443
- repo = git.Repo()
439
+ repo = calkit.git.get_repo()
444
440
  commit_paths = []
445
441
  if storage is None:
446
442
  if calkit.get_size(dest_dir) > calkit.DVC_SIZE_THRESH_BYTES:
@@ -508,7 +504,7 @@ def import_from_zenodo(
508
504
  json.dump(imports, f, indent=2)
509
505
  # Commit if desired
510
506
  if not no_commit:
511
- repo = git.Repo()
507
+ repo = calkit.git.get_repo()
512
508
  repo.git.add(commit_paths)
513
509
  if repo.git.diff(commit_paths + ["--staged"]):
514
510
  repo.git.commit(
@@ -151,10 +151,8 @@ def list_stages(
151
151
  @list_app.command(name="remotes")
152
152
  def list_remotes():
153
153
  """List Git and DVC remotes."""
154
- import git
155
-
156
154
  try:
157
- repo = git.Repo()
155
+ repo = calkit.git.get_repo()
158
156
  for remote in repo.remotes:
159
157
  typer.echo(f"(Git) {remote.name}: {remote.url}")
160
158
  except Exception as e:
@@ -125,8 +125,6 @@ def init(
125
125
  ] = False,
126
126
  ):
127
127
  """Initialize the current working directory."""
128
- import git
129
-
130
128
  subprocess.run(["git", "init"])
131
129
  result = calkit.dvc.run_dvc_command(
132
130
  ["init"] + (["--force"] if force else [])
@@ -138,7 +136,7 @@ def init(
138
136
  if result != 0:
139
137
  raise_error("Failed to configure DVC autostage")
140
138
  # Commit the newly created .dvc directory
141
- repo = git.Repo()
139
+ repo = calkit.git.get_repo()
142
140
  repo.git.add(".dvc")
143
141
  repo.git.commit("-m", "Initialize DVC")
144
142
  # TODO: Initialize `calkit.yaml`
@@ -316,6 +314,17 @@ def get_status(
316
314
  ),
317
315
  ),
318
316
  ] = None,
317
+ no_check_envs: Annotated[
318
+ bool,
319
+ typer.Option(
320
+ "--no-env-check",
321
+ help=(
322
+ "Skip environment checks. "
323
+ "Note that this may produce an inaccurate pipeline status "
324
+ "if materialized environments have changed."
325
+ ),
326
+ ),
327
+ ] = False,
319
328
  as_json: Annotated[
320
329
  bool, typer.Option("--json", help="Output status as JSON.")
321
330
  ] = False,
@@ -325,10 +334,12 @@ def get_status(
325
334
  from git.exc import InvalidGitRepositoryError
326
335
 
327
336
  ck_info = calkit.load_calkit_info()
328
- # If there's anything in ck_info and this isn't a Git repo, initialize one
337
+ # If there's anything in ck_info and this isn't a Git repo, initialize one.
338
+ # Use search_parent_directories so a subproject folder inside a parent repo
339
+ # is discovered correctly rather than getting a new git init.
329
340
  if ck_info:
330
341
  try:
331
- git.Repo()
342
+ calkit.git.get_repo()
332
343
  except InvalidGitRepositoryError:
333
344
  git.Repo.init()
334
345
  valid_categories = ["project", "git", "dvc", "pipeline"]
@@ -349,7 +360,7 @@ def get_status(
349
360
  pipeline_status = calkit.pipeline.get_status(
350
361
  ck_info=ck_info,
351
362
  targets=targets,
352
- check_environments=True,
363
+ check_environments=not no_check_envs,
353
364
  clean_notebooks=True,
354
365
  compile_to_dvc=True,
355
366
  )
@@ -373,7 +384,7 @@ def get_status(
373
384
  )
374
385
  if "git" in categories:
375
386
  try:
376
- repo = git.Repo()
387
+ repo = calkit.git.get_repo()
377
388
  changed_files = calkit.git.get_changed_files(repo=repo)
378
389
  staged_files = calkit.git.get_staged_files(repo=repo)
379
390
  untracked_files = calkit.git.get_untracked_files(repo=repo)
@@ -577,7 +588,6 @@ def add(
577
588
  adding any .dvc files to Git when adding to DVC.
578
589
  """
579
590
  import dvc.repo
580
- import git
581
591
  from dvc.exceptions import NotDvcRepoError
582
592
  from git.exc import InvalidGitRepositoryError
583
593
 
@@ -598,7 +608,7 @@ def add(
598
608
  if to is not None and to not in ["git", "dvc", "dvc-zip"]:
599
609
  raise_error(f"Invalid option for 'to': {to}")
600
610
  try:
601
- repo = git.Repo()
611
+ repo = calkit.git.get_repo()
602
612
  except InvalidGitRepositoryError:
603
613
  # Prompt user if they want to run git init here
604
614
  warn("Current directory is not a Git repo")
@@ -610,7 +620,7 @@ def add(
610
620
  subprocess.check_call(["git", "init"])
611
621
  else:
612
622
  raise_error("Not currently in a Git repo; run `calkit init` first")
613
- repo = git.Repo()
623
+ repo = calkit.git.get_repo()
614
624
  try:
615
625
  dvc_repo = calkit.dvc.get_dvc_repo()
616
626
  except NotDvcRepoError:
@@ -1116,9 +1126,7 @@ def ignore(
1116
1126
  ] = False,
1117
1127
  ):
1118
1128
  """Ignore a file, i.e., keep it out of version control."""
1119
- import git
1120
-
1121
- repo = git.Repo()
1129
+ repo = calkit.git.get_repo()
1122
1130
  # Ensure path makes it into .gitignore as a POSIX path
1123
1131
  path = Path(path).as_posix()
1124
1132
  if repo.ignored(path):
@@ -1129,7 +1137,7 @@ def ignore(
1129
1137
  with open(".gitignore", "a") as f:
1130
1138
  f.write(txt)
1131
1139
  if not no_commit:
1132
- repo = git.Repo()
1140
+ repo = calkit.git.get_repo()
1133
1141
  repo.git.reset()
1134
1142
  repo.git.add(".gitignore")
1135
1143
  if calkit.git.get_staged_files():
@@ -1384,13 +1392,18 @@ def run(
1384
1392
  help="Sync with Overleaf before and after running.",
1385
1393
  ),
1386
1394
  ] = False,
1395
+ no_push: Annotated[
1396
+ bool,
1397
+ typer.Option(
1398
+ "--no-push", help="Do not push to Git and DVC after saving."
1399
+ ),
1400
+ ] = False,
1387
1401
  ) -> dict:
1388
1402
  """Check dependencies and run the pipeline."""
1389
1403
  import dvc.log
1390
1404
  import dvc.repo
1391
1405
  import dvc.repo.reproduce
1392
1406
  import dvc.ui
1393
- import git
1394
1407
  from dvc.cli import main as dvc_cli_main
1395
1408
  from git.exc import InvalidGitRepositoryError
1396
1409
 
@@ -1404,9 +1417,11 @@ def run(
1404
1417
  os.environ["CALKIT_PIPELINE_RUNNING"] = "1"
1405
1418
  dotenv.load_dotenv(dotenv_path=".env", verbose=verbose)
1406
1419
  ck_info = calkit.load_calkit_info()
1407
- # Ensure Git is initialized so DVC can be used
1420
+ # Ensure Git is initialized so DVC can be used.
1421
+ # Use search_parent_directories so running from a subproject folder
1422
+ # discovers the parent repo instead of triggering a new git init.
1408
1423
  try:
1409
- git.Repo()
1424
+ calkit.git.get_repo()
1410
1425
  except InvalidGitRepositoryError:
1411
1426
  if not quiet:
1412
1427
  typer.echo("Initializing Git repo")
@@ -1456,12 +1471,45 @@ def run(
1456
1471
  failed = not result.get("success", False)
1457
1472
  if failed:
1458
1473
  warn(f"Failed to check environment '{env_name}'")
1474
+ # Check environments for each subproject so DVC can detect changes
1475
+ subprojects = ck_info.get("subprojects", [])
1476
+ if subprojects:
1477
+ prev_cwd = os.getcwd()
1478
+ for subproject in subprojects:
1479
+ if not isinstance(subproject, dict) or not subproject.get("path"):
1480
+ continue
1481
+ sp = Path(subproject["path"]).as_posix()
1482
+ if not os.path.isdir(sp):
1483
+ continue
1484
+ if not quiet:
1485
+ typer.echo(f"Checking environments for subproject: {sp}")
1486
+ os.chdir(sp)
1487
+ try:
1488
+ sp_ck_info = calkit.load_calkit_info()
1489
+ sp_env_results = calkit.environments.check_all_in_pipeline(
1490
+ ck_info=sp_ck_info, force=force
1491
+ )
1492
+ for env_name, sp_result in sp_env_results.items():
1493
+ if verbose:
1494
+ typer.echo(f"{sp}/{env_name}: {sp_result}")
1495
+ if not sp_result.get("success", False):
1496
+ warn(
1497
+ f"Failed to check environment '{env_name}' "
1498
+ f"in subproject '{sp}'"
1499
+ )
1500
+ except Exception as e:
1501
+ warn(
1502
+ f"Failed to check environments for subproject '{sp}': "
1503
+ f"{e.__class__.__name__}: {e}"
1504
+ )
1505
+ finally:
1506
+ os.chdir(prev_cwd)
1459
1507
  # If specified, perform initial Overleaf sync
1460
1508
  if sync_overleaf:
1461
1509
  overleaf_sync(no_commit=False, no_push=True, verbose=verbose)
1462
- # Compile the DVC pipeline
1510
+ # Compile the DVC pipeline (and subproject pipelines)
1463
1511
  dvc_stages = None
1464
- if ck_info.get("pipeline", {}):
1512
+ if ck_info.get("pipeline", {}) or ck_info.get("subprojects"):
1465
1513
  if not quiet:
1466
1514
  typer.echo("Compiling DVC pipeline")
1467
1515
  try:
@@ -1521,7 +1569,7 @@ def run(
1521
1569
  raise_error("No stages found to run")
1522
1570
  if save_logs:
1523
1571
  # Get status of Git repo before running
1524
- repo = git.Repo()
1572
+ repo = calkit.git.get_repo()
1525
1573
  git_rev = repo.head.commit.hexsha
1526
1574
  try:
1527
1575
  git_branch = repo.active_branch.name
@@ -1538,7 +1586,9 @@ def run(
1538
1586
  dvc_data_status_before.pop("git", None) # Remove git status
1539
1587
  if targets is None:
1540
1588
  targets = []
1541
- args = deepcopy(targets)
1589
+ args, isolated_sp_targets = calkit.pipeline.translate_run_targets(
1590
+ deepcopy(targets), ck_info=ck_info
1591
+ )
1542
1592
  # Extract any boolean args
1543
1593
  for name in [
1544
1594
  "quiet",
@@ -1560,6 +1610,47 @@ def run(
1560
1610
  ]:
1561
1611
  if locals()[name.replace("-", "_")]:
1562
1612
  args.append("--" + name)
1613
+ # Inline subprojects (no .dvc/ dir) share the parent DVC project.
1614
+ # Tell DVC to discover all pipelines so their dvc.yaml files are included,
1615
+ # unless the user already specified targets that include dvc.yaml paths
1616
+ # (translated from subproject shorthand) or --all-pipelines was passed.
1617
+ inline_subprojects = [
1618
+ sp
1619
+ for sp in subprojects
1620
+ if isinstance(sp, dict)
1621
+ and sp.get("path")
1622
+ and not os.path.isdir(os.path.join(sp["path"], ".dvc"))
1623
+ ]
1624
+ translated_targets_have_dvc_yaml = any(
1625
+ "dvc.yaml" in t for t in args if not t.startswith("--")
1626
+ )
1627
+ if (
1628
+ inline_subprojects
1629
+ and not targets
1630
+ and not all_pipelines
1631
+ and not translated_targets_have_dvc_yaml
1632
+ ):
1633
+ args.append("--all-pipelines")
1634
+ failed = False
1635
+ # Run isolated subproject stage targets directly inside their directories.
1636
+ if isolated_sp_targets:
1637
+ for sp_path, stage_name in isolated_sp_targets:
1638
+ sp_args = [stage_name] if stage_name else []
1639
+ if dry:
1640
+ sp_args.append("--dry")
1641
+ if force:
1642
+ sp_args.append("--force")
1643
+ original_dir = os.getcwd()
1644
+ try:
1645
+ os.chdir(sp_path)
1646
+ sp_res = dvc_cli_main(["repro"] + sp_args)
1647
+ finally:
1648
+ os.chdir(original_dir)
1649
+ if sp_res != 0:
1650
+ failed = True
1651
+ if not args or all(a.startswith("--") for a in args):
1652
+ # Only isolated subproject stage targets were given; skip parent run
1653
+ return {}
1563
1654
  if pipeline is not None:
1564
1655
  args += ["--pipeline", pipeline]
1565
1656
  if downstream is not None:
@@ -1593,7 +1684,7 @@ def run(
1593
1684
  # Disable other misc DVC output
1594
1685
  dvc.ui.ui.write = lambda *args, **kwargs: None
1595
1686
  res = dvc_cli_main(["repro"] + args)
1596
- failed = res != 0
1687
+ failed = failed or res != 0
1597
1688
  # Parse log to get timing and which stages ran
1598
1689
  with open(log_fpath, "r") as f:
1599
1690
  log_content = f.read()
@@ -1687,7 +1778,7 @@ def run(
1687
1778
  save_message = "Run pipeline"
1688
1779
  if not quiet:
1689
1780
  typer.echo("Saving the project after successful run")
1690
- save(save_all=True, message=save_message)
1781
+ save(save_all=True, message=save_message, no_push=no_push)
1691
1782
  # If specified, perform final Overleaf sync
1692
1783
  if sync_overleaf:
1693
1784
  overleaf_sync(
@@ -2272,8 +2363,6 @@ def run_procedure(
2272
2363
  return bool(value)
2273
2364
  return value
2274
2365
 
2275
- import git
2276
-
2277
2366
  from calkit.models import Procedure
2278
2367
 
2279
2368
  ck_info = calkit.load_calkit_info(process_includes="procedures")
@@ -2285,7 +2374,7 @@ def run_procedure(
2285
2374
  proc = Procedure.model_validate(procs[name])
2286
2375
  except Exception as e:
2287
2376
  raise_error(f"Procedure '{name}' is invalid: {e}")
2288
- git_repo = git.Repo()
2377
+ git_repo = calkit.git.get_repo()
2289
2378
  # Check to make sure the working tree is clean, so we know we ran the
2290
2379
  # committed version of the procedure
2291
2380
  git_status = git_repo.git.status()
@@ -2431,10 +2520,8 @@ def set_env_var(
2431
2520
  value: Annotated[str, typer.Argument(help="Value of the variable.")],
2432
2521
  ):
2433
2522
  """Set an environmental variable for the project in its '.env' file."""
2434
- import git
2435
-
2436
2523
  # Ensure that .env is ignored by git
2437
- repo = git.Repo()
2524
+ repo = calkit.git.get_repo()
2438
2525
  if not repo.ignored(".env"):
2439
2526
  typer.echo("Adding .env to .gitignore")
2440
2527
  with open(".gitignore", "a") as f:
@@ -2493,9 +2580,7 @@ def upgrade(
2493
2580
  @app.command(name="switch-branch")
2494
2581
  def switch_branch(name: Annotated[str, typer.Argument(help="Branch name.")]):
2495
2582
  """Switch to a different branch."""
2496
- import git
2497
-
2498
- repo = git.Repo()
2583
+ repo = calkit.git.get_repo()
2499
2584
  if name not in repo.heads:
2500
2585
  typer.echo(f"Branch '{name}' does not exist; creating")
2501
2586
  cmd = ["-b", name]
@@ -2624,9 +2709,7 @@ def map_paths(
2624
2709
  Currently this is done with copying. Outputs are ensured to be ignored by
2625
2710
  Git.
2626
2711
  """
2627
- import git
2628
-
2629
- repo = git.Repo()
2712
+ repo = calkit.git.get_repo()
2630
2713
 
2631
2714
  def validate_and_split(mapping: str) -> tuple[str, str]:
2632
2715
  if "->" not in mapping:
@@ -297,7 +297,7 @@ def execute_and_record(
297
297
  language = "latex"
298
298
  pdf_path = first_arg.removesuffix(".tex") + ".pdf"
299
299
  try:
300
- repo = git.Repo(".")
300
+ repo = calkit.git.get_repo()
301
301
  if repo.git.ls_files(pdf_path):
302
302
  stage["pdf_storage"] = "git"
303
303
  else:
@@ -484,7 +484,7 @@ def execute_and_record(
484
484
  )
485
485
  # Initialize git repo and get DVC paths for storage determination
486
486
  try:
487
- repo = git.Repo(".")
487
+ repo = calkit.git.get_repo()
488
488
  except InvalidGitRepositoryError:
489
489
  repo = None
490
490
  dvc_paths = []