calkit-python 0.26.9__tar.gz → 0.26.11__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 (171) hide show
  1. calkit_python-0.26.11/CITATION.cff +42 -0
  2. {calkit_python-0.26.9 → calkit_python-0.26.11}/PKG-INFO +1 -1
  3. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/__init__.py +1 -1
  4. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/check.py +10 -15
  5. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/main.py +52 -7
  6. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/notebooks.py +7 -2
  7. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/core.py +33 -2
  8. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/models/core.py +8 -1
  9. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/cli/test_check.py +29 -0
  10. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/cli/test_main.py +10 -0
  11. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_core.py +15 -0
  12. {calkit_python-0.26.9 → calkit_python-0.26.11}/.github/FUNDING.yml +0 -0
  13. {calkit_python-0.26.9 → calkit_python-0.26.11}/.github/workflows/docs.yml +0 -0
  14. {calkit_python-0.26.9 → calkit_python-0.26.11}/.github/workflows/format.yml +0 -0
  15. {calkit_python-0.26.9 → calkit_python-0.26.11}/.github/workflows/publish-test.yml +0 -0
  16. {calkit_python-0.26.9 → calkit_python-0.26.11}/.github/workflows/publish.yml +0 -0
  17. {calkit_python-0.26.9 → calkit_python-0.26.11}/.github/workflows/test.yml +0 -0
  18. {calkit_python-0.26.9 → calkit_python-0.26.11}/.gitignore +0 -0
  19. {calkit_python-0.26.9 → calkit_python-0.26.11}/.pre-commit-config.yaml +0 -0
  20. {calkit_python-0.26.9 → calkit_python-0.26.11}/.python-version +0 -0
  21. {calkit_python-0.26.9 → calkit_python-0.26.11}/CONTRIBUTING.md +0 -0
  22. {calkit_python-0.26.9 → calkit_python-0.26.11}/LICENSE +0 -0
  23. {calkit_python-0.26.9 → calkit_python-0.26.11}/Makefile +0 -0
  24. {calkit_python-0.26.9 → calkit_python-0.26.11}/README.md +0 -0
  25. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/__main__.py +0 -0
  26. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/calc.py +0 -0
  27. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/check.py +0 -0
  28. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/__init__.py +0 -0
  29. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/cloud.py +0 -0
  30. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/config.py +0 -0
  31. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/core.py +0 -0
  32. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/describe.py +0 -0
  33. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/import_.py +0 -0
  34. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/list.py +0 -0
  35. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/new.py +0 -0
  36. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/office.py +0 -0
  37. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/overleaf.py +0 -0
  38. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cli/update.py +0 -0
  39. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/cloud.py +0 -0
  40. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/conda.py +0 -0
  41. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/config.py +0 -0
  42. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/datasets.py +0 -0
  43. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/docker.py +0 -0
  44. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/dvc.py +0 -0
  45. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/environments.py +0 -0
  46. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/git.py +0 -0
  47. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/github.py +0 -0
  48. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/gui.py +0 -0
  49. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/jupyter.py +0 -0
  50. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/magics.py +0 -0
  51. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/matlab.py +0 -0
  52. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/models/__init__.py +0 -0
  53. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/models/io.py +0 -0
  54. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/models/iteration.py +0 -0
  55. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/models/pipeline.py +0 -0
  56. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/notebooks.py +0 -0
  57. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/office.py +0 -0
  58. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/ops.py +0 -0
  59. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/pipeline.py +0 -0
  60. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/releases.py +0 -0
  61. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/server.py +0 -0
  62. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/__init__.py +0 -0
  63. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/core.py +0 -0
  64. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/__init__.py +0 -0
  65. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/article/paper.tex +0 -0
  66. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/core.py +0 -0
  67. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/jfm/jfm.bst +0 -0
  68. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/jfm/jfm.cls +0 -0
  69. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
  70. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/jfm/paper.tex +0 -0
  71. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/templates/latex/jfm/upmath.sty +0 -0
  72. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/__init__.py +0 -0
  73. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/cli/__init__.py +0 -0
  74. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/cli/test_config.py +0 -0
  75. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/cli/test_list.py +0 -0
  76. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/cli/test_new.py +0 -0
  77. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/cli/test_notebooks.py +0 -0
  78. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/models/__init__.py +0 -0
  79. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/models/test_pipeline.py +0 -0
  80. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_calc.py +0 -0
  81. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_check.py +0 -0
  82. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_conda.py +0 -0
  83. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_dvc.py +0 -0
  84. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_jupyter.py +0 -0
  85. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_magics.py +0 -0
  86. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_notebooks.py +0 -0
  87. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_pipeline.py +0 -0
  88. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/tests/test_templates.py +0 -0
  89. {calkit_python-0.26.9 → calkit_python-0.26.11}/calkit/zenodo.py +0 -0
  90. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/CNAME +0 -0
  91. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/apps.md +0 -0
  92. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/calculations.md +0 -0
  93. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/calkit-yaml.md +0 -0
  94. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/cli-reference.md +0 -0
  95. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/cloud-integration.md +0 -0
  96. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/datasets.md +0 -0
  97. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/dependencies.md +0 -0
  98. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/environments.md +0 -0
  99. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/examples.md +0 -0
  100. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/help.md +0 -0
  101. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/img/c-to-the-k-white.svg +0 -0
  102. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/img/calkit-no-bg.png +0 -0
  103. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/img/connect-zenodo.png +0 -0
  104. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/index.md +0 -0
  105. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/installation.md +0 -0
  106. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/local-server.md +0 -0
  107. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/notebooks.md +0 -0
  108. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/overleaf.md +0 -0
  109. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/pipeline/index.md +0 -0
  110. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/pipeline/manual-steps.md +0 -0
  111. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/pipeline/running-and-logging.md +0 -0
  112. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/quickstart.md +0 -0
  113. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/references.md +0 -0
  114. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/releases.md +0 -0
  115. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/adding-latex-pub-docker.md +0 -0
  116. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/conda-envs.md +0 -0
  117. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/existing-project.md +0 -0
  118. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/first-project.md +0 -0
  119. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
  120. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
  121. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
  122. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
  123. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
  124. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
  125. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
  126. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
  127. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
  128. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
  129. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/push.png +0 -0
  130. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
  131. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
  132. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/chart-more-rows.png +0 -0
  133. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/create-project.png +0 -0
  134. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
  135. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/excel-chart.png +0 -0
  136. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/excel-data.png +0 -0
  137. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
  138. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/needs-clone.png +0 -0
  139. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/new-stage.png +0 -0
  140. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
  141. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
  142. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/status-more-rows.png +0 -0
  143. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
  144. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/untracked-data.png +0 -0
  145. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/updated-publication.png +0 -0
  146. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
  147. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/office/workflow-page.png +0 -0
  148. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/clone.png +0 -0
  149. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/create-project.png +0 -0
  150. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
  151. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
  152. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
  153. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/new-token.png +0 -0
  154. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/reclone.png +0 -0
  155. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
  156. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/img/run-proc.png +0 -0
  157. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/index.md +0 -0
  158. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/latex-codespaces.md +0 -0
  159. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/matlab.md +0 -0
  160. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/notebook-pipeline.md +0 -0
  161. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/office.md +0 -0
  162. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/openfoam.md +0 -0
  163. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/tutorials/procedures.md +0 -0
  164. {calkit_python-0.26.9 → calkit_python-0.26.11}/docs/version-control.md +0 -0
  165. {calkit_python-0.26.9 → calkit_python-0.26.11}/mkdocs.yml +0 -0
  166. {calkit_python-0.26.9 → calkit_python-0.26.11}/pyproject.toml +0 -0
  167. {calkit_python-0.26.9 → calkit_python-0.26.11}/scripts/install.ps1 +0 -0
  168. {calkit_python-0.26.9 → calkit_python-0.26.11}/scripts/install.sh +0 -0
  169. {calkit_python-0.26.9 → calkit_python-0.26.11}/test/pipeline.ipynb +0 -0
  170. {calkit_python-0.26.9 → calkit_python-0.26.11}/test/test-log.log +0 -0
  171. {calkit_python-0.26.9 → calkit_python-0.26.11}/uv.lock +0 -0
