calkit-python 0.41.3__tar.gz → 0.41.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 (336) hide show
  1. calkit_python-0.41.4/.gitattributes +1 -0
  2. {calkit_python-0.41.3 → calkit_python-0.41.4}/PKG-INFO +1 -1
  3. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/check.py +1 -1
  4. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/main/core.py +6 -4
  5. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/new.py +3 -3
  6. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/scheduler.py +16 -7
  7. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/detect.py +18 -11
  8. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/dvc/core.py +70 -0
  9. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/dvc/zip.py +7 -2
  10. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/environments.py +17 -9
  11. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/git.py +4 -4
  12. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/overleaf.py +4 -1
  13. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/pipeline.py +16 -39
  14. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/releases.py +2 -2
  15. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/main/test_core.py +25 -0
  16. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/main/test_xr.py +5 -0
  17. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_check.py +9 -0
  18. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_latex.py +15 -0
  19. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_new.py +5 -0
  20. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_notebooks.py +9 -0
  21. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_overleaf.py +5 -1
  22. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_scheduler.py +7 -0
  23. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_update.py +5 -0
  24. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/dvc/test_core.py +88 -0
  25. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_conda.py +17 -2
  26. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_git.py +14 -0
  27. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_install.py +13 -0
  28. {calkit_python-0.41.3 → calkit_python-0.41.4}/.claude-plugin/marketplace.json +0 -0
  29. {calkit_python-0.41.3 → calkit_python-0.41.4}/.gitignore +0 -0
  30. {calkit_python-0.41.3 → calkit_python-0.41.4}/.pre-commit-config.yaml +0 -0
  31. {calkit_python-0.41.3 → calkit_python-0.41.4}/.prettierignore +0 -0
  32. {calkit_python-0.41.3 → calkit_python-0.41.4}/.python-version +0 -0
  33. {calkit_python-0.41.3 → calkit_python-0.41.4}/.vscode/launch.json +0 -0
  34. {calkit_python-0.41.3 → calkit_python-0.41.4}/.vscode/tasks.json +0 -0
  35. {calkit_python-0.41.3 → calkit_python-0.41.4}/.yarnrc.yml +0 -0
  36. {calkit_python-0.41.3 → calkit_python-0.41.4}/AGENTS.md +0 -0
  37. {calkit_python-0.41.3 → calkit_python-0.41.4}/CITATION.cff +0 -0
  38. {calkit_python-0.41.3 → calkit_python-0.41.4}/CODE_OF_CONDUCT.md +0 -0
  39. {calkit_python-0.41.3 → calkit_python-0.41.4}/CONTRIBUTING.md +0 -0
  40. {calkit_python-0.41.3 → calkit_python-0.41.4}/LICENSE +0 -0
  41. {calkit_python-0.41.3 → calkit_python-0.41.4}/Makefile +0 -0
  42. {calkit_python-0.41.3 → calkit_python-0.41.4}/README.md +0 -0
  43. {calkit_python-0.41.3 → calkit_python-0.41.4}/agent-plugin/.claude-plugin/plugin.json +0 -0
  44. {calkit_python-0.41.3 → calkit_python-0.41.4}/agent-plugin/skills/add-pipeline-stage/SKILL.md +0 -0
  45. {calkit_python-0.41.3 → calkit_python-0.41.4}/agent-plugin/skills/conventions/SKILL.md +0 -0
  46. {calkit_python-0.41.3 → calkit_python-0.41.4}/agent-plugin/skills/create-pipeline/SKILL.md +0 -0
  47. {calkit_python-0.41.3 → calkit_python-0.41.4}/babel.config.js +0 -0
  48. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/__init__.py +0 -0
  49. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/__main__.py +0 -0
  50. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/calc.py +0 -0
  51. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/check.py +0 -0
  52. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/__init__.py +0 -0
  53. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/cloud.py +0 -0
  54. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/config.py +0 -0
  55. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/core.py +0 -0
  56. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/describe.py +0 -0
  57. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/dev.py +0 -0
  58. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/import_.py +0 -0
  59. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/latex.py +0 -0
  60. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/list.py +0 -0
  61. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/main/__init__.py +0 -0
  62. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/main/xr.py +0 -0
  63. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/notebooks.py +0 -0
  64. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/office.py +0 -0
  65. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/overleaf.py +0 -0
  66. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cli/update.py +0 -0
  67. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/cloud.py +0 -0
  68. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/conda.py +0 -0
  69. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/config.py +0 -0
  70. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/core.py +0 -0
  71. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/datasets.py +0 -0
  72. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/dependencies.py +0 -0
  73. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/docker.py +0 -0
  74. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/dvc/__init__.py +0 -0
  75. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/fs.py +0 -0
  76. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/github.py +0 -0
  77. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/gui.py +0 -0
  78. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/install.py +0 -0
  79. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/invenio.py +0 -0
  80. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/julia.py +0 -0
  81. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/jupyter.py +0 -0
  82. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/jupyterlab/__init__.py +0 -0
  83. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/jupyterlab/routes.py +0 -0
  84. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/package.json +0 -0
  85. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/schemas/calkit/package.json.orig +0 -0
  86. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/schemas/calkit/plugin.json +0 -0
  87. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
  88. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
  89. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
  90. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/909.e3f9cc3408834a7fdcc3.js +0 -0
  91. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
  92. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
  93. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
  94. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/remoteEntry.65469af996e7a96aa983.js +0 -0
  95. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/style.js +0 -0
  96. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/labextension/static/third-party-licenses.json +0 -0
  97. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/licenses.py +0 -0
  98. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/magics.py +0 -0
  99. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/matlab.py +0 -0
  100. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/models/__init__.py +0 -0
  101. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/models/core.py +0 -0
  102. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/models/io.py +0 -0
  103. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/models/iteration.py +0 -0
  104. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/models/pipeline.py +0 -0
  105. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/notebooks.py +0 -0
  106. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/office.py +0 -0
  107. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/ops.py +0 -0
  108. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/server.py +0 -0
  109. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/__init__.py +0 -0
  110. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/core.py +0 -0
  111. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/__init__.py +0 -0
  112. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/article/paper.tex +0 -0
  113. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/core.py +0 -0
  114. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/jfm/jfm.bst +0 -0
  115. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/jfm/jfm.cls +0 -0
  116. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
  117. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/jfm/paper.tex +0 -0
  118. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/templates/latex/jfm/upmath.sty +0 -0
  119. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/__init__.py +0 -0
  120. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/__init__.py +0 -0
  121. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/main/__init__.py +0 -0
  122. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/main/test_subprojects.py +0 -0
  123. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_cloud.py +0 -0
  124. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_config.py +0 -0
  125. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_import.py +0 -0
  126. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/cli/test_list.py +0 -0
  127. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/dvc/__init__.py +0 -0
  128. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/dvc/test_zip.py +0 -0
  129. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/jupyterlab/__init__.py +0 -0
  130. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/jupyterlab/test_routes.py +0 -0
  131. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/models/__init__.py +0 -0
  132. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/models/test_iteration.py +0 -0
  133. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/models/test_pipeline.py +0 -0
  134. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_calc.py +0 -0
  135. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_check.py +0 -0
  136. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_cloud.py +0 -0
  137. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_core.py +0 -0
  138. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_dependencies.py +0 -0
  139. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_detect.py +0 -0
  140. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_docker.py +0 -0
  141. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_environments.py +0 -0
  142. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_fs.py +0 -0
  143. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_invenio.py +0 -0
  144. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_julia.py +0 -0
  145. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_jupyter.py +0 -0
  146. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_magics.py +0 -0
  147. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_matlab.py +0 -0
  148. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_notebooks.py +0 -0
  149. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_pipeline.py +0 -0
  150. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_releases.py +0 -0
  151. {calkit_python-0.41.3 → calkit_python-0.41.4}/calkit/tests/test_templates.py +0 -0
  152. {calkit_python-0.41.3 → calkit_python-0.41.4}/conftest.py +0 -0
  153. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/CNAME +0 -0
  154. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/ai-tools.md +0 -0
  155. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/apps.md +0 -0
  156. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/calculations.md +0 -0
  157. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/calkit-yaml.md +0 -0
  158. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/cli-reference.md +0 -0
  159. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/cloud-integration.md +0 -0
  160. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/datasets.md +0 -0
  161. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/dependencies.md +0 -0
  162. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/environments.md +0 -0
  163. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/examples.md +0 -0
  164. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/governance.md +0 -0
  165. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/help.md +0 -0
  166. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/hpc.md +0 -0
  167. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/c-to-the-k-white.svg +0 -0
  168. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/calkit-fragmentation-compendium.png +0 -0
  169. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/calkit-no-bg.png +0 -0
  170. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/connect-zenodo.png +0 -0
  171. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/jupyterlab/all-green.png +0 -0
  172. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/jupyterlab/collect-data-stale.png +0 -0
  173. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/jupyterlab/new-env.png +0 -0
  174. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/jupyterlab/new-notebook.png +0 -0
  175. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/jupyterlab/pipeline-badge.png +0 -0
  176. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/jupyterlab-params.png +0 -0
  177. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/plos-osi-code-2024-03.png +0 -0
  178. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/img/vscode-nb-params.png +0 -0
  179. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/index.md +0 -0
  180. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/installation.md +0 -0
  181. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/jupyterlab.md +0 -0
  182. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/local-server.md +0 -0
  183. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/notebooks.md +0 -0
  184. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/overleaf.md +0 -0
  185. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/pipeline/index.md +0 -0
  186. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/pipeline/manual-steps.md +0 -0
  187. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/pipeline/running-and-logging.md +0 -0
  188. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/quickstart.md +0 -0
  189. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/references.md +0 -0
  190. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/releases.md +0 -0
  191. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/reproducibility.md +0 -0
  192. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/subprojects.md +0 -0
  193. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/adding-latex-pub-docker.md +0 -0
  194. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/conda-envs.md +0 -0
  195. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/existing-project.md +0 -0
  196. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/first-project.md +0 -0
  197. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/github-actions.md +0 -0
  198. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/actions-repo-secrets.png +0 -0
  199. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
  200. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
  201. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
  202. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
  203. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
  204. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
  205. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
  206. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
  207. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
  208. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
  209. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/push.png +0 -0
  210. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
  211. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
  212. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/chart-more-rows.png +0 -0
  213. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/create-project.png +0 -0
  214. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
  215. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/excel-chart.png +0 -0
  216. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/excel-data.png +0 -0
  217. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
  218. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/needs-clone.png +0 -0
  219. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/new-stage.png +0 -0
  220. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
  221. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
  222. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/status-more-rows.png +0 -0
  223. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
  224. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/untracked-data.png +0 -0
  225. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/updated-publication.png +0 -0
  226. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
  227. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/office/workflow-page.png +0 -0
  228. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/clone.png +0 -0
  229. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/create-project.png +0 -0
  230. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
  231. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
  232. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
  233. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/new-token.png +0 -0
  234. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/reclone.png +0 -0
  235. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
  236. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/quick-actions.png +0 -0
  237. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/run-proc.png +0 -0
  238. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/vscode-slurm-notebook/create-calkit-env.png +0 -0
  239. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/vscode-slurm-notebook/create-inner-env.png +0 -0
  240. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/vscode-slurm-notebook/create-new-calkit-env.png +0 -0
  241. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/vscode-slurm-notebook/select-calkit-env.png +0 -0
  242. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/vscode-slurm-notebook/slurm-job-running.png +0 -0
  243. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/vscode-slurm-notebook/slurm-launch-options.png +0 -0
  244. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/img/vscode-slurm-notebook/starting-slurm-job.png +0 -0
  245. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/index.md +0 -0
  246. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/jupyterlab.md +0 -0
  247. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/latex-codespaces.md +0 -0
  248. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/matlab.md +0 -0
  249. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/notebook-pipeline.md +0 -0
  250. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/office.md +0 -0
  251. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/openfoam.md +0 -0
  252. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/procedures.md +0 -0
  253. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/tutorials/vscode-slurm-notebook.md +0 -0
  254. {calkit_python-0.41.3 → calkit_python-0.41.4}/docs/version-control.md +0 -0
  255. {calkit_python-0.41.3 → calkit_python-0.41.4}/flake.lock +0 -0
  256. {calkit_python-0.41.3 → calkit_python-0.41.4}/flake.nix +0 -0
  257. {calkit_python-0.41.3 → calkit_python-0.41.4}/install.json +0 -0
  258. {calkit_python-0.41.3 → calkit_python-0.41.4}/jest.config.js +0 -0
  259. {calkit_python-0.41.3 → calkit_python-0.41.4}/jupyter-config/server-config/calkit.json +0 -0
  260. {calkit_python-0.41.3 → calkit_python-0.41.4}/mkdocs.yml +0 -0
  261. {calkit_python-0.41.3 → calkit_python-0.41.4}/package.json +0 -0
  262. {calkit_python-0.41.3 → calkit_python-0.41.4}/pyproject.toml +0 -0
  263. {calkit_python-0.41.3 → calkit_python-0.41.4}/schema/plugin.json +0 -0
  264. {calkit_python-0.41.3 → calkit_python-0.41.4}/scripts/generate-docs-references.py +0 -0
  265. {calkit_python-0.41.3 → calkit_python-0.41.4}/scripts/install.ps1 +0 -0
  266. {calkit_python-0.41.3 → calkit_python-0.41.4}/scripts/install.sh +0 -0
  267. {calkit_python-0.41.3 → calkit_python-0.41.4}/scripts/make-calk9.sh +0 -0
  268. {calkit_python-0.41.3 → calkit_python-0.41.4}/scripts/sync-docs.py +0 -0
  269. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/__tests__/useQueries.spec.ts +0 -0
  270. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/calkit-config.ts +0 -0
  271. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/cell-output-marker.ts +0 -0
  272. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/commit-dialog.tsx +0 -0
  273. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/environment-editor.tsx +0 -0
  274. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/notebook-registration.tsx +0 -0
  275. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/notebook-toolbar.tsx +0 -0
  276. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/pipeline-status-bar.tsx +0 -0
  277. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/project-info-editor.tsx +0 -0
  278. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/sidebar-settings.tsx +0 -0
  279. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/sidebar.tsx +0 -0
  280. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/components/stage-editor.tsx +0 -0
  281. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/feature-flags.ts +0 -0
  282. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/file-browser-menu.ts +0 -0
  283. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/hooks/__tests__/useQueries.test.tsx +0 -0
  284. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/hooks/useQueries.ts +0 -0
  285. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/icons.ts +0 -0
  286. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/index.ts +0 -0
  287. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/io-tracker.ts +0 -0
  288. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/pipeline-state.ts +0 -0
  289. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/queryClient.ts +0 -0
  290. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/request.ts +0 -0
  291. {calkit_python-0.41.3 → calkit_python-0.41.4}/src/shims-mainmenu.d.ts +0 -0
  292. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/base.css +0 -0
  293. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/cell-output-marker.css +0 -0
  294. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/environment-editor.css +0 -0
  295. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/environment-selector.css +0 -0
  296. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/img/calkit-no-bg.png +0 -0
  297. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/index.css +0 -0
  298. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/index.js +0 -0
  299. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/notebook-toolbar.css +0 -0
  300. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/pipeline-status-bar.css +0 -0
  301. {calkit_python-0.41.3 → calkit_python-0.41.4}/style/sidebar.css +0 -0
  302. {calkit_python-0.41.3 → calkit_python-0.41.4}/test/dvc-md5-dir/osx-arm64.txt +0 -0
  303. {calkit_python-0.41.3 → calkit_python-0.41.4}/test/nb-julia.ipynb +0 -0
  304. {calkit_python-0.41.3 → calkit_python-0.41.4}/test/nb-params.ipynb +0 -0
  305. {calkit_python-0.41.3 → calkit_python-0.41.4}/test/nb-subdir.ipynb +0 -0
  306. {calkit_python-0.41.3 → calkit_python-0.41.4}/test/pipeline.ipynb +0 -0
  307. {calkit_python-0.41.3 → calkit_python-0.41.4}/test/script.py +0 -0
  308. {calkit_python-0.41.3 → calkit_python-0.41.4}/test/test-log.log +0 -0
  309. {calkit_python-0.41.3 → calkit_python-0.41.4}/tsconfig.json +0 -0
  310. {calkit_python-0.41.3 → calkit_python-0.41.4}/tsconfig.test.json +0 -0
  311. {calkit_python-0.41.3 → calkit_python-0.41.4}/ui-tests/.gitignore +0 -0
  312. {calkit_python-0.41.3 → calkit_python-0.41.4}/ui-tests/README.md +0 -0
  313. {calkit_python-0.41.3 → calkit_python-0.41.4}/ui-tests/jupyter_server_test_config.py +0 -0
  314. {calkit_python-0.41.3 → calkit_python-0.41.4}/ui-tests/package.json +0 -0
  315. {calkit_python-0.41.3 → calkit_python-0.41.4}/ui-tests/playwright.config.js +0 -0
  316. {calkit_python-0.41.3 → calkit_python-0.41.4}/ui-tests/tests/calkit.spec.ts +0 -0
  317. {calkit_python-0.41.3 → calkit_python-0.41.4}/ui-tests/yarn.lock +0 -0
  318. {calkit_python-0.41.3 → calkit_python-0.41.4}/uv.lock +0 -0
  319. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/.gitignore +0 -0
  320. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/.vscodeignore +0 -0
  321. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/CHANGELOG.md +0 -0
  322. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/LICENSE +0 -0
  323. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/README.md +0 -0
  324. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/images/calkit-no-bg.png +0 -0
  325. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/package-lock.json +0 -0
  326. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/package.json +0 -0
  327. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/scripts/set-proposed-api.js +0 -0
  328. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/src/environments.ts +0 -0
  329. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/src/extension.ts +0 -0
  330. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/src/notebooks.ts +0 -0
  331. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/src/test/environments.test.ts +0 -0
  332. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/src/test/kernel-selection.test.ts +0 -0
  333. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/src/test/notebooks.test.ts +0 -0
  334. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/src/types.ts +0 -0
  335. {calkit_python-0.41.3 → calkit_python-0.41.4}/vscode-ext/tsconfig.json +0 -0
  336. {calkit_python-0.41.3 → calkit_python-0.41.4}/yarn.lock +0 -0
