calkit-python 0.41.9__tar.gz → 0.41.10__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.
- {calkit_python-0.41.9 → calkit_python-0.41.10}/PKG-INFO +1 -1
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/check.py +90 -131
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/main/core.py +22 -4
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/new.py +36 -16
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/notebooks.py +2 -2
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/scheduler.py +7 -8
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/dvc/core.py +19 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/environments.py +62 -6
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/julia.py +36 -3
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/models/core.py +12 -5
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/pipeline.py +3 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/main/test_core.py +33 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_new.py +2 -1
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_scheduler.py +31 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/dvc/test_core.py +13 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_environments.py +63 -3
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_julia.py +34 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_pipeline.py +33 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/cli-reference.md +47 -46
- calkit_python-0.41.10/docs/tutorials/ai-agents.md +144 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.claude-plugin/marketplace.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.gitattributes +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.gitignore +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.pre-commit-config.yaml +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.prettierignore +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.python-version +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.vscode/launch.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.vscode/tasks.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/.yarnrc.yml +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/AGENTS.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/CITATION.cff +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/CODE_OF_CONDUCT.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/CONTRIBUTING.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/LICENSE +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/Makefile +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/README.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/agent-plugin/.claude-plugin/plugin.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/agent-plugin/skills/add-pipeline-stage/SKILL.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/agent-plugin/skills/conventions/SKILL.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/agent-plugin/skills/create-pipeline/SKILL.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/babel.config.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/__main__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/calc.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/check.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/cloud.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/config.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/core.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/describe.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/dev.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/import_.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/latex.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/list.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/main/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/main/xr.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/office.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/overleaf.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cli/update.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/cloud.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/conda.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/config.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/core.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/datasets.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/dependencies.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/detect.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/docker.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/dvc/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/dvc/zip.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/fs.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/git.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/github.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/gui.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/install.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/invenio.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/jupyter.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/jupyterlab/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/jupyterlab/routes.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/package.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/schemas/calkit/package.json.orig +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/schemas/calkit/plugin.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/909.e3f9cc3408834a7fdcc3.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/remoteEntry.65469af996e7a96aa983.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/style.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/labextension/static/third-party-licenses.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/licenses.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/magics.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/matlab.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/models/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/models/io.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/models/iteration.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/models/pipeline.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/notebooks.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/office.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/ops.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/overleaf.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/releases.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/server.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/core.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/main/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/main/test_subprojects.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/main/test_xr.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_check.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_cloud.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_config.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_import.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_latex.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_notebooks.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_overleaf.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/cli/test_update.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/dvc/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/dvc/test_zip.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/jupyterlab/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/jupyterlab/test_routes.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/models/__init__.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/models/test_iteration.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/models/test_pipeline.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_cloud.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_conda.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_dependencies.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_detect.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_docker.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_fs.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_git.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_install.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_invenio.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_licenses.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_matlab.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_notebooks.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_releases.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/conftest.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/CNAME +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/ai-tools.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/apps.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/calculations.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/cloud-integration.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/datasets.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/dependencies.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/environments.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/examples.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/governance.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/help.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/hpc.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/calkit-fragmentation-compendium.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/connect-zenodo.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/jupyterlab/all-green.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/jupyterlab/collect-data-stale.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/jupyterlab/new-env.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/jupyterlab/new-notebook.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/jupyterlab/pipeline-badge.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/jupyterlab-params.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/plos-osi-code-2024-03.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/img/vscode-nb-params.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/index.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/installation.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/jupyterlab.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/local-server.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/notebooks.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/overleaf.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/pipeline/index.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/pipeline/running-and-logging.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/quickstart.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/references.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/releases.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/reproducibility.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/subprojects.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/existing-project.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/github-actions.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/actions-repo-secrets.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/quick-actions.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/vscode-slurm-notebook/create-calkit-env.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/vscode-slurm-notebook/create-inner-env.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/vscode-slurm-notebook/create-new-calkit-env.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/vscode-slurm-notebook/select-calkit-env.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/vscode-slurm-notebook/slurm-job-running.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/vscode-slurm-notebook/slurm-launch-options.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/img/vscode-slurm-notebook/starting-slurm-job.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/index.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/jupyterlab.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/office.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/tutorials/vscode-slurm-notebook.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/docs/version-control.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/flake.lock +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/flake.nix +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/install.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/jest.config.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/jupyter-config/server-config/calkit.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/mkdocs.yml +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/package.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/pyproject.toml +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/schema/plugin.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/scripts/generate-docs-references.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/scripts/install.ps1 +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/scripts/install.sh +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/scripts/make-calk9.sh +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/scripts/sync-docs.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/__tests__/useQueries.spec.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/calkit-config.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/cell-output-marker.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/commit-dialog.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/environment-editor.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/notebook-registration.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/notebook-toolbar.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/pipeline-status-bar.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/project-info-editor.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/sidebar-settings.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/sidebar.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/components/stage-editor.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/feature-flags.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/file-browser-menu.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/hooks/__tests__/useQueries.test.tsx +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/hooks/useQueries.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/icons.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/index.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/io-tracker.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/pipeline-state.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/queryClient.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/request.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/src/shims-mainmenu.d.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/base.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/cell-output-marker.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/environment-editor.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/environment-selector.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/img/calkit-no-bg.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/index.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/index.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/notebook-toolbar.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/pipeline-status-bar.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/style/sidebar.css +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/test/dvc-md5-dir/osx-arm64.txt +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/test/nb-julia.ipynb +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/test/nb-params.ipynb +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/test/nb-subdir.ipynb +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/test/pipeline.ipynb +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/test/script.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/test/test-log.log +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/tsconfig.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/tsconfig.test.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/ui-tests/.gitignore +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/ui-tests/README.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/ui-tests/jupyter_server_test_config.py +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/ui-tests/package.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/ui-tests/playwright.config.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/ui-tests/tests/calkit.spec.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/ui-tests/yarn.lock +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/uv.lock +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/.gitignore +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/.vscodeignore +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/CHANGELOG.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/LICENSE +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/README.md +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/images/calkit-no-bg.png +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/package-lock.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/package.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/scripts/set-proposed-api.js +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/src/environments.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/src/extension.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/src/notebooks.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/src/test/environments.test.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/src/test/kernel-selection.test.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/src/test/notebooks.test.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/src/types.ts +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/vscode-ext/tsconfig.json +0 -0
- {calkit_python-0.41.9 → calkit_python-0.41.10}/yarn.lock +0 -0
|
@@ -163,7 +163,7 @@ def _check_julia_env(
|
|
|
163
163
|
deps_to_add = []
|
|
164
164
|
if deps_to_add:
|
|
165
165
|
pkg_list = ", ".join(f'"{dep}"' for dep in deps_to_add)
|
|
166
|
-
cmd = [
|
|
166
|
+
cmd = [calkit.julia.get_julia_exe()]
|
|
167
167
|
if julia_version:
|
|
168
168
|
cmd.append(f"+{julia_version}")
|
|
169
169
|
cmd += [
|
|
@@ -190,7 +190,7 @@ def _check_julia_env(
|
|
|
190
190
|
success=False,
|
|
191
191
|
)
|
|
192
192
|
raise_error("Failed to add Julia dependencies")
|
|
193
|
-
cmd = [
|
|
193
|
+
cmd = [calkit.julia.get_julia_exe()]
|
|
194
194
|
if julia_version:
|
|
195
195
|
cmd.append(f"+{julia_version}")
|
|
196
196
|
cmd += [
|
|
@@ -318,6 +318,7 @@ def check_environment(
|
|
|
318
318
|
get_all_conda_lock_fpaths,
|
|
319
319
|
get_all_docker_lock_fpaths,
|
|
320
320
|
get_all_venv_lock_fpaths,
|
|
321
|
+
get_default_venv_prefix,
|
|
321
322
|
get_env_lock_fpath,
|
|
322
323
|
write_scheduler_env_lock,
|
|
323
324
|
)
|
|
@@ -403,12 +404,14 @@ def check_environment(
|
|
|
403
404
|
except subprocess.CalledProcessError:
|
|
404
405
|
raise_error("Failed to check uv environment")
|
|
405
406
|
elif (kind := env["kind"]) in ["uv-venv", "venv"]:
|
|
406
|
-
if "prefix" not in env:
|
|
407
|
-
raise_error("venv environments require a prefix")
|
|
408
407
|
if "path" not in env:
|
|
409
408
|
raise_error("venv environments require a path")
|
|
410
|
-
prefix = os.path.expandvars(env["prefix"])
|
|
411
409
|
path = os.path.expandvars(env["path"])
|
|
410
|
+
# Resolve the prefix on the fly if it isn't pinned in calkit.yaml
|
|
411
|
+
prefix = env.get("prefix")
|
|
412
|
+
if prefix is None:
|
|
413
|
+
prefix = get_default_venv_prefix(envs, path, env_name)
|
|
414
|
+
prefix = os.path.expandvars(prefix)
|
|
412
415
|
lock_fpath = get_env_lock_fpath(
|
|
413
416
|
env=env, env_name=env_name, as_posix=False
|
|
414
417
|
)
|
|
@@ -543,6 +546,41 @@ def check_environments(
|
|
|
543
546
|
)
|
|
544
547
|
|
|
545
548
|
|
|
549
|
+
def _renv_snapshot_from_description(env_dir: str, verbose: bool) -> None:
|
|
550
|
+
"""Install packages from DESCRIPTION and (re)write renv.lock.
|
|
551
|
+
|
|
552
|
+
Used to create the initial lock, to add newly declared packages, and as a
|
|
553
|
+
fallback when an existing lock can't be restored (e.g. its versions don't
|
|
554
|
+
build against the installed R version).
|
|
555
|
+
"""
|
|
556
|
+
hydrate_cmd = [
|
|
557
|
+
"Rscript",
|
|
558
|
+
"--vanilla",
|
|
559
|
+
"-e",
|
|
560
|
+
"renv::load(); renv::hydrate()",
|
|
561
|
+
]
|
|
562
|
+
if verbose:
|
|
563
|
+
typer.echo(f"Running: {' '.join(hydrate_cmd)}")
|
|
564
|
+
try:
|
|
565
|
+
subprocess.check_call(hydrate_cmd, cwd=env_dir)
|
|
566
|
+
except subprocess.CalledProcessError:
|
|
567
|
+
# Hydrate may fail if some packages aren't available; snapshot anyway
|
|
568
|
+
if verbose:
|
|
569
|
+
typer.echo("Warning: hydrate had issues, continuing to snapshot")
|
|
570
|
+
snapshot_cmd = [
|
|
571
|
+
"Rscript",
|
|
572
|
+
"--vanilla",
|
|
573
|
+
"-e",
|
|
574
|
+
"renv::load(); renv::snapshot(type='explicit', prompt=FALSE)",
|
|
575
|
+
]
|
|
576
|
+
if verbose:
|
|
577
|
+
typer.echo(f"Running: {' '.join(snapshot_cmd)}")
|
|
578
|
+
try:
|
|
579
|
+
subprocess.check_call(snapshot_cmd, cwd=env_dir)
|
|
580
|
+
except subprocess.CalledProcessError:
|
|
581
|
+
raise_error(f"Failed to snapshot renv in {env_dir}")
|
|
582
|
+
|
|
583
|
+
|
|
546
584
|
@check_app.command(name="renv")
|
|
547
585
|
def check_renv(
|
|
548
586
|
env_path: Annotated[
|
|
@@ -606,153 +644,74 @@ def check_renv(
|
|
|
606
644
|
subprocess.check_call(init_cmd, cwd=env_dir)
|
|
607
645
|
except subprocess.CalledProcessError:
|
|
608
646
|
raise_error(f"Failed to initialize renv in {env_dir}")
|
|
609
|
-
#
|
|
647
|
+
# Install packages from DESCRIPTION and write the lock file
|
|
610
648
|
if verbose:
|
|
611
649
|
typer.echo("Setting up environment from DESCRIPTION")
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
]
|
|
618
|
-
if verbose:
|
|
619
|
-
typer.echo(f"Running: {' '.join(hydrate_cmd)}")
|
|
620
|
-
try:
|
|
621
|
-
subprocess.check_call(hydrate_cmd, cwd=env_dir)
|
|
622
|
-
except subprocess.CalledProcessError:
|
|
623
|
-
# Hydrate might fail if packages aren't available, continue anyway
|
|
624
|
-
if verbose:
|
|
625
|
-
typer.echo(
|
|
626
|
-
"Warning: hydrate had issues, continuing to snapshot"
|
|
627
|
-
)
|
|
628
|
-
# Always snapshot after hydrate to create lock file from DESCRIPTION
|
|
650
|
+
_renv_snapshot_from_description(env_dir, verbose=verbose)
|
|
651
|
+
else:
|
|
652
|
+
# A lock file exists, so treat it as the source of truth: restore the
|
|
653
|
+
# library to the exact recorded versions rather than re-resolving from
|
|
654
|
+
# DESCRIPTION (which would bump packages and overwrite the lock).
|
|
629
655
|
if verbose:
|
|
630
|
-
typer.echo("
|
|
631
|
-
|
|
656
|
+
typer.echo("Restoring library from lockfile")
|
|
657
|
+
restore_cmd = [
|
|
632
658
|
"Rscript",
|
|
633
659
|
"--vanilla",
|
|
634
660
|
"-e",
|
|
635
|
-
"renv::load(); renv::
|
|
661
|
+
"renv::load(); renv::restore(prompt=FALSE)",
|
|
636
662
|
]
|
|
637
663
|
if verbose:
|
|
638
|
-
typer.echo(f"Running: {' '.join(
|
|
664
|
+
typer.echo(f"Running: {' '.join(restore_cmd)}")
|
|
639
665
|
try:
|
|
640
|
-
subprocess.check_call(
|
|
666
|
+
subprocess.check_call(restore_cmd, cwd=env_dir)
|
|
667
|
+
restored = True
|
|
641
668
|
except subprocess.CalledProcessError:
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
"renv::load(); status <- renv::status(); cat(status$synchronized)",
|
|
653
|
-
]
|
|
654
|
-
try:
|
|
655
|
-
result = subprocess.run(
|
|
656
|
-
status_cmd,
|
|
657
|
-
cwd=env_dir,
|
|
658
|
-
capture_output=True,
|
|
659
|
-
text=True,
|
|
660
|
-
check=True,
|
|
669
|
+
restored = False
|
|
670
|
+
if not restored:
|
|
671
|
+
# The locked versions couldn't be installed (e.g. they don't build
|
|
672
|
+
# against the installed R version). Fall back to re-resolving from
|
|
673
|
+
# DESCRIPTION, which updates renv.lock to a working set.
|
|
674
|
+
warn(
|
|
675
|
+
f"Could not restore renv environment in {env_dir} from "
|
|
676
|
+
"renv.lock; the locked versions may be incompatible with the "
|
|
677
|
+
"installed R version. Re-resolving from DESCRIPTION and "
|
|
678
|
+
"updating renv.lock."
|
|
661
679
|
)
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
#
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
680
|
+
_renv_snapshot_from_description(env_dir, verbose=verbose)
|
|
681
|
+
else:
|
|
682
|
+
# Only update the lock if DESCRIPTION declares dependencies the
|
|
683
|
+
# lock doesn't cover (e.g. the user added a package). After the
|
|
684
|
+
# restore the library matches the lock, so status is unsynchronized
|
|
685
|
+
# only when DESCRIPTION and the lock genuinely disagree---not merely
|
|
686
|
+
# because packages were missing on a fresh checkout.
|
|
669
687
|
if verbose:
|
|
670
|
-
typer.echo("
|
|
671
|
-
|
|
672
|
-
hydrate_cmd = [
|
|
688
|
+
typer.echo("Checking if DESCRIPTION matches lockfile")
|
|
689
|
+
status_cmd = [
|
|
673
690
|
"Rscript",
|
|
674
691
|
"--vanilla",
|
|
675
692
|
"-e",
|
|
676
|
-
"renv::load(); renv::
|
|
693
|
+
"renv::load(); cat(renv::status()$synchronized)",
|
|
677
694
|
]
|
|
678
|
-
if verbose:
|
|
679
|
-
typer.echo(f"Running: {' '.join(hydrate_cmd)}")
|
|
680
695
|
try:
|
|
681
|
-
subprocess.
|
|
696
|
+
result = subprocess.run(
|
|
697
|
+
status_cmd,
|
|
698
|
+
cwd=env_dir,
|
|
699
|
+
capture_output=True,
|
|
700
|
+
text=True,
|
|
701
|
+
check=True,
|
|
702
|
+
)
|
|
703
|
+
in_sync = "TRUE" in result.stdout
|
|
682
704
|
except subprocess.CalledProcessError:
|
|
705
|
+
# If status fails, keep the lock rather than risk clobbering it
|
|
706
|
+
in_sync = True
|
|
683
707
|
if verbose:
|
|
684
|
-
typer.echo(
|
|
685
|
-
|
|
686
|
-
)
|
|
687
|
-
# Snapshot to update lock
|
|
688
|
-
snapshot_cmd = [
|
|
689
|
-
"Rscript",
|
|
690
|
-
"--vanilla",
|
|
691
|
-
"-e",
|
|
692
|
-
"renv::load(); renv::snapshot(type='explicit', prompt=FALSE)",
|
|
693
|
-
]
|
|
694
|
-
if verbose:
|
|
695
|
-
typer.echo(f"Running: {' '.join(snapshot_cmd)}")
|
|
696
|
-
try:
|
|
697
|
-
subprocess.check_call(snapshot_cmd, cwd=env_dir)
|
|
698
|
-
except subprocess.CalledProcessError:
|
|
708
|
+
typer.echo("Warning: status check failed, keeping lock")
|
|
709
|
+
if not in_sync:
|
|
699
710
|
if verbose:
|
|
700
|
-
typer.echo("
|
|
701
|
-
|
|
702
|
-
|
|
711
|
+
typer.echo("DESCRIPTION changed; updating lockfile")
|
|
712
|
+
_renv_snapshot_from_description(env_dir, verbose=verbose)
|
|
713
|
+
elif verbose:
|
|
703
714
|
typer.echo("Lockfile is already in sync with DESCRIPTION")
|
|
704
|
-
# Check if library needs restoring
|
|
705
|
-
if verbose:
|
|
706
|
-
typer.echo("Checking if library is in sync with lockfile")
|
|
707
|
-
lib_status_cmd = [
|
|
708
|
-
"Rscript",
|
|
709
|
-
"--vanilla",
|
|
710
|
-
"-e",
|
|
711
|
-
(
|
|
712
|
-
"renv::load(); "
|
|
713
|
-
"status <- tryCatch({"
|
|
714
|
-
" renv::status();"
|
|
715
|
-
" cat('synchronized');"
|
|
716
|
-
"}, error = function(e) {"
|
|
717
|
-
" cat('needs_restore');"
|
|
718
|
-
"})"
|
|
719
|
-
),
|
|
720
|
-
]
|
|
721
|
-
try:
|
|
722
|
-
result = subprocess.run(
|
|
723
|
-
lib_status_cmd,
|
|
724
|
-
cwd=env_dir,
|
|
725
|
-
capture_output=True,
|
|
726
|
-
text=True,
|
|
727
|
-
check=True,
|
|
728
|
-
)
|
|
729
|
-
needs_restore = "needs_restore" in result.stdout or (
|
|
730
|
-
"synchronized" not in result.stdout
|
|
731
|
-
)
|
|
732
|
-
except subprocess.CalledProcessError:
|
|
733
|
-
# If check fails, restore to be safe
|
|
734
|
-
needs_restore = True
|
|
735
|
-
if verbose:
|
|
736
|
-
typer.echo("Warning: library status check failed, will restore")
|
|
737
|
-
|
|
738
|
-
if needs_restore:
|
|
739
|
-
if verbose:
|
|
740
|
-
typer.echo("Restoring library from lockfile")
|
|
741
|
-
restore_cmd = [
|
|
742
|
-
"Rscript",
|
|
743
|
-
"--vanilla",
|
|
744
|
-
"-e",
|
|
745
|
-
"renv::load(); renv::restore(prompt=FALSE)",
|
|
746
|
-
]
|
|
747
|
-
if verbose:
|
|
748
|
-
typer.echo(f"Running: {' '.join(restore_cmd)}")
|
|
749
|
-
try:
|
|
750
|
-
subprocess.check_call(restore_cmd, cwd=env_dir)
|
|
751
|
-
except subprocess.CalledProcessError:
|
|
752
|
-
raise_error(f"Failed to restore renv in {env_dir}")
|
|
753
|
-
else:
|
|
754
|
-
if verbose:
|
|
755
|
-
typer.echo("Library is already in sync with lockfile")
|
|
756
715
|
|
|
757
716
|
|
|
758
717
|
@check_app.command(name="docker-env")
|
|
@@ -1762,6 +1762,17 @@ def run(
|
|
|
1762
1762
|
"--no-push", help="Do not push to Git and DVC after saving."
|
|
1763
1763
|
),
|
|
1764
1764
|
] = False,
|
|
1765
|
+
mock_scheduler: Annotated[
|
|
1766
|
+
bool,
|
|
1767
|
+
typer.Option(
|
|
1768
|
+
"--mock-scheduler",
|
|
1769
|
+
"-K",
|
|
1770
|
+
help=(
|
|
1771
|
+
"Run job-scheduler (SLURM/PBS) stages locally instead of "
|
|
1772
|
+
"submitting them to a real scheduler."
|
|
1773
|
+
),
|
|
1774
|
+
),
|
|
1775
|
+
] = False,
|
|
1765
1776
|
) -> dict:
|
|
1766
1777
|
"""Check dependencies and run the pipeline."""
|
|
1767
1778
|
import dvc.log
|
|
@@ -1779,6 +1790,10 @@ def run(
|
|
|
1779
1790
|
if (target_inputs or target_outputs) and targets:
|
|
1780
1791
|
raise_error("Cannot specify both targets and inputs")
|
|
1781
1792
|
os.environ["CALKIT_PIPELINE_RUNNING"] = "1"
|
|
1793
|
+
# Mock the scheduler for this run (and any subprocesses) so SLURM/PBS
|
|
1794
|
+
# stages execute locally; child processes inherit it via os.environ
|
|
1795
|
+
if mock_scheduler:
|
|
1796
|
+
os.environ[calkit.cli.scheduler.MOCK_ENV_VAR] = "1"
|
|
1782
1797
|
dotenv.load_dotenv(dotenv_path=".env", verbose=verbose)
|
|
1783
1798
|
ck_info = calkit.load_calkit_info()
|
|
1784
1799
|
# Ensure Git is initialized so DVC can be used.
|
|
@@ -2463,12 +2478,15 @@ def run_in_env(
|
|
|
2463
2478
|
except subprocess.CalledProcessError:
|
|
2464
2479
|
raise_error("Failed to run in uv environment")
|
|
2465
2480
|
elif (kind := env["kind"]) in ["uv-venv", "venv"]:
|
|
2466
|
-
if "prefix" not in env:
|
|
2467
|
-
raise_error("venv environments require a prefix")
|
|
2468
2481
|
if "path" not in env:
|
|
2469
2482
|
raise_error("venv environments require a path")
|
|
2470
|
-
prefix = env["prefix"]
|
|
2471
2483
|
path = env["path"]
|
|
2484
|
+
# Resolve the prefix on the fly if it isn't pinned in calkit.yaml
|
|
2485
|
+
prefix = env.get("prefix")
|
|
2486
|
+
if prefix is None:
|
|
2487
|
+
prefix = calkit.environments.get_default_venv_prefix(
|
|
2488
|
+
envs, path, env_name
|
|
2489
|
+
)
|
|
2472
2490
|
shell_cmd = _to_shell_cmd(cmd)
|
|
2473
2491
|
if _platform.system() == "Windows":
|
|
2474
2492
|
activate_cmd = f"{prefix}\\Scripts\\activate"
|
|
@@ -2525,7 +2543,7 @@ def run_in_env(
|
|
|
2525
2543
|
# specifying the project
|
|
2526
2544
|
cmd = [arg for arg in cmd if not arg.startswith("--project=")]
|
|
2527
2545
|
julia_cmd = [
|
|
2528
|
-
|
|
2546
|
+
calkit.julia.get_julia_exe(),
|
|
2529
2547
|
f"+{julia_version}",
|
|
2530
2548
|
"--project=" + env_dir,
|
|
2531
2549
|
] + cmd
|
|
@@ -1604,8 +1604,15 @@ def new_uv_venv(
|
|
|
1604
1604
|
str, typer.Option("--path", help="Path for requirements file.")
|
|
1605
1605
|
] = "requirements.txt",
|
|
1606
1606
|
prefix: Annotated[
|
|
1607
|
-
str
|
|
1608
|
-
|
|
1607
|
+
str | None,
|
|
1608
|
+
typer.Option(
|
|
1609
|
+
"--prefix",
|
|
1610
|
+
help=(
|
|
1611
|
+
"Prefix for environment location (defaults to .venv, or "
|
|
1612
|
+
".calkit/envs/<name>/.venv if .venv is already taken)."
|
|
1613
|
+
),
|
|
1614
|
+
),
|
|
1615
|
+
] = None,
|
|
1609
1616
|
python_version: Annotated[
|
|
1610
1617
|
str | None, typer.Option("--python", "-p", help="Python version.")
|
|
1611
1618
|
] = None,
|
|
@@ -1654,12 +1661,13 @@ def new_uv_venv(
|
|
|
1654
1661
|
f"Environment with name {name} already exists "
|
|
1655
1662
|
"(use -f to overwrite)"
|
|
1656
1663
|
)
|
|
1657
|
-
#
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1664
|
+
# Only pin a prefix if one was explicitly given; otherwise it is resolved
|
|
1665
|
+
# on the fly (defaulting to .venv) at check/run time
|
|
1666
|
+
if prefix is not None and not overwrite:
|
|
1667
|
+
for other_name, other_env in envs.items():
|
|
1668
|
+
if other_env.get("prefix") == prefix:
|
|
1661
1669
|
raise_error(
|
|
1662
|
-
f"Environment '{
|
|
1670
|
+
f"Environment '{other_name}' already exists with "
|
|
1663
1671
|
f"prefix '{prefix}'"
|
|
1664
1672
|
)
|
|
1665
1673
|
if packages is not None:
|
|
@@ -1669,7 +1677,9 @@ def new_uv_venv(
|
|
|
1669
1677
|
with open(path, "w") as f:
|
|
1670
1678
|
f.write(packages_txt)
|
|
1671
1679
|
typer.echo("Adding environment to calkit.yaml")
|
|
1672
|
-
env = dict(path=path, kind="uv-venv"
|
|
1680
|
+
env = dict(path=path, kind="uv-venv")
|
|
1681
|
+
if prefix is not None:
|
|
1682
|
+
env["prefix"] = prefix
|
|
1673
1683
|
if python_version is not None:
|
|
1674
1684
|
env["python"] = python_version
|
|
1675
1685
|
if description is not None:
|
|
@@ -1703,8 +1713,15 @@ def new_venv(
|
|
|
1703
1713
|
str, typer.Option("--path", help="Path for requirements file.")
|
|
1704
1714
|
] = "requirements.txt",
|
|
1705
1715
|
prefix: Annotated[
|
|
1706
|
-
str
|
|
1707
|
-
|
|
1716
|
+
str | None,
|
|
1717
|
+
typer.Option(
|
|
1718
|
+
"--prefix",
|
|
1719
|
+
help=(
|
|
1720
|
+
"Prefix for environment location (defaults to .venv, or "
|
|
1721
|
+
".calkit/envs/<name>/.venv if .venv is already taken)."
|
|
1722
|
+
),
|
|
1723
|
+
),
|
|
1724
|
+
] = None,
|
|
1708
1725
|
description: Annotated[
|
|
1709
1726
|
str | None, typer.Option("--description", help="Description.")
|
|
1710
1727
|
] = None,
|
|
@@ -1745,12 +1762,13 @@ def new_venv(
|
|
|
1745
1762
|
f"Environment with name {name} already exists "
|
|
1746
1763
|
"(use -f to overwrite)"
|
|
1747
1764
|
)
|
|
1748
|
-
#
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1765
|
+
# Only pin a prefix if one was explicitly given; otherwise it is resolved
|
|
1766
|
+
# on the fly (defaulting to .venv) at check/run time
|
|
1767
|
+
if prefix is not None and not overwrite:
|
|
1768
|
+
for other_name, other_env in envs.items():
|
|
1769
|
+
if other_env.get("prefix") == prefix:
|
|
1752
1770
|
raise_error(
|
|
1753
|
-
f"Environment '{
|
|
1771
|
+
f"Environment '{other_name}' already exists with "
|
|
1754
1772
|
f"prefix '{prefix}'"
|
|
1755
1773
|
)
|
|
1756
1774
|
packages_txt = "\n".join(packages)
|
|
@@ -1760,7 +1778,9 @@ def new_venv(
|
|
|
1760
1778
|
f.write(packages_txt)
|
|
1761
1779
|
repo.git.add(path)
|
|
1762
1780
|
typer.echo("Adding environment to calkit.yaml")
|
|
1763
|
-
env = dict(path=path, kind="venv"
|
|
1781
|
+
env = dict(path=path, kind="venv")
|
|
1782
|
+
if prefix is not None:
|
|
1783
|
+
env["prefix"] = prefix
|
|
1764
1784
|
if description is not None:
|
|
1765
1785
|
env["description"] = description
|
|
1766
1786
|
envs[name] = env
|
|
@@ -90,7 +90,7 @@ def _check_ijulia_available(
|
|
|
90
90
|
env_dir: str,
|
|
91
91
|
) -> bool:
|
|
92
92
|
ijulia_check_cmd = [
|
|
93
|
-
|
|
93
|
+
calkit.julia.get_julia_exe(),
|
|
94
94
|
f"+{julia_version}",
|
|
95
95
|
"--project=" + env_dir,
|
|
96
96
|
"-e",
|
|
@@ -322,7 +322,7 @@ def check_env_kernel(
|
|
|
322
322
|
"println(kp);"
|
|
323
323
|
)
|
|
324
324
|
cmd = [
|
|
325
|
-
|
|
325
|
+
calkit.julia.get_julia_exe(),
|
|
326
326
|
f"+{julia_version}",
|
|
327
327
|
"--project=" + env_dir,
|
|
328
328
|
"-e",
|
|
@@ -251,20 +251,19 @@ def _cancel(kind: str, job_id: str) -> tuple[bool, str]:
|
|
|
251
251
|
|
|
252
252
|
|
|
253
253
|
def _wait_until_done(kind: str, job_id: str, name: str) -> None:
|
|
254
|
-
"""Poll until the job finishes,
|
|
254
|
+
"""Poll until the job finishes, canceling it on Ctrl+C.
|
|
255
255
|
|
|
256
|
-
The job is
|
|
257
|
-
|
|
258
|
-
resumes from here.
|
|
256
|
+
The job is submitted and tracked, so interrupting the local wait cancels
|
|
257
|
+
the scheduler job before exiting rather than leaving it orphaned.
|
|
259
258
|
"""
|
|
260
259
|
try:
|
|
261
260
|
while _is_active(kind, job_id):
|
|
262
261
|
time.sleep(1)
|
|
263
262
|
except KeyboardInterrupt:
|
|
264
|
-
typer.echo(
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
263
|
+
typer.echo(f"Interrupted; canceling job '{name}' ({job_id})")
|
|
264
|
+
ok, stderr = _cancel(kind, job_id)
|
|
265
|
+
if not ok:
|
|
266
|
+
typer.echo(f"Failed to cancel job '{name}' ({job_id}): {stderr}")
|
|
268
267
|
raise typer.Exit(130)
|
|
269
268
|
|
|
270
269
|
|
|
@@ -261,6 +261,25 @@ def get_dvc_repo(wdir: str | None = None) -> dvc.repo.Repo:
|
|
|
261
261
|
return dvc.repo.Repo(wdir)
|
|
262
262
|
|
|
263
263
|
|
|
264
|
+
def ensure_dvc_lock_not_ignored(wdir: str | None = None) -> bool:
|
|
265
|
+
"""Ensure ``dvc.lock`` is not Git-ignored.
|
|
266
|
+
|
|
267
|
+
DVC raises ``FileIsGitIgnored`` when ``dvc.lock`` is excluded by Git, which
|
|
268
|
+
breaks ``dvc status`` and pipeline runs. This un-ignores it (editing the
|
|
269
|
+
relevant ``.gitignore`` as needed) so those operations keep working.
|
|
270
|
+
|
|
271
|
+
Returns True if a ``.gitignore`` was modified.
|
|
272
|
+
"""
|
|
273
|
+
import calkit.git
|
|
274
|
+
|
|
275
|
+
lock_path = os.path.join(wdir, "dvc.lock") if wdir else "dvc.lock"
|
|
276
|
+
try:
|
|
277
|
+
repo = calkit.git.get_repo(wdir)
|
|
278
|
+
except Exception:
|
|
279
|
+
return False
|
|
280
|
+
return bool(calkit.git.ensure_path_is_not_ignored(repo, path=lock_path))
|
|
281
|
+
|
|
282
|
+
|
|
264
283
|
def get_running_pipeline_processes(wdir: str | None = None) -> list[dict]:
|
|
265
284
|
"""Return live processes holding DVC's read/write lock.
|
|
266
285
|
|
|
@@ -138,7 +138,7 @@ def _get_julia_version() -> str:
|
|
|
138
138
|
"""
|
|
139
139
|
try:
|
|
140
140
|
result = subprocess.run(
|
|
141
|
-
[
|
|
141
|
+
[calkit.julia.get_julia_exe(), "--version"],
|
|
142
142
|
capture_output=True,
|
|
143
143
|
text=True,
|
|
144
144
|
timeout=5,
|
|
@@ -449,7 +449,15 @@ def write_scheduler_env_lock(
|
|
|
449
449
|
parent = os.path.dirname(full_path)
|
|
450
450
|
if parent:
|
|
451
451
|
os.makedirs(parent, exist_ok=True)
|
|
452
|
-
|
|
452
|
+
lock_data = dict(env)
|
|
453
|
+
# Record when the scheduler is mocked so switching between a mocked run
|
|
454
|
+
# (executed locally) and a real scheduler run changes the lock file and
|
|
455
|
+
# invalidates the cached result
|
|
456
|
+
from calkit.cli.scheduler import _mock_enabled
|
|
457
|
+
|
|
458
|
+
if _mock_enabled():
|
|
459
|
+
lock_data["mocked"] = True
|
|
460
|
+
content = json.dumps(lock_data, indent=2, sort_keys=True) + "\n"
|
|
453
461
|
if os.path.isfile(full_path):
|
|
454
462
|
with open(full_path, "r") as f:
|
|
455
463
|
existing = f.read()
|
|
@@ -744,6 +752,55 @@ def make_env_name(path: str, all_env_names: list[str], kind: str) -> str:
|
|
|
744
752
|
return name
|
|
745
753
|
|
|
746
754
|
|
|
755
|
+
def get_default_venv_prefix(envs: dict, path: str, name: str) -> str:
|
|
756
|
+
"""Return the default prefix for a venv or uv-venv environment.
|
|
757
|
+
|
|
758
|
+
The prefix defaults to ``.venv`` in the same directory as ``path``,
|
|
759
|
+
unless that location is already claimed by another environment, in which
|
|
760
|
+
case the virtualenv is nested under ``.calkit/envs/{name}/.venv``. This
|
|
761
|
+
is resolved on the fly so that the prefix need not be stored in
|
|
762
|
+
``calkit.yaml``.
|
|
763
|
+
|
|
764
|
+
A location is considered claimed by another environment if it pins that
|
|
765
|
+
explicit ``prefix``, or if it is a ``uv``, ``venv``, or ``uv-venv``
|
|
766
|
+
environment whose ``.venv`` would live there (``uv`` always creates its
|
|
767
|
+
virtualenv at ``.venv`` in its project directory, so a flexible venv
|
|
768
|
+
yields to it). Sibling venvs that would otherwise collide all nest under
|
|
769
|
+
their own name-scoped location, which is collision-free.
|
|
770
|
+
|
|
771
|
+
Parameters
|
|
772
|
+
----------
|
|
773
|
+
envs : dict
|
|
774
|
+
All environments, keyed by name.
|
|
775
|
+
path : str
|
|
776
|
+
Path to the spec file the environment lives alongside.
|
|
777
|
+
name : str
|
|
778
|
+
Name of the environment being resolved, used both to exclude it from
|
|
779
|
+
the claimed locations and for the nested fallback.
|
|
780
|
+
|
|
781
|
+
Returns
|
|
782
|
+
-------
|
|
783
|
+
str
|
|
784
|
+
A POSIX-style prefix that does not collide with another environment.
|
|
785
|
+
"""
|
|
786
|
+
base = os.path.join(os.path.dirname(path), ".venv")
|
|
787
|
+
# Collect .venv locations claimed by the other environments
|
|
788
|
+
claimed = set()
|
|
789
|
+
for other_name, env in envs.items():
|
|
790
|
+
if other_name == name:
|
|
791
|
+
continue
|
|
792
|
+
prefix = env.get("prefix")
|
|
793
|
+
if prefix is not None:
|
|
794
|
+
claimed.add(os.path.normpath(prefix))
|
|
795
|
+
elif env.get("kind") in ("uv", "venv", "uv-venv"):
|
|
796
|
+
other_dir = os.path.dirname(env.get("path", ""))
|
|
797
|
+
claimed.add(os.path.normpath(os.path.join(other_dir, ".venv")))
|
|
798
|
+
# Nest under .calkit/envs/{name} if the default location is taken
|
|
799
|
+
if os.path.normpath(base) in claimed:
|
|
800
|
+
base = os.path.join(".calkit", "envs", name, ".venv")
|
|
801
|
+
return Path(base).as_posix()
|
|
802
|
+
|
|
803
|
+
|
|
747
804
|
def env_from_name_or_path(
|
|
748
805
|
name_or_path: str | None = None,
|
|
749
806
|
ck_info: dict | None = None,
|
|
@@ -851,15 +908,14 @@ def env_from_name_or_path(
|
|
|
851
908
|
if os.path.isfile(env_path):
|
|
852
909
|
if env_path.endswith("requirements.txt"):
|
|
853
910
|
# TODO: Detect if uv is installed, and use a plain venv if not
|
|
911
|
+
# The prefix is left unset and resolved on the fly at check/run
|
|
912
|
+
# time via get_default_venv_prefix
|
|
854
913
|
return EnvDetectResult(
|
|
855
914
|
name=make_env_name(env_path, all_env_names, kind="uv-venv"),
|
|
856
915
|
env={
|
|
857
916
|
"kind": "uv-venv",
|
|
858
917
|
"path": env_path,
|
|
859
918
|
"python": DEFAULT_PYTHON_VERSION,
|
|
860
|
-
"prefix": Path(env_path)
|
|
861
|
-
.parent.joinpath(".venv")
|
|
862
|
-
.as_posix(),
|
|
863
919
|
},
|
|
864
920
|
exists=False,
|
|
865
921
|
)
|
|
@@ -1325,7 +1381,7 @@ end
|
|
|
1325
1381
|
# Run Julia with the script
|
|
1326
1382
|
result = subprocess.run(
|
|
1327
1383
|
[
|
|
1328
|
-
|
|
1384
|
+
calkit.julia.get_julia_exe(),
|
|
1329
1385
|
script_path,
|
|
1330
1386
|
",".join(package_names),
|
|
1331
1387
|
],
|