@@ -0,0 +1,42 @@
1
+ cff-version: 1.2.0
2
+ message: If you use these files, please cite is using these metadata.
3
+ title: Calkit
4
+ abstract: A project framework and toolkit for single button reproducible
5
+ research.
6
+ repository-code: https://github.com/calkit/calkit
7
+ authors:
8
+ - family-names: Bachant
9
+ given-names: Pete
10
+ orcid: "0000-0003-4039-6954"
11
+ - family-names: McCabe
12
+ given-names: Rebecca
13
+ orcid:
14
+ - family-names: Bisht
15
+ given-names: Mukul
16
+ orcid:
17
+ identifiers:
18
+ - description: "All Calkit releases"
19
+ type: doi
20
+ value: 10.5281/zenodo.16710624
21
+ - description: "Calkit v0.26.10"
22
+ type: doi
23
+ value: 10.5281/zenodo.16710625
24
+ - type: swh
25
+ value: swh:1:dir:50caaf3793cccc64fd9ece2fed488a0110756aff;origin=https://doi.org/10.5281/zenodo.16710624;visit=swh:1:snp:1103646b0c17db58d2485bf2134578b71aec02db;anchor=swh:1:rel:0822fe71a56c06e4097ec9eb128808aeb773e7c2;path=calkit-calkit-c418e8e
26
+ license: MIT
27
+ keywords:
28
+ - reproducible research
29
+ - reproducibility
30
+ - open science
31
+ - project framework
32
+ - data science
33
+ - Python
34
+ - containerization
35
+ references:
36
+ - authors:
37
+ - name: The DVC team and contributors
38
+ website: https://github.com/iterative
39
+ doi: 10.5281/zenodo.15828598
40
+ repository-code: https://github.com/iterative/dvc
41
+ title: "DVC: Data Version Control - Git for Data & Models"
42
+ type: software
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calkit-python
3
- Version: 0.26.9
3
+ Version: 0.26.11
4
4
  Summary: Reproducibility simplified.