@@ -0,0 +1 @@
1
+ test/dvc-md5-dir/** text eol=lf
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: calkit-python
3
- Version: 0.41.3
3
+ Version: 0.41.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
@@ -381,7 +381,7 @@ def check_environment(
381
381
  quiet=not verbose,
382
382
  )
383
383
  elif env["kind"] == "pixi":
384
- cmd = ["pixi", "lock"]
384
+ cmd = ["pixi", "install"]
385
385
  env_dir = os.path.dirname(env["path"])
386
386
  if env_dir:
387
387
  cmd += ["--manifest-path", env["path"]]
@@ -502,10 +502,11 @@ def get_status(
502
502
  if "dvc" in categories:
503
503
  try:
504
504
  dvc_repo = calkit.dvc.get_dvc_repo()
505
- data_status = dvc_repo.data_status()
506
- if isinstance(data_status, dict):
507
- data_status.pop("git", None)
508
- status_dict["dvc"] = data_status
505
+ data_status = dict(dvc_repo.data_status())
506
+ data_status.pop("git", None)
507
+ status_dict["dvc"] = calkit.dvc.data_status_as_posix(
508
+ data_status
509
+ )
509
510
  except Exception as e:
510
511
  status_dict["dvc"] = {"error": f"{e.__class__.__name__}: {e}"}
511
512
  if "pipeline" in categories or "dvc" in categories:
@@ -557,6 +558,7 @@ def get_status(
557
558
  dvc_repo = calkit.dvc.get_dvc_repo()
558
559
  raw = dict(dvc_repo.data_status())
559
560
  raw.pop("git", None)
561
+ raw = calkit.dvc.data_status_as_posix(raw)
560
562
  typer.echo(_format_dvc_data_status(raw, zip_path_map))
561
563
  if "pipeline" in categories or "dvc" in categories:
562
564
  print_sep("Pipeline")
@@ -1152,10 +1152,10 @@ def new_publication(
1152
1152
  deps += stage.get("outs", [])
1153
1153
  # Create publication object
1154
1154
  if template_type == "latex":
1155
- pub_fpath = os.path.join(
1155
+ pub_fpath = pathlib.Path(
1156
1156
  path,
1157
1157
  template_obj.target.removesuffix(".tex") + ".pdf", # type: ignore
1158
- )
1158
+ ).as_posix()
1159
1159
  else:
1160
1160
  pub_fpath = path
1161
1161
  if not overwrite and pub_fpath in pub_paths:
@@ -1190,7 +1190,7 @@ def new_publication(
1190
1190
  stage = LatexStage(
1191
1191
  kind="latex",
1192
1192
  environment=env_name,
1193
- target_path=os.path.join(path, template_obj.target), # type: ignore
1193
+ target_path=pathlib.Path(path, template_obj.target).as_posix(), # type: ignore
1194
1194
  outputs=[pub_fpath],
1195
1195
  ).model_dump()
1196
1196
  if "pipeline" not in ck_info:
@@ -92,9 +92,9 @@ def _mock_enabled() -> bool:
92
92
 
93
93
 
94
94
  def _require_posix_mock() -> None:
95
- # The mock backend uses bash, new sessions, and process-group signals.
96
- if os.name != "posix":
97
- raise_error("CALKIT_MOCK_SCHEDULER is only supported on POSIX systems")
95
+ # The mock backend uses bash; if that is missing, the mock cannot run.
96
+ if shutil.which("bash") is None:
97
+ raise_error("CALKIT_MOCK_SCHEDULER requires bash on PATH")
98
98
 
99
99
 
100
100
  def _ensure_mock_dir() -> None:
@@ -177,13 +177,19 @@ def _mock_submit(job_id: str, job_command: str, log_path: str) -> int:
177
177
  env = dict(os.environ)
178
178
  env.setdefault("PBS_O_WORKDIR", os.getcwd())
179
179
  with open(log_path, "w") as log_file:
180
- proc = subprocess.Popen(
181
- ["bash", "-c", wrapped],
180
+ popen_kwargs = dict(
182
181
  stdout=log_file,
183
182
  stderr=subprocess.STDOUT,
184
- start_new_session=True,
185
183
  env=env,
186
184
  )
185
+ if os.name == "posix":
186
+ popen_kwargs["start_new_session"] = True
187
+ elif hasattr(subprocess, "CREATE_NEW_PROCESS_GROUP"):
188
+ popen_kwargs["creationflags"] = subprocess.CREATE_NEW_PROCESS_GROUP
189
+ proc = subprocess.Popen(
190
+ ["bash", "-c", wrapped],
191
+ **popen_kwargs,
192
+ )
187
193
  return proc.pid
188
194
 
189
195
 
@@ -192,7 +198,10 @@ def _mock_cancel(job_id: str) -> tuple[bool, str]:
192
198
  pid = _mock_pid(job_id)
193
199
  if pid is not None:
194
200
  try:
195
- os.killpg(os.getpgid(pid), signal.SIGTERM)
201
+ if os.name == "posix":
202
+ os.killpg(os.getpgid(pid), signal.SIGTERM)
203
+ else:
204
+ os.kill(pid, signal.SIGTERM)
196
205
  except (ProcessLookupError, PermissionError):
197
206
  pass
198
207
  # Drop a sentinel so later liveness checks report the job as finished.
@@ -10,6 +10,7 @@ import os
10
10
  import re
11
11
  import shlex
12
12
  import sys
13
+ from pathlib import Path
13
14
  from typing import Literal
14
15
 
15
16
  NotebookLanguage = Literal["python", "julia", "r"]
@@ -114,7 +115,7 @@ def detect_julia_script_io(
114
115
  if not os.path.isabs(match):
115
116
  full_path = os.path.join(script_dir, match)
116
117
  if os.path.exists(full_path):
117
- inputs.append(os.path.relpath(full_path))
118
+ inputs.append(Path(os.path.relpath(full_path)).as_posix())
118
119
  elif _is_valid_project_path(match):
119
120
  inputs.append(match)
120
121
  read_patterns = [
@@ -421,26 +422,29 @@ def detect_latex_io(tex_path: str) -> dict[str, list[str]]:
421
422
  for pattern, pattern_type in patterns:
422
423
  matches = re.findall(pattern, content)
423
424
  for match in matches:
425
+
426
+ def _resolve(name: str) -> str:
427
+ return Path(
428
+ os.path.normpath(os.path.join(tex_dir, name))
429
+ ).as_posix()
430
+
424
431
  if pattern_type == "bib":
425
432
  files = [f.strip() for f in match.split(",")]
426
433
  for f in files:
427
434
  if not f.endswith(".bib"):
428
435
  f += ".bib"
429
436
  # Resolve relative to the document directory
430
- resolved = os.path.normpath(os.path.join(tex_dir, f))
431
- inputs.append(resolved)
437
+ inputs.append(_resolve(f))
432
438
  elif pattern_type == "tex":
433
439
  filename = match
434
440
  if not filename.endswith(".tex"):
435
441
  filename += ".tex"
436
442
  # Resolve relative to the document directory
437
- resolved = os.path.normpath(os.path.join(tex_dir, filename))
438
- inputs.append(resolved)
443
+ inputs.append(_resolve(filename))
439
444
  else:
440
445
  # Include graphics or other files
441
446
  # Resolve relative to the document directory
442
- resolved = os.path.normpath(os.path.join(tex_dir, match))
443
- inputs.append(resolved)
447
+ inputs.append(_resolve(match))
444
448
  # Filter and deduplicate inputs
445
449
  inputs = [p for p in inputs if _is_valid_project_path(p)]
446
450
  inputs = list(dict.fromkeys(inputs))
@@ -774,6 +778,9 @@ def _detect_python_code_io(
774
778
  except ValueError:
775
779
  # If paths are on different drives (Windows), use normalized path
776
780
  rel_path = full_path
781
+ # Always emit posix separators so downstream comparisons are stable
782
+ # across platforms.
783
+ rel_path = Path(rel_path).as_posix()
777
784
  # Strip leading ../ for paths outside project root
778
785
  while rel_path.startswith("../"):
779
786
  rel_path = rel_path[3:]
@@ -938,7 +945,7 @@ def _detect_julia_code_io(
938
945
  if not os.path.isabs(match):
939
946
  full_path = os.path.join(script_dir, match)
940
947
  if os.path.exists(full_path):
941
- inputs.append(os.path.relpath(full_path))
948
+ inputs.append(Path(os.path.relpath(full_path)).as_posix())
942
949
  elif _is_valid_project_path(match):
943
950
  inputs.append(match)
944
951
  read_patterns = [
@@ -978,12 +985,12 @@ def _resolve_python_import(
978
985
  if os.path.exists(file_path) and _is_valid_project_path(
979
986
  os.path.relpath(file_path)
980
987
  ):
981
- return os.path.relpath(file_path)
988
+ return Path(os.path.relpath(file_path)).as_posix()
982
989
  init_path = os.path.join(search_dir, module_path, "__init__.py")
983
990
  if os.path.exists(init_path) and _is_valid_project_path(
984
991
  os.path.relpath(init_path)
985
992
  ):
986
- return os.path.relpath(init_path)
993
+ return Path(os.path.relpath(init_path)).as_posix()
987
994
  return None
988
995
 
989
996
 
@@ -1018,7 +1025,7 @@ def _detect_r_code_io(
1018
1025
  if not os.path.isabs(match):
1019
1026
  full_path = os.path.join(script_dir, match)
1020
1027
  if os.path.exists(full_path):
1021
- inputs.append(os.path.relpath(full_path))
1028
+ inputs.append(Path(os.path.relpath(full_path)).as_posix())
1022
1029
  elif _is_valid_project_path(match):
1023
1030
  inputs.append(match)
1024
1031
  # Read patterns that capture variables, file.path() expressions, or literals
@@ -26,6 +26,24 @@ logger.setLevel(logging.INFO)
26
26
  USE_CK_REMOTE_BY_DEFAULT = True
27
27
 
28
28
 
29
+ class _FrozenStageWarningFilter(logging.Filter):
30
+ """Drop DVC's "stage is frozen" warnings.
31
+
32
+ DVC emits these for every frozen stage on every ``status``/``repro`` call
33
+ ("... not going to be shown in the status output." and "... not going to
34
+ be reproduced."). Frozen stages are pinned by design, so the warnings are
35
+ noise — the substring shared by both variants is matched here.
36
+ """
37
+
38
+ def filter(self, record: logging.LogRecord) -> bool:
39
+ return "is frozen. Its dependencies are" not in record.getMessage()
40
+
41
+
42
+ _frozen_stage_warning_filter = _FrozenStageWarningFilter()
43
+ for _name in ("dvc.repo.reproduce", "dvc.repo.status"):
44
+ logging.getLogger(_name).addFilter(_frozen_stage_warning_filter)
45
+
46
+
29
47
  class CalkitDVCFileSystem(ObjectFileSystem):
30
48
  """DVC-facing filesystem wrapper for the ``ck://`` scheme."""
31
49
 
@@ -614,3 +632,55 @@ def hash_path(path: str) -> dict:
614
632
  return hash_file(path)
615
633
  else:
616
634
  raise ValueError(f"Path does not exist: {path}")
635
+
636
+
637
+ def _path_item_as_posix(item):
638
+ # Renamed entries are dicts like {"old": ..., "new": ...}.
639
+ if isinstance(item, dict):
640
+ return {k: Path(v).as_posix() for k, v in item.items()}
641
+ return Path(item).as_posix()
642
+
643
+
644
+ def data_status_as_posix(data_status: dict) -> dict:
645
+ """Convert all paths in DVC data status to posix format.
646
+
647
+ We skip the ``git`` entry since Git already formats as posix.
648
+ """
649
+ data_status_fmt = {}
650
+ for cat, obj in data_status.items():
651
+ if cat == "git":
652
+ data_status_fmt[cat] = obj
653
+ elif isinstance(obj, list):
654
+ data_status_fmt[cat] = [_path_item_as_posix(p) for p in obj]
655
+ elif isinstance(obj, dict):
656
+ obj_fmt = {}
657
+ for cat2, obj_i in obj.items():
658
+ obj_fmt[cat2] = [_path_item_as_posix(p) for p in obj_i]
659
+ data_status_fmt[cat] = obj_fmt
660
+ else:
661
+ data_status_fmt[cat] = obj
662
+ return data_status_fmt
663
+
664
+
665
+ def status_as_posix(status: dict) -> dict:
666
+ """Convert all paths in repo status to posix format."""
667
+ status_fmt = {}
668
+ for stage_name, st_list in status.items():
669
+ st_list_fmt = []
670
+ for st_dict in st_list:
671
+ if isinstance(st_dict, str):
672
+ st_list_fmt.append(st_dict)
673
+ continue
674
+ st_dict_fmt = {}
675
+ for st_cat, path_st_dict in st_dict.items():
676
+ if not isinstance(path_st_dict, dict):
677
+ # e.g. {"changed command": "python src/new-script.py"}
678
+ st_dict_fmt[st_cat] = path_st_dict
679
+ continue
680
+ path_st_dict_fmt = {}
681
+ for p, st in path_st_dict.items():
682
+ path_st_dict_fmt[Path(p).as_posix()] = st
683
+ st_dict_fmt[st_cat] = path_st_dict_fmt
684
+ st_list_fmt.append(st_dict_fmt)
685
+ status_fmt[stage_name] = st_list_fmt
686
+ return status_fmt
@@ -113,7 +113,7 @@ class SyncRecord(BaseModel):
113
113
 
114
114
  def make_zip_path(workspace_path: str) -> str:
115
115
  """Make a zip path for a given workspace path."""
116
- return os.path.join(ZIPS_DIR, "files", workspace_path + ".zip")
116
+ return Path(ZIPS_DIR, "files", f"{workspace_path}.zip").as_posix()
117
117
 
118
118
 
119
119
  def _path_map_path(wdir: str | None = None) -> str:
@@ -272,6 +272,7 @@ def get_sync_record(
272
272
  ) -> SyncRecord | None:
273
273
  """Get a sync record for a given workspace path."""
274
274
  _check_local_dir(wdir)
275
+ workspace_path = Path(workspace_path).as_posix()
275
276
  with SqliteDict(_sync_records_path(wdir)) as db:
276
277
  raw = db.get(workspace_path)
277
278
  if raw is not None:
@@ -283,13 +284,14 @@ def write_sync_record(record: SyncRecord, wdir: str | None = None):
283
284
  """Write a sync record."""
284
285
  _check_local_dir(wdir)
285
286
  with SqliteDict(_sync_records_path(wdir)) as db:
286
- db[record.workspace_path] = record.model_dump()
287
+ db[Path(record.workspace_path).as_posix()] = record.model_dump()
287
288
  db.commit()
288
289
 
289
290
 
290
291
  def delete_sync_record(workspace_path: str, wdir: str | None = None):
291
292
  """Delete a sync record."""
292
293
  _check_local_dir(wdir)
294
+ workspace_path = Path(workspace_path).as_posix()
293
295
  with SqliteDict(_sync_records_path(wdir)) as db:
294
296
  if workspace_path in db:
295
297
  del db[workspace_path]
@@ -466,6 +468,9 @@ def sync_one(
466
468
  workspace_path = os.path.join(wdir, workspace_path)
467
469
  if zip_path is not None:
468
470
  zip_path = os.path.join(wdir, zip_path)
471
+ workspace_path = Path(workspace_path).as_posix()
472
+ if zip_path is not None:
473
+ zip_path = Path(zip_path).as_posix()
469
474
  return _sync_one(workspace_path, zip_path, direction, wdir=wdir)
470
475
 
471
476
 
@@ -38,6 +38,12 @@ CONDA_VENV_ARCHS = [
38
38
  ]
39
39
  ENV_CHECK_CACHE_TTL_SECONDS = 3600
40
40
  KINDS_NO_CHECK = ["_system", "ssh"]
41
+
42
+
43
+ def _as_posix_path(path: str) -> str:
44
+ return Path(path).as_posix()
45
+
46
+
41
47
  COMPOSITE_ENV_SEP = ":"
42
48
  VALID_OUTER_ENV_KINDS = ["slurm", "pbs"]
43
49
 
@@ -717,7 +723,7 @@ def make_env_name(path: str, all_env_names: list[str], kind: str) -> str:
717
723
  str
718
724
  A unique environment name.
719
725
  """
720
- dirname = os.path.basename(os.path.dirname(path))
726
+ dirname = Path(path).parent.name
721
727
  # If this is the first env in the project, call it main
722
728
  if not all_env_names:
723
729
  return dirname or "main"
@@ -841,7 +847,7 @@ def env_from_name_or_path(
841
847
  exists=True,
842
848
  )
843
849
  # Check if name_or_path is a file and detect environment type
844
- env_path = name_or_path
850
+ env_path = _as_posix_path(name_or_path)
845
851
  if os.path.isfile(env_path):
846
852
  if env_path.endswith("requirements.txt"):
847
853
  # TODO: Detect if uv is installed, and use a plain venv if not
@@ -851,9 +857,9 @@ def env_from_name_or_path(
851
857
  "kind": "uv-venv",
852
858
  "path": env_path,
853
859
  "python": DEFAULT_PYTHON_VERSION,
854
- "prefix": os.path.join(
855
- os.path.split(env_path)[0], ".venv"
856
- ),
860
+ "prefix": Path(env_path)
861
+ .parent.joinpath(".venv")
862
+ .as_posix(),
857
863
  },
858
864
  exists=False,
859
865
  )
@@ -942,9 +948,10 @@ def env_from_name_and_or_path(
942
948
  if ck_info is None:
943
949
  ck_info = calkit.load_calkit_info()
944
950
  envs = ck_info.get("environments", {})
951
+ path = _as_posix_path(path) if path else None
945
952
  if name and name in envs:
946
953
  env = envs[name]
947
- if path and env.get("path") != path:
954
+ if path and _as_posix_path(env.get("path", "")) != path:
948
955
  raise ValueError(
949
956
  f"Environment '{name}' exists but has a different path "
950
957
  f"('{env.get('path')}') than provided ('{path}')"
@@ -958,7 +965,7 @@ def env_from_name_and_or_path(
958
965
  # Look for a sub-environment with the given name and path
959
966
  for sub_name, sub_env in envs.items():
960
967
  if (sub_name == sub_env_name) or (
961
- path and sub_env.get("path") == path
968
+ path and _as_posix_path(sub_env.get("path", "")) == path
962
969
  ):
963
970
  return EnvDetectResult(
964
971
  name=sub_name,
@@ -995,12 +1002,13 @@ def env_from_notebook_path(
995
1002
  """
996
1003
  if ck_info is None:
997
1004
  ck_info = calkit.load_calkit_info()
1005
+ notebook_path = _as_posix_path(notebook_path)
998
1006
  stages = ck_info.get("pipeline", {}).get("stages", {})
999
1007
  envs = ck_info.get("environments", {})
1000
1008
  for stage in stages.values():
1001
1009
  if (
1002
1010
  stage.get("kind") == "jupyter-notebook"
1003
- and stage.get("notebook_path") == notebook_path
1011
+ and _as_posix_path(stage.get("notebook_path", "")) == notebook_path
1004
1012
  ):
1005
1013
  env_name = stage.get("environment")
1006
1014
  if env_name:
@@ -1008,7 +1016,7 @@ def env_from_notebook_path(
1008
1016
  if env:
1009
1017
  return EnvDetectResult(name=env_name, env=env, exists=True)
1010
1018
  for nb in ck_info.get("notebooks", []):
1011
- if nb.get("path") == notebook_path:
1019
+ if _as_posix_path(nb.get("path", "")) == notebook_path:
1012
1020
  env_name = nb.get("environment")
1013
1021
  if env_name:
1014
1022
  env = envs.get(env_name)
@@ -157,7 +157,7 @@ def ensure_path_is_ignored(
157
157
  if os.path.isfile(gitignore_path):
158
158
  with open(gitignore_path) as f:
159
159
  gitignore_txt = f.read()
160
- lines = gitignore_txt.splitlines()
160
+ lines = [line for line in gitignore_txt.splitlines() if line]
161
161
  if target_path in lines:
162
162
  # The direct rule exists; also remove any stale negation that
163
163
  # follows it, otherwise the negation wins and the path stays
@@ -169,7 +169,7 @@ def ensure_path_is_ignored(
169
169
  for n in stale:
170
170
  lines.remove(n)
171
171
  with open(gitignore_path, "w") as f:
172
- f.write(os.linesep.join(lines))
172
+ f.write("\n".join(lines))
173
173
  return True
174
174
  # Remove any stale negations for this path so the ignore rule takes
175
175
  # effect cleanly without accumulating contradictory entries.
@@ -180,7 +180,7 @@ def ensure_path_is_ignored(
180
180
  lines.remove(n)
181
181
  lines.append(target_path)
182
182
  with open(gitignore_path, "w") as f:
183
- f.write(os.linesep.join(lines))
183
+ f.write("\n".join(lines))
184
184
  return True
185
185
  with open(gitignore_path, "a") as f:
186
186
  if (
@@ -329,7 +329,7 @@ def ensure_path_is_not_ignored(
329
329
  lines.remove(no_ignore_line)
330
330
  lines.append(no_ignore_line)
331
331
  with open(gitignore_path, "w") as f:
332
- f.write(os.linesep.join(lines))
332
+ f.write("\n".join(lines))
333
333
  # If the path is still ignored after updating this gitignore file (e.g.,
334
334
  # because a subdirectory .gitignore also contains a matching rule), fix
335
335
  # that file as well. Depth-limit guards against pathological gitignore
@@ -4,6 +4,7 @@ import json
4
4
  import os
5
5
  import shutil
6
6
  import subprocess
7
+ import tempfile
7
8
  import warnings
8
9
  from copy import deepcopy
9
10
  from functools import cached_property
@@ -23,7 +24,9 @@ def get_git_remote_url(project_id: str, token: str) -> str:
23
24
  If running against a test environment, this will use a local directory.
24
25
  """
25
26
  if calkit.config.get_env() == "test":
26
- return os.path.join("/tmp", "overleaf", project_id)
27
+ return (
28
+ Path(tempfile.gettempdir()) / "overleaf" / project_id
29
+ ).as_posix()
27
30
  return f"https://git:{token}@git.overleaf.com/{project_id}"
28
31
 
29
32
 
@@ -1,7 +1,6 @@
1
1
  """Pipeline-related functionality."""
2
2
 
3
3
  import itertools
4
- import logging
5
4
  import os
6
5
  from collections.abc import Callable
7
6
  from pathlib import Path
@@ -18,17 +17,6 @@ from calkit.models.pipeline import (
18
17
  )
19
18
 
20
19
 
21
- class _FrozenStageWarningFilter(logging.Filter):
22
- """Drop only DVC's "stage is frozen" status warning.
23
-
24
- Frozen stages are intentionally hidden from Calkit status output, so this
25
- warning is noise; all other ``dvc.repo.status`` diagnostics pass through.
26
- """
27
-
28
- def filter(self, record: logging.LogRecord) -> bool:
29
- return "is frozen. Its dependencies are" not in record.getMessage()
30
-
31
-
32
20
  def _coerce_frozen(value: object) -> bool:
33
21
  """Interpret a raw ``frozen`` value the same way the Stage model would.
34
22
 
@@ -289,18 +277,15 @@ class StaleStage(BaseModel):
289
277
  # parent-relative. Use normpath to collapse any "../" segments that
290
278
  # arise from cross-subproject deps (e.g. sp + "../shared.txt").
291
279
  if path_prefix:
292
- modified_inputs = [
293
- os.path.normpath(os.path.join(path_prefix, p))
294
- for p in modified_inputs
295
- ]
296
- output_paths = [
297
- os.path.normpath(os.path.join(path_prefix, p))
298
- for p in output_paths
299
- ]
300
- modified_outputs = [
301
- os.path.normpath(os.path.join(path_prefix, p))
302
- for p in modified_outputs
303
- ]
280
+
281
+ def _prefix(p: str) -> str:
282
+ return Path(
283
+ os.path.normpath(os.path.join(path_prefix, p))
284
+ ).as_posix()
285
+
286
+ modified_inputs = [_prefix(p) for p in modified_inputs]
287
+ output_paths = [_prefix(p) for p in output_paths]
288
+ modified_outputs = [_prefix(p) for p in modified_outputs]
304
289
  configured_outputs = [str(path) for path in (configured_outputs or [])]
305
290
  stale_outputs = []
306
291
  if modified_inputs or modified_command:
@@ -641,19 +626,10 @@ def get_status(
641
626
  return PipelineStatus.model_validate(result)
642
627
  try:
643
628
  dvc_repo = calkit.dvc.get_dvc_repo()
644
- # Frozen stages emit a "stage is frozen. Its dependencies are not
645
- # going to be shown in the status output." warning from DVC's
646
- # status module; suppress just that message since we intentionally
647
- # hide frozen stages from the Calkit status output entirely.
648
- # A targeted filter is used (rather than raising the logger level)
649
- # so unrelated DVC diagnostics are still emitted.
650
- dvc_status_logger = logging.getLogger("dvc.repo.status")
651
- frozen_filter = _FrozenStageWarningFilter()
652
- dvc_status_logger.addFilter(frozen_filter)
653
- try:
654
- raw_status = dvc_repo.status(targets=targets)
655
- finally:
656
- dvc_status_logger.removeFilter(frozen_filter)
629
+ # calkit.dvc.core installs a filter on dvc.repo.status that drops
630
+ # the noisy frozen-stage warning, so the call here stays quiet.
631
+ raw_status = dvc_repo.status(targets=targets)
632
+ raw_status = calkit.dvc.status_as_posix(raw_status)
657
633
  except Exception as e:
658
634
  result["errors"].append(
659
635
  "Failed to get pipeline status from DVC: "
@@ -690,6 +666,7 @@ def get_status(
690
666
  try:
691
667
  sp_dvc_repo = calkit.dvc.get_dvc_repo(sp)
692
668
  sp_raw_status = sp_dvc_repo.status()
669
+ sp_raw_status = calkit.dvc.status_as_posix(sp_raw_status)
693
670
  except Exception:
694
671
  sp_raw_status = {}
695
672
  if sp_raw_status:
@@ -808,7 +785,7 @@ def get_status(
808
785
  )
809
786
  # DVC reports subproject stage paths relative to the repo root
810
787
  # (e.g., "sub1/out.txt"), but calkit.yaml stores them relative to
811
- # the subproject dir ("out.txt"). Prefix with the subproject path
788
+ # the subproject dir ("out.txt"). Prefix with the subproject path
812
789
  # so configured_outputs matches DVC's reported paths.
813
790
  raw_outputs = [
814
791
  output.get("path", str(output))
@@ -1296,7 +1273,7 @@ def get_matrix_item_targets(
1296
1273
 
1297
1274
  repo = calkit.dvc.get_dvc_repo(wdir)
1298
1275
  prefix = stage_name + "@"
1299
- items = [s for s in repo.index.stages if (s.name or "").startswith(prefix)]
1276
+ items = [s for s in repo.index.stages if (s.name or "").startswith(prefix)] # type: ignore
1300
1277
  item_set = set(items)
1301
1278
  upstreams: set = set()
1302
1279
  for item in items:
@@ -164,7 +164,7 @@ def ls_files() -> list[str]:
164
164
  for filename in files:
165
165
  fpath = os.path.join(root, filename)
166
166
  if os.path.isfile(fpath):
167
- cache_files.append(fpath)
167
+ cache_files.append(Path(fpath).as_posix())
168
168
  # Include files from unzipped dvc-zip workspace folders, which are
169
169
  # ignored by both Git and DVC and would otherwise be missing from the
170
170
  # release archive
@@ -185,7 +185,7 @@ def ls_files() -> list[str]:
185
185
  abs_fpath = Path(root) / filename
186
186
  if abs_fpath.is_file():
187
187
  dvc_zip_files.append(
188
- str(abs_fpath.relative_to(repo_root))
188
+ abs_fpath.relative_to(repo_root).as_posix()
189
189
  )
190
190
  elif abs_workspace.exists():
191
191
  raise ValueError(