5
5
  Project-URL: Homepage, https://calkit.org
6
6
  Project-URL: Issues, https://github.com/calkit/calkit/issues
@@ -1,4 +1,4 @@
1
- __version__ = "0.26.9"
1
+ __version__ = "0.26.11"
2
2
 
3
3
  from .core import * # noqa: F403, I001
4
4
  from . import git # noqa: F401
@@ -555,23 +555,18 @@ def check_env_vars(
555
555
  dotenv.load_dotenv(dotenv_path=".env")
556
556
  ck_info = calkit.load_calkit_info()
557
557
  deps = ck_info.get("dependencies", [])
558
- env_var_deps = {}
559
- for d in deps:
560
- if isinstance(d, dict):
561
- keys = list(d.keys())
562
- if len(keys) > 1:
563
- raise_error(
564
- f"Malformed dependency: {d}\n"
565
- "Dependencies with attributes should have a single key "
566
- "(their name)"
567
- )
568
- name = keys[0]
569
- attrs = list(d.values())[0]
570
- if attrs.get("kind") == "env-var":
571
- env_var_deps[name] = attrs
572
- for name, attrs in env_var_deps.items():
558
+ env_var_dep_names = calkit.get_env_var_dep_names(ck_info)
559
+ for name in env_var_dep_names:
573
560
  if verbose:
574
561
  typer.echo(f"Checking for environmental variable '{name}'")
562
+ attrs = {}
563
+ for dep in deps:
564
+ if isinstance(dep, dict) and "name" in dep:
565
+ attrs = dep
566
+ break
567
+ elif isinstance(dep, dict) and list(dep.keys()) == [name]:
568
+ attrs = dep[name]
569
+ break
575
570
  if name not in os.environ:
576
571
  typer.echo(f"Missing env var '{name}'")
577
572
  if "default" in attrs:
@@ -526,6 +526,20 @@ def save(
526
526
  "--no-push", help="Do not push to Git and DVC after committing."
527
527
  ),
528
528
  ] = False,
529
+ git_push_args: Annotated[
530
+ list[str],
531
+ typer.Option(
532
+ "--git-push",
533
+ help="Additional Git args to pass when pushing.",
534
+ ),
535
+ ] = [],
536
+ dvc_push_args: Annotated[
537
+ list[str],
538
+ typer.Option(
539
+ "--dvc-push",
540
+ help="Additional DVC args to pass when pushing.",
541
+ ),
542
+ ] = [],
529
543
  verbose: Annotated[
530
544
  bool, typer.Option("--verbose", "-v", help="Print verbose output.")
531
545
  ] = False,
@@ -579,17 +593,27 @@ def save(
579
593
  if not no_push:
580
594
  if verbose and not any_dvc:
581
595
  typer.echo("Not pushing to DVC since no DVC files were staged")
582
- push(no_dvc=not any_dvc)
596
+ push(
597
+ no_dvc=not any_dvc, git_args=git_push_args, dvc_args=dvc_push_args
598
+ )
583
599
 
584
600
 
585
601
  @app.command(name="pull")
586
602
  def pull(
587
603
  no_check_auth: Annotated[bool, typer.Option("--no-check-auth")] = False,
604
+ git_args: Annotated[
605
+ list[str],
606
+ typer.Option("--git-arg", help="Additional Git args."),
607
+ ] = [],
608
+ dvc_args: Annotated[
609
+ list[str],
610
+ typer.Option("--dvc-arg", help="Additional DVC args."),
611
+ ] = [],
588
612
  ):
589
613
  """Pull with both Git and DVC."""
590
614
  typer.echo("Git pulling")
591
615
  try:
592
- subprocess.check_call(["git", "pull"])
616
+ subprocess.check_call(["git", "pull"] + git_args)
593
617
  except subprocess.CalledProcessError:
594
618
  raise_error("Git pull failed")
595
619
  typer.echo("DVC pulling")
@@ -601,7 +625,7 @@ def pull(
601
625
  typer.echo(f"Checking authentication for DVC remote: {name}")
602
626
  calkit.dvc.set_remote_auth(remote_name=name)
603
627
  try:
604
- subprocess.check_call([sys.executable, "-m", "dvc", "pull"])
628
+ subprocess.check_call([sys.executable, "-m", "dvc", "pull"] + dvc_args)
605
629
  except subprocess.CalledProcessError:
606
630
  raise_error("DVC pull failed")
607
631
 
@@ -610,11 +634,19 @@ def pull(
610
634
  def push(
611
635
  no_check_auth: Annotated[bool, typer.Option("--no-check-auth")] = False,
612
636
  no_dvc: Annotated[bool, typer.Option("--no-dvc")] = False,
637
+ git_args: Annotated[
638
+ list[str],
639
+ typer.Option("--git-arg", help="Additional Git args."),
640
+ ] = [],
641
+ dvc_args: Annotated[
642
+ list[str],
643
+ typer.Option("--dvc-arg", help="Additional DVC args."),
644
+ ] = [],
613
645
  ):
614
646
  """Push with both Git and DVC."""
615
647
  typer.echo("Pushing to Git remote")
616
648
  try:
617
- subprocess.check_call(["git", "push"])
649
+ subprocess.check_call(["git", "push"] + git_args)
618
650
  except subprocess.CalledProcessError:
619
651
  raise_error("Git push failed")
620
652
  if not no_dvc:
@@ -629,7 +661,9 @@ def push(
629
661
  )
630
662
  calkit.dvc.set_remote_auth(remote_name=name)
631
663
  try:
632
- subprocess.check_call([sys.executable, "-m", "dvc", "push"])
664
+ subprocess.check_call(
665
+ [sys.executable, "-m", "dvc", "push"] + dvc_args
666
+ )
633
667
  except subprocess.CalledProcessError:
634
668
  raise_error("DVC push failed")
635
669
 
@@ -925,7 +959,11 @@ def run(
925
959
  # Get status of Git repo before running
926
960
  repo = git.Repo()
927
961
  git_rev = repo.head.commit.hexsha
928
- git_branch = repo.active_branch.name
962
+ try:
963
+ git_branch = repo.active_branch.name
964
+ except TypeError:
965
+ # If no branch is checked out, we are in a detached HEAD state
966
+ git_branch = None
929
967
  git_changed_files_before = calkit.git.get_changed_files(repo=repo)
930
968
  git_staged_files_before = calkit.git.get_staged_files(repo=repo)
931
969
  git_untracked_files_before = calkit.git.get_untracked_files(repo=repo)
@@ -1205,7 +1243,14 @@ def run_in_env(
1205
1243
  ]
1206
1244
  if platform:
1207
1245
  docker_cmd += ["--platform", platform]
1208
- env_vars = env.get("env-vars", {})
1246
+ env_vars = env.get("env_vars", {})
1247
+ if "env-vars" in env:
1248
+ warn("The 'env-vars' key is deprecated; use 'env_vars' instead.")
1249
+ env_vars.update(env["env-vars"])
1250
+ # Also add any project-level environmental variable dependencies
1251
+ project_env_vars = calkit.get_env_var_dep_names()
1252
+ if project_env_vars:
1253
+ env_vars.update({k: f"${k}" for k in project_env_vars})
1209
1254
  if env_vars:
1210
1255
  for key, value in env_vars.items():
1211
1256
  if isinstance(value, str):
@@ -66,6 +66,9 @@ def execute_notebook(
66
66
  "--no-check", help="Do not check environment before executing."
67
67
  ),
68
68
  ] = False,
69
+ verbose: Annotated[
70
+ bool, typer.Option("--verbose", "-v", help="Print verbose output.")
71
+ ] = False,
69
72
  ):
70
73
  """Execute notebook and place a copy in the relevant directory.
71
74
 
@@ -96,7 +99,7 @@ def execute_notebook(
96
99
  "--output",
97
100
  fname,
98
101
  ]
99
- run_in_env(cmd=cmd, env_name=env_name, no_check=no_check)
102
+ run_in_env(cmd=cmd, env_name=env_name, no_check=no_check, verbose=verbose)
100
103
  for to_fmt in to:
101
104
  if to_fmt != "notebook":
102
105
  try:
@@ -122,4 +125,6 @@ def execute_notebook(
122
125
  fname_out,
123
126
  ]
124
127
  typer.echo(f"Exporting {to_fmt}")
125
- run_in_env(cmd=cmd, env_name=env_name, no_check=True)
128
+ run_in_env(
129
+ cmd=cmd, env_name=env_name, no_check=True, verbose=verbose
130
+ )
@@ -312,9 +312,16 @@ def check_system_deps(
312
312
  for dep in deps:
313
313
  if isinstance(dep, dict):
314
314
  keys = list(dep.keys())
315
- if len(keys) != 1:
315
+ # For backwards compatibility, we allow the name to be a single key
316
+ # or we allow a `name` key to be present
317
+ if len(keys) != 1 and "name" not in keys:
318
+ raise ValueError(f"Malformed dependency: {dep}")
319
+ if len(keys) == 1:
320
+ dep_name = keys[0]
321
+ elif "name" in keys:
322
+ dep_name = dep["name"]
323
+ else:
316
324
  raise ValueError(f"Malformed dependency: {dep}")
317
- dep_name = keys[0]
318
325
  dep_kind = dep[dep_name].get("kind", "app")
319
326
  else:
320
327
  dep_name = re.split("[=<>]", dep)[0]
@@ -323,6 +330,30 @@ def check_system_deps(
323
330
  raise ValueError(f"{dep_kind} '{dep_name}' not found")
324
331
 
325
332
 
333
+ def get_env_var_dep_names(ck_info: dict | None = None) -> list[str]:
334
+ """Get a list of all environment variable names used in the project."""
335
+ if ck_info is None:
336
+ ck_info = load_calkit_info()
337
+ env_vars = []
338
+ for dep in ck_info.get("dependencies", []):
339
+ if isinstance(dep, dict):
340
+ keys = list(dep.keys())
341
+ # For backwards compatibility, we allow the name to be a single key
342
+ # or we allow a `name` key to be present
343
+ if len(keys) != 1 and "name" not in keys:
344
+ raise ValueError(f"Malformed dependency: {dep}")
345
+ if len(keys) == 1:
346
+ dep_kind = dep[keys[0]].get("kind", "app")
347
+ if dep_kind == "env-var":
348
+ env_vars.append(keys[0])
349
+ elif dep.get("kind") == "env-var":
350
+ if "name" in keys:
351
+ env_vars.append(dep["name"])
352
+ else:
353
+ raise ValueError(f"Malformed dependency: {dep}")
354
+ return env_vars
355
+
356
+
326
357
  def project_and_path_from_path(path: str) -> tuple:
327
358
  """Split a path into project and path, respecting the ``CALKIT_PROJECT``
328
359
  environmental variable if set.
@@ -240,6 +240,13 @@ class ProjectStatus(BaseModel):
240
240
  message: str | None = None
241
241
 
242
242
 
243
+ class Dependency(BaseModel):
244
+ """A system-level dependency, e.g., and app or environmental variable."""
245
+
246
+ kind: Literal["app", "env-var"]
247
+ name: str
248
+
249
+
243
250
  class ProjectInfo(BaseModel):
244
251
  """All of the project's information or metadata, written to the
245
252
  ``calkit.yaml`` file.
@@ -267,7 +274,7 @@ class ProjectInfo(BaseModel):
267
274
  git_repo_url: str | None = None
268
275
  derived_from: DerivedFromProject | None = None
269
276
  questions: list[str] = []
270
- dependencies: list = []
277
+ dependencies: list[str | dict[str, str] | Dependency] = []
271
278
  parameters: ParametersType | None = None
272
279
  metrics: dict[str, Metric] | None = None
273
280
  pipeline: Pipeline | None = None
@@ -1,8 +1,13 @@
1
1
  """Tests for ``calkit.cli.check``."""
2
2
 
3
+ import os
3
4
  import shutil
4
5
  import subprocess
5
6
 
7
+ import pytest
8
+
9
+ import calkit
10
+
6
11
 
7
12
  def test_check_venv(tmp_dir):
8
13
  with open("reqs.txt", "w") as f:
@@ -43,3 +48,27 @@ def test_check_venv(tmp_dir):
43
48
  with open("lock.txt") as f:
44
49
  lock_txt_3 = f.read()
45
50
  assert "polars==1.0.0" in lock_txt_3
51
+
52
+
53
+ def test_check_env_vars(tmp_dir):
54
+ subprocess.check_call(["calkit", "init"])
55
+ ck_info = {
56
+ "dependencies": [
57
+ {"name": "MY_ENV_VAR", "kind": "env-var"},
58
+ {"name": "MY_APP", "kind": "app"},
59
+ "something-else",
60
+ {"MY_OTHER_ENV_VAR": {"kind": "env-var"}},
61
+ ]
62
+ }
63
+ with open("calkit.yaml", "w") as f:
64
+ calkit.ryaml.dump(ck_info, f)
65
+ subprocess.check_call(
66
+ ["calkit", "check", "env-vars"],
67
+ env=os.environ.copy()
68
+ | {"MY_ENV_VAR": "value1", "MY_OTHER_ENV_VAR": "value2"},
69
+ )
70
+ with pytest.raises(subprocess.CalledProcessError):
71
+ subprocess.check_call(
72
+ ["calkit", "check", "env-vars"],
73
+ env=os.environ.copy() | {"MY_ENV_VAR": "value1"},
74
+ )
@@ -407,8 +407,18 @@ def test_run(tmp_dir):
407
407
  "main",
408
408
  ]
409
409
  )
410
+ subprocess.check_call(
411
+ ["calkit", "save", "-am", "Create pipeline", "--no-push"]
412
+ )
410
413
  out = subprocess.check_output(["calkit", "run"], text=True)
411
414
  print(out)
415
+ subprocess.check_call(
416
+ ["calkit", "save", "-am", "Run pipeline", "--no-push"]
417
+ )
418
+ # Make sure we can run on a detached head
419
+ repo = git.Repo()
420
+ repo.git.checkout("HEAD^")
421
+ out = subprocess.check_output(["calkit", "run"], text=True)
412
422
 
413
423
 
414
424
  def test_stage_run_info_from_log_content():
@@ -63,3 +63,18 @@ def test_load_calkit_info(tmp_dir):
63
63
  ck_info = calkit.load_calkit_info(process_includes=True)
64
64
  assert ck_info["environments"]["env1"]["image"] == "ubuntu"
65
65
  assert ck_info["environments"]["env2"]["image"] == "openfoam"
66
+
67
+
68
+ def test_get_env_var_dep_names():
69
+ ck_info = {
70
+ "dependencies": [
71
+ {"name": "MY_ENV_VAR", "kind": "env-var"},
72
+ {"name": "MY_APP", "kind": "app"},
73
+ "something-else",
74
+ {"MY_OTHER_ENV_VAR": {"kind": "env-var"}},
75
+ ]
76
+ }
77
+ assert calkit.get_env_var_dep_names(ck_info) == [
78
+ "MY_ENV_VAR",
79
+ "MY_OTHER_ENV_VAR",
80
+ ]
File without changes
File without changes
File without changes