calkit-python 0.39.0__tar.gz → 0.39.2__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.39.0 → calkit_python-0.39.2}/PKG-INFO +1 -1
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/__init__.py +38 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/main/core.py +63 -20
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/conda.py +182 -10
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/dvc/zip.py +83 -45
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/pipeline.py +174 -58
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_conda.py +59 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_pipeline.py +198 -1
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.claude-plugin/marketplace.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.gitignore +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.pre-commit-config.yaml +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.prettierignore +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.python-version +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.vscode/launch.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.vscode/tasks.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/.yarnrc.yml +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/AGENTS.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/CITATION.cff +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/CODE_OF_CONDUCT.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/CONTRIBUTING.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/LICENSE +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/Makefile +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/README.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/agent-plugin/.claude-plugin/plugin.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/agent-plugin/skills/add-pipeline-stage/SKILL.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/agent-plugin/skills/conventions/SKILL.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/agent-plugin/skills/create-pipeline/SKILL.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/babel.config.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/__main__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/calc.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/check.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/check.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/cloud.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/config.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/describe.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/dev.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/import_.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/latex.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/list.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/main/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/main/xr.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/new.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/notebooks.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/office.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/overleaf.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/slurm.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cli/update.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/cloud.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/config.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/datasets.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/detect.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/docker.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/dvc/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/dvc/core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/environments.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/fs.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/git.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/github.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/gui.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/invenio.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/julia.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/jupyter.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/jupyterlab/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/jupyterlab/routes.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/package.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/schemas/calkit/package.json.orig +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/schemas/calkit/plugin.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/909.e3f9cc3408834a7fdcc3.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/remoteEntry.65469af996e7a96aa983.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/style.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/labextension/static/third-party-licenses.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/licenses.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/magics.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/matlab.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/models/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/models/core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/models/io.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/models/iteration.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/models/pipeline.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/notebooks.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/office.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/ops.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/overleaf.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/releases.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/server.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/main/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/main/test_core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/main/test_subprojects.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/main/test_xr.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_check.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_cloud.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_config.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_import.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_latex.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_new.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_notebooks.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_overleaf.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/cli/test_update.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/dvc/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/dvc/test_core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/dvc/test_zip.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/jupyterlab/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/jupyterlab/test_routes.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/models/__init__.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/models/test_iteration.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/models/test_pipeline.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_cloud.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_detect.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_docker.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_environments.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_fs.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_git.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_invenio.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_julia.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_matlab.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_notebooks.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_releases.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/conftest.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/CNAME +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/ai-tools.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/apps.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/calculations.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/cli-reference.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/cloud-integration.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/datasets.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/dependencies.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/environments.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/examples.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/governance.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/help.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/calkit-fragmentation-compendium.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/connect-zenodo.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/jupyterlab/all-green.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/jupyterlab/collect-data-stale.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/jupyterlab/new-env.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/jupyterlab/new-notebook.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/jupyterlab/pipeline-badge.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/jupyterlab-params.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/plos-osi-code-2024-03.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/img/vscode-nb-params.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/index.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/installation.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/jupyterlab.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/local-server.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/notebooks.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/overleaf.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/pipeline/index.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/pipeline/running-and-logging.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/pipeline/slurm.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/quickstart.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/references.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/releases.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/reproducibility.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/subprojects.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/existing-project.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/github-actions.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/actions-repo-secrets.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/quick-actions.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/create-calkit-env.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/create-inner-env.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/create-new-calkit-env.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/select-calkit-env.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/slurm-job-running.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/slurm-launch-options.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/starting-slurm-job.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/index.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/jupyterlab.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/office.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/tutorials/vscode-slurm-notebook.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/docs/version-control.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/install.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/jest.config.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/jupyter-config/server-config/calkit.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/mkdocs.yml +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/package.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/pyproject.toml +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/schema/plugin.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/scripts/generate-docs-references.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/scripts/install.ps1 +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/scripts/install.sh +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/scripts/make-calk9.sh +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/scripts/sync-docs.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/__tests__/useQueries.spec.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/calkit-config.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/cell-output-marker.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/commit-dialog.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/environment-editor.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/notebook-registration.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/notebook-toolbar.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/pipeline-status-bar.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/project-info-editor.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/sidebar-settings.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/sidebar.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/components/stage-editor.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/feature-flags.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/file-browser-menu.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/hooks/__tests__/useQueries.test.tsx +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/hooks/useQueries.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/icons.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/index.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/io-tracker.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/pipeline-state.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/queryClient.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/request.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/src/shims-mainmenu.d.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/base.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/cell-output-marker.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/environment-editor.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/environment-selector.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/img/calkit-no-bg.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/index.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/index.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/notebook-toolbar.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/pipeline-status-bar.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/style/sidebar.css +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/test/dvc-md5-dir/osx-arm64.txt +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/test/nb-julia.ipynb +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/test/nb-params.ipynb +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/test/nb-subdir.ipynb +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/test/pipeline.ipynb +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/test/script.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/test/test-log.log +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/tsconfig.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/tsconfig.test.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/ui-tests/.gitignore +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/ui-tests/README.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/ui-tests/jupyter_server_test_config.py +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/ui-tests/package.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/ui-tests/playwright.config.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/ui-tests/tests/calkit.spec.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/ui-tests/yarn.lock +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/uv.lock +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/.gitignore +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/.vscodeignore +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/CHANGELOG.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/LICENSE +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/README.md +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/images/calkit-no-bg.png +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/package-lock.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/package.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/scripts/set-proposed-api.js +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/src/environments.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/src/extension.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/src/notebooks.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/src/test/environments.test.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/src/test/kernel-selection.test.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/src/test/notebooks.test.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/src/types.ts +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/vscode-ext/tsconfig.json +0 -0
- {calkit_python-0.39.0 → calkit_python-0.39.2}/yarn.lock +0 -0
|
@@ -1,9 +1,47 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from importlib.metadata import version as _version
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
2
5
|
|
|
3
6
|
__version__ = _version("calkit-python")
|
|
4
7
|
|
|
5
8
|
from .core import * # noqa: F403, I001
|
|
6
9
|
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from calkit import ( # noqa: F401
|
|
12
|
+
calc,
|
|
13
|
+
check,
|
|
14
|
+
cloud,
|
|
15
|
+
conda,
|
|
16
|
+
config,
|
|
17
|
+
datasets,
|
|
18
|
+
detect,
|
|
19
|
+
docker,
|
|
20
|
+
dvc,
|
|
21
|
+
environments,
|
|
22
|
+
fs,
|
|
23
|
+
git,
|
|
24
|
+
github,
|
|
25
|
+
gui,
|
|
26
|
+
invenio,
|
|
27
|
+
julia,
|
|
28
|
+
jupyter,
|
|
29
|
+
licenses,
|
|
30
|
+
magics,
|
|
31
|
+
matlab,
|
|
32
|
+
models,
|
|
33
|
+
notebooks,
|
|
34
|
+
office,
|
|
35
|
+
ops,
|
|
36
|
+
overleaf,
|
|
37
|
+
pipeline,
|
|
38
|
+
releases,
|
|
39
|
+
server,
|
|
40
|
+
templates,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
from .notebooks import declare_notebook # noqa: F401
|
|
44
|
+
|
|
7
45
|
# Lazy-load submodules to speed up imports
|
|
8
46
|
_SUBMODULES = {
|
|
9
47
|
"git",
|
|
@@ -669,9 +669,11 @@ def add(
|
|
|
669
669
|
paths.remove(".")
|
|
670
670
|
if dvc_repo is not None:
|
|
671
671
|
dvc_status = dvc_repo.data_status()
|
|
672
|
-
|
|
672
|
+
uncommitted = dvc_status["uncommitted"]
|
|
673
|
+
dvc_uncommitted_all = uncommitted.get(
|
|
673
674
|
"modified", []
|
|
674
|
-
)
|
|
675
|
+
) + uncommitted.get("deleted", [])
|
|
676
|
+
for dvc_uncommitted in dvc_uncommitted_all:
|
|
675
677
|
if os.path.exists(dvc_uncommitted):
|
|
676
678
|
if dry_run:
|
|
677
679
|
typer.echo(
|
|
@@ -679,12 +681,25 @@ def add(
|
|
|
679
681
|
)
|
|
680
682
|
else:
|
|
681
683
|
typer.echo(f"Adding {dvc_uncommitted} to DVC")
|
|
682
|
-
dvc_repo.commit(
|
|
684
|
+
dvc_repo.commit(
|
|
685
|
+
dvc_uncommitted,
|
|
686
|
+
force=True,
|
|
687
|
+
allow_missing=True,
|
|
688
|
+
)
|
|
683
689
|
else:
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
690
|
+
if dry_run:
|
|
691
|
+
typer.echo(
|
|
692
|
+
f"Would commit deleted {dvc_uncommitted} to DVC"
|
|
693
|
+
)
|
|
694
|
+
else:
|
|
695
|
+
typer.echo(
|
|
696
|
+
f"Committing deleted {dvc_uncommitted} to DVC"
|
|
697
|
+
)
|
|
698
|
+
dvc_repo.commit(
|
|
699
|
+
dvc_uncommitted,
|
|
700
|
+
force=True,
|
|
701
|
+
allow_missing=True,
|
|
702
|
+
)
|
|
688
703
|
if not disable_auto_ignore:
|
|
689
704
|
for untracked_file in untracked_git_files:
|
|
690
705
|
if (
|
|
@@ -1053,10 +1068,32 @@ def pull(
|
|
|
1053
1068
|
if calkit.dvc.detect_calkit_remote_type(name, url) == "http":
|
|
1054
1069
|
typer.echo(f"Checking authentication for DVC remote: {name}")
|
|
1055
1070
|
calkit.dvc.set_remote_auth(remote_name=name)
|
|
1071
|
+
if (
|
|
1072
|
+
not no_recursive
|
|
1073
|
+
and "--recursive" not in dvc_args
|
|
1074
|
+
and "-R" not in dvc_args
|
|
1075
|
+
):
|
|
1076
|
+
dvc_args.append("--recursive")
|
|
1056
1077
|
result = calkit.dvc.run_dvc_command(["pull"] + dvc_args)
|
|
1057
1078
|
if result != 0:
|
|
1058
1079
|
raise_error("DVC pull failed")
|
|
1059
1080
|
calkit.dvc.zip.sync_all(direction="to-workspace")
|
|
1081
|
+
if not no_recursive:
|
|
1082
|
+
# Pull DVC in isolated subprojects (those with their own .dvc folder)
|
|
1083
|
+
ck_info = calkit.load_calkit_info()
|
|
1084
|
+
for sp in ck_info.get("subprojects", []):
|
|
1085
|
+
if not isinstance(sp, dict) or not sp.get("path"):
|
|
1086
|
+
continue
|
|
1087
|
+
sp_path = sp["path"]
|
|
1088
|
+
if not os.path.isdir(os.path.join(sp_path, ".dvc")):
|
|
1089
|
+
continue
|
|
1090
|
+
typer.echo(f"DVC pulling subproject: {sp_path}")
|
|
1091
|
+
sp_result = calkit.dvc.run_dvc_command(
|
|
1092
|
+
["pull"] + dvc_args, cwd=sp_path
|
|
1093
|
+
)
|
|
1094
|
+
if sp_result != 0:
|
|
1095
|
+
raise_error(f"DVC pull failed for subproject: {sp_path}")
|
|
1096
|
+
calkit.dvc.zip.sync_all(direction="to-workspace", wdir=sp_path)
|
|
1060
1097
|
|
|
1061
1098
|
|
|
1062
1099
|
@app.command(name="push")
|
|
@@ -1431,13 +1468,8 @@ def run(
|
|
|
1431
1468
|
raise_error("Failed to initialize Git repo")
|
|
1432
1469
|
# Set env vars
|
|
1433
1470
|
calkit.set_env_vars(ck_info=ck_info)
|
|
1434
|
-
# Clean all notebooks in the pipeline
|
|
1435
|
-
try:
|
|
1436
|
-
calkit.notebooks.clean_all_in_pipeline(ck_info=ck_info)
|
|
1437
|
-
except Exception as e:
|
|
1438
|
-
raise_error(f"Failed to clean notebooks: {e.__class__.__name__}: {e}")
|
|
1439
1471
|
if not quiet:
|
|
1440
|
-
|
|
1472
|
+
calkit.echo("💻 Getting system information")
|
|
1441
1473
|
# Get system information
|
|
1442
1474
|
system_info = calkit.get_system_info()
|
|
1443
1475
|
if save_logs:
|
|
@@ -1453,7 +1485,7 @@ def run(
|
|
|
1453
1485
|
json.dump(system_info, f, indent=2)
|
|
1454
1486
|
# First check any system-level dependencies exist
|
|
1455
1487
|
if not quiet:
|
|
1456
|
-
|
|
1488
|
+
calkit.echo("🔗 Checking system-level dependencies")
|
|
1457
1489
|
try:
|
|
1458
1490
|
calkit.check_system_deps(ck_info=ck_info, system_info=system_info)
|
|
1459
1491
|
except Exception as e:
|
|
@@ -1461,7 +1493,7 @@ def run(
|
|
|
1461
1493
|
raise_error(str(e))
|
|
1462
1494
|
# Check all environments in the pipeline (with caching)
|
|
1463
1495
|
# If any failed, warn the user that we might have problems running
|
|
1464
|
-
|
|
1496
|
+
calkit.echo("📦 Checking environments")
|
|
1465
1497
|
env_check_results = calkit.environments.check_all_in_pipeline(
|
|
1466
1498
|
ck_info=ck_info, targets=targets, force=force
|
|
1467
1499
|
)
|
|
@@ -1471,7 +1503,13 @@ def run(
|
|
|
1471
1503
|
failed = not result.get("success", False)
|
|
1472
1504
|
if failed:
|
|
1473
1505
|
warn(f"Failed to check environment '{env_name}'")
|
|
1474
|
-
#
|
|
1506
|
+
# Clean all notebooks in the pipeline
|
|
1507
|
+
try:
|
|
1508
|
+
calkit.echo("📓 Cleaning notebooks")
|
|
1509
|
+
calkit.notebooks.clean_all_in_pipeline(ck_info=ck_info)
|
|
1510
|
+
except Exception as e:
|
|
1511
|
+
raise_error(f"Failed to clean notebooks: {e.__class__.__name__}: {e}")
|
|
1512
|
+
# Check environments and clean notebooks for each subproject
|
|
1475
1513
|
subprojects = ck_info.get("subprojects", [])
|
|
1476
1514
|
if subprojects:
|
|
1477
1515
|
prev_cwd = os.getcwd()
|
|
@@ -1481,11 +1519,13 @@ def run(
|
|
|
1481
1519
|
sp = Path(subproject["path"]).as_posix()
|
|
1482
1520
|
if not os.path.isdir(sp):
|
|
1483
1521
|
continue
|
|
1484
|
-
if not quiet:
|
|
1485
|
-
typer.echo(f"Checking environments for subproject: {sp}")
|
|
1486
1522
|
os.chdir(sp)
|
|
1487
1523
|
try:
|
|
1488
1524
|
sp_ck_info = calkit.load_calkit_info()
|
|
1525
|
+
if not quiet:
|
|
1526
|
+
calkit.echo(
|
|
1527
|
+
f"📦 Checking environments for subproject: {sp}"
|
|
1528
|
+
)
|
|
1489
1529
|
sp_env_results = calkit.environments.check_all_in_pipeline(
|
|
1490
1530
|
ck_info=sp_ck_info, force=force
|
|
1491
1531
|
)
|
|
@@ -1497,9 +1537,12 @@ def run(
|
|
|
1497
1537
|
f"Failed to check environment '{env_name}' "
|
|
1498
1538
|
f"in subproject '{sp}'"
|
|
1499
1539
|
)
|
|
1540
|
+
if not quiet:
|
|
1541
|
+
calkit.echo(f"📓 Cleaning notebooks for subproject: {sp}")
|
|
1542
|
+
calkit.notebooks.clean_all_in_pipeline(ck_info=sp_ck_info)
|
|
1500
1543
|
except Exception as e:
|
|
1501
1544
|
warn(
|
|
1502
|
-
f"Failed to
|
|
1545
|
+
f"Failed to prepare subproject '{sp}': "
|
|
1503
1546
|
f"{e.__class__.__name__}: {e}"
|
|
1504
1547
|
)
|
|
1505
1548
|
finally:
|
|
@@ -1511,7 +1554,7 @@ def run(
|
|
|
1511
1554
|
dvc_stages = None
|
|
1512
1555
|
if ck_info.get("pipeline", {}) or ck_info.get("subprojects"):
|
|
1513
1556
|
if not quiet:
|
|
1514
|
-
|
|
1557
|
+
calkit.echo("🔀 Compiling DVC pipeline")
|
|
1515
1558
|
try:
|
|
1516
1559
|
dvc_stages = calkit.pipeline.to_dvc(ck_info=ck_info, write=True)
|
|
1517
1560
|
except Exception as e:
|
|
@@ -7,6 +7,7 @@ import os
|
|
|
7
7
|
import re
|
|
8
8
|
import shutil
|
|
9
9
|
import subprocess
|
|
10
|
+
import sys
|
|
10
11
|
import warnings
|
|
11
12
|
from pathlib import Path
|
|
12
13
|
from typing import cast
|
|
@@ -137,6 +138,75 @@ def _editable_package_name_from_dir(dir_path: str) -> str:
|
|
|
137
138
|
raise ValueError(f"Could not determine package name from {dir_path}")
|
|
138
139
|
|
|
139
140
|
|
|
141
|
+
def _run_pip_freeze(env_prefix: str) -> list[str]:
|
|
142
|
+
"""Run pip freeze inside a conda env and return the list of packages.
|
|
143
|
+
|
|
144
|
+
Uses the env's pip executable directly (avoids ``conda run``, which can
|
|
145
|
+
touch the env directory and invalidate the stored mtime check).
|
|
146
|
+
This captures git URLs and exact refs that ``conda env export`` drops.
|
|
147
|
+
"""
|
|
148
|
+
if sys.platform == "win32":
|
|
149
|
+
pip_exe = os.path.join(env_prefix, "Scripts", "pip.exe")
|
|
150
|
+
else:
|
|
151
|
+
pip_exe = os.path.join(env_prefix, "bin", "pip")
|
|
152
|
+
if not os.path.isfile(pip_exe):
|
|
153
|
+
return []
|
|
154
|
+
output = subprocess.check_output([pip_exe, "freeze"]).decode()
|
|
155
|
+
return [
|
|
156
|
+
line.strip()
|
|
157
|
+
for line in output.splitlines()
|
|
158
|
+
if line.strip() and not line.startswith("#")
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
_GIT_RE = re.compile(r"\s*@\s*git\+", re.IGNORECASE)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def _pkg_name_from_dep(dep: str) -> str:
|
|
166
|
+
"""Extract the normalized package name from a pip/conda dep string."""
|
|
167
|
+
name = _GIT_RE.split(dep)[0]
|
|
168
|
+
name = re.split(r"[@=<>]", name)[0]
|
|
169
|
+
return name.strip().lower()
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def _enrich_pip_deps_from_freeze(
|
|
173
|
+
pip_deps: list[str],
|
|
174
|
+
pip_freeze: list[str],
|
|
175
|
+
) -> list[str]:
|
|
176
|
+
"""Replace pip dep entries with pip freeze versions when available.
|
|
177
|
+
|
|
178
|
+
Preserves git URLs and exact refs that conda env export drops.
|
|
179
|
+
Editable installs in pip_deps are kept unchanged.
|
|
180
|
+
"""
|
|
181
|
+
freeze_by_name = {
|
|
182
|
+
_pkg_name_from_dep(line): line
|
|
183
|
+
for line in pip_freeze
|
|
184
|
+
if not line.startswith("-e ") and "@ file://" not in line
|
|
185
|
+
}
|
|
186
|
+
result = []
|
|
187
|
+
for dep in pip_deps:
|
|
188
|
+
if dep.startswith("-e ") or dep.startswith("--editable "):
|
|
189
|
+
result.append(dep)
|
|
190
|
+
continue
|
|
191
|
+
name = _pkg_name_from_dep(dep)
|
|
192
|
+
result.append(freeze_by_name.get(name, dep))
|
|
193
|
+
return result
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _normalize_git_dep_url(dep: str) -> str:
|
|
197
|
+
"""Extract and normalize the git URL+ref from a dep string for comparison.
|
|
198
|
+
|
|
199
|
+
Returns the lowercased URL with .git suffix removed.
|
|
200
|
+
"""
|
|
201
|
+
parts = _GIT_RE.split(dep, maxsplit=1)
|
|
202
|
+
if len(parts) < 2:
|
|
203
|
+
return ""
|
|
204
|
+
url = parts[1].strip().lower()
|
|
205
|
+
if url.endswith(".git"):
|
|
206
|
+
url = url[:-4]
|
|
207
|
+
return url.rstrip("/")
|
|
208
|
+
|
|
209
|
+
|
|
140
210
|
def _check_single(
|
|
141
211
|
req: str, actual: str, env_spec_dir: str, conda: bool = False
|
|
142
212
|
) -> bool:
|
|
@@ -156,11 +226,28 @@ def _check_single(
|
|
|
156
226
|
req = os.path.join(env_spec_dir, req)
|
|
157
227
|
req = _editable_package_name_from_dir(req)
|
|
158
228
|
editable = True
|
|
159
|
-
#
|
|
160
|
-
#
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
229
|
+
# Handle git-based requirements — both legacy "pkg@git+url" and PEP 508
|
|
230
|
+
# "pkg @ git+url" forms.
|
|
231
|
+
req_is_git = bool(_GIT_RE.search(req))
|
|
232
|
+
actual_is_git = bool(_GIT_RE.search(actual))
|
|
233
|
+
if req_is_git and actual_is_git:
|
|
234
|
+
# Both sides have git URLs: compare normalized URL+ref directly.
|
|
235
|
+
# A short SHA in the spec matches a full SHA in the installed dep when
|
|
236
|
+
# the full SHA starts with the short one.
|
|
237
|
+
req_url = _normalize_git_dep_url(req)
|
|
238
|
+
actual_url = _normalize_git_dep_url(actual)
|
|
239
|
+
if req_url and actual_url:
|
|
240
|
+
req_base, _, req_ref = req_url.rpartition("@")
|
|
241
|
+
actual_base, _, actual_ref = actual_url.rpartition("@")
|
|
242
|
+
if req_base != actual_base:
|
|
243
|
+
return False
|
|
244
|
+
return actual_ref.startswith(req_ref) or req_ref.startswith(
|
|
245
|
+
actual_ref
|
|
246
|
+
)
|
|
247
|
+
# Fallback: compare names only
|
|
248
|
+
return _pkg_name_from_dep(req) == _pkg_name_from_dep(actual)
|
|
249
|
+
if req_is_git:
|
|
250
|
+
req = _GIT_RE.split(req)[0].strip()
|
|
164
251
|
req_name = re.split("[=<>]", req)[0].strip()
|
|
165
252
|
req_spec = req.removeprefix(req_name).strip().replace(" ", "")
|
|
166
253
|
if "[" in req_name:
|
|
@@ -176,9 +263,16 @@ def _check_single(
|
|
|
176
263
|
numbers_and_dots = re.match(r"^[0-9.]+$", req_spec[2:])
|
|
177
264
|
if numbers_and_dots and len(req_spec.split(".")) < 3:
|
|
178
265
|
req_spec += ".*"
|
|
179
|
-
|
|
180
|
-
|
|
266
|
+
if actual_is_git:
|
|
267
|
+
# Spec has no git URL but installed dep does; name match is sufficient
|
|
268
|
+
actual = _GIT_RE.split(actual)[0].strip()
|
|
269
|
+
actual_parts = re.split("[=<>]+", actual, maxsplit=1)
|
|
270
|
+
actual_name = actual_parts[0]
|
|
271
|
+
actual_vers = actual_parts[1] if len(actual_parts) > 1 else ""
|
|
272
|
+
if actual_name.strip().lower() != req_name.lower():
|
|
181
273
|
return False
|
|
274
|
+
if req_is_git or actual_is_git:
|
|
275
|
+
return True
|
|
182
276
|
actual_spec = actual.removeprefix(actual_name)
|
|
183
277
|
if conda and actual_spec.startswith("="):
|
|
184
278
|
actual_spec = "=" + actual_spec
|
|
@@ -328,6 +422,7 @@ def check_env(
|
|
|
328
422
|
os.remove(lock_to_use_for_creation)
|
|
329
423
|
lock_to_use_for_creation = None
|
|
330
424
|
res = EnvCheckResult()
|
|
425
|
+
early_pip_freeze: list[str] = []
|
|
331
426
|
if verbose:
|
|
332
427
|
log_func("Getting conda info")
|
|
333
428
|
conda_exe = find_conda_exe()
|
|
@@ -360,8 +455,10 @@ def check_env(
|
|
|
360
455
|
prefix_orig = prefix
|
|
361
456
|
if prefix is not None:
|
|
362
457
|
prefix = os.path.abspath(prefix)
|
|
458
|
+
env_prefix_path = prefix
|
|
363
459
|
env_check_fpath = os.path.join(prefix, "env-export.yml")
|
|
364
460
|
else:
|
|
461
|
+
env_prefix_path = os.path.join(envs_dir, env_name)
|
|
365
462
|
env_check_fpath = os.path.join(
|
|
366
463
|
os.path.expanduser("~"),
|
|
367
464
|
".calkit",
|
|
@@ -371,6 +468,8 @@ def check_env(
|
|
|
371
468
|
env_check_dir = os.path.dirname(env_check_fpath)
|
|
372
469
|
os.makedirs(env_check_dir, exist_ok=True)
|
|
373
470
|
env_spec_dir = os.path.dirname(os.path.abspath(env_fpath))
|
|
471
|
+
spec_pip_deps = _get_pip_dependency_list(env_spec["dependencies"])
|
|
472
|
+
spec_has_git_pip = any(_GIT_RE.search(d) for d in spec_pip_deps)
|
|
374
473
|
# Create env export command, which will be used later
|
|
375
474
|
export_cmd = [
|
|
376
475
|
conda_exe, # Mamba output is slightly different
|
|
@@ -464,8 +563,26 @@ def check_env(
|
|
|
464
563
|
env_check["mtime"] = os.path.getmtime(
|
|
465
564
|
os.path.normpath(env_check["prefix"])
|
|
466
565
|
)
|
|
467
|
-
|
|
468
|
-
|
|
566
|
+
# If the spec has git pip deps, enrich the in-memory env_check pip
|
|
567
|
+
# section so that git refs are compared correctly during the dep check
|
|
568
|
+
# rather than falling back to name-only matching.
|
|
569
|
+
if spec_has_git_pip:
|
|
570
|
+
log_func("Running pip freeze to enrich git dep comparison")
|
|
571
|
+
try:
|
|
572
|
+
early_pip_freeze = _run_pip_freeze(env_prefix_path)
|
|
573
|
+
except Exception as e:
|
|
574
|
+
log_func(
|
|
575
|
+
f"pip freeze failed; git dep URLs may be missing: {e}"
|
|
576
|
+
)
|
|
577
|
+
if early_pip_freeze:
|
|
578
|
+
check_pip = _get_pip_dependency_list(env_check["dependencies"])
|
|
579
|
+
enriched_check_pip = _enrich_pip_deps_from_freeze(
|
|
580
|
+
check_pip, early_pip_freeze
|
|
581
|
+
)
|
|
582
|
+
for dep_entry in env_check["dependencies"]:
|
|
583
|
+
if isinstance(dep_entry, dict) and "pip" in dep_entry:
|
|
584
|
+
dep_entry["pip"] = enriched_check_pip
|
|
585
|
+
break
|
|
469
586
|
# Determine if the env matches
|
|
470
587
|
env_needs_rebuild = False
|
|
471
588
|
existing_conda_deps, existing_pip_deps = _split_env_dependencies(
|
|
@@ -552,12 +669,41 @@ def check_env(
|
|
|
552
669
|
)
|
|
553
670
|
# If the env was rebuilt, export the env check
|
|
554
671
|
res.env_needs_export = env_needs_export
|
|
672
|
+
# Determine whether we need pip freeze output for enriching the stored
|
|
673
|
+
# env check and lock file with exact git URLs/refs.
|
|
674
|
+
needs_pip_freeze = (
|
|
675
|
+
env_needs_export
|
|
676
|
+
or not res.env_exists
|
|
677
|
+
or res.env_needs_rebuild
|
|
678
|
+
or spec_has_git_pip
|
|
679
|
+
)
|
|
680
|
+
pip_freeze: list[str] = []
|
|
681
|
+
if needs_pip_freeze:
|
|
682
|
+
# Reuse the early freeze captured before dep check when possible so
|
|
683
|
+
# we don't run pip twice; fall back to a fresh run after a rebuild.
|
|
684
|
+
if early_pip_freeze and not res.env_needs_rebuild:
|
|
685
|
+
pip_freeze = early_pip_freeze
|
|
686
|
+
else:
|
|
687
|
+
log_func("Running pip freeze to capture git deps")
|
|
688
|
+
try:
|
|
689
|
+
pip_freeze = _run_pip_freeze(env_prefix_path)
|
|
690
|
+
except Exception as e:
|
|
691
|
+
log_func(
|
|
692
|
+
f"pip freeze failed; git dep URLs may be missing: {e}"
|
|
693
|
+
)
|
|
555
694
|
if env_needs_export:
|
|
556
695
|
log_func(f"Exporting existing env to {env_check_fpath}")
|
|
557
696
|
env_check = json.loads(subprocess.check_output(export_cmd).decode())
|
|
558
697
|
env_check["mtime"] = os.path.getmtime(
|
|
559
698
|
os.path.normpath(env_check["prefix"])
|
|
560
699
|
)
|
|
700
|
+
if pip_freeze:
|
|
701
|
+
check_pip = _get_pip_dependency_list(env_check["dependencies"])
|
|
702
|
+
enriched = _enrich_pip_deps_from_freeze(check_pip, pip_freeze)
|
|
703
|
+
for dep_entry in env_check["dependencies"]:
|
|
704
|
+
if isinstance(dep_entry, dict) and "pip" in dep_entry:
|
|
705
|
+
dep_entry["pip"] = enriched
|
|
706
|
+
break
|
|
561
707
|
with open(env_check_fpath, "w") as f:
|
|
562
708
|
ryaml.dump(env_check, f)
|
|
563
709
|
if lock_fpath is None:
|
|
@@ -602,8 +748,13 @@ def check_env(
|
|
|
602
748
|
editable_pip_deps[pkg_name] = dir_path
|
|
603
749
|
export_pip_deps = _get_pip_dependency_list(env_export["dependencies"])
|
|
604
750
|
if export_pip_deps:
|
|
751
|
+
# Enrich with pip freeze to preserve git URLs, then fix editable paths
|
|
752
|
+
if pip_freeze:
|
|
753
|
+
export_pip_deps = _enrich_pip_deps_from_freeze(
|
|
754
|
+
export_pip_deps, pip_freeze
|
|
755
|
+
)
|
|
605
756
|
for i, dep in enumerate(export_pip_deps):
|
|
606
|
-
dep_name =
|
|
757
|
+
dep_name = _pkg_name_from_dep(dep)
|
|
607
758
|
if dep_name in editable_pip_deps:
|
|
608
759
|
path_rel_to_project_root = editable_pip_deps[dep_name]
|
|
609
760
|
lock_dir = os.path.dirname(lock_fpath)
|
|
@@ -613,9 +764,30 @@ def check_env(
|
|
|
613
764
|
export_pip_deps[i] = (
|
|
614
765
|
"-e " + Path(path_rel_to_lock).as_posix()
|
|
615
766
|
)
|
|
767
|
+
# Write the modified list back (enrichment returns a new list)
|
|
768
|
+
for dep_entry in env_export["dependencies"]:
|
|
769
|
+
if isinstance(dep_entry, dict) and "pip" in dep_entry:
|
|
770
|
+
dep_entry["pip"] = export_pip_deps
|
|
771
|
+
break
|
|
616
772
|
out_dir = os.path.dirname(lock_fpath)
|
|
617
773
|
if out_dir:
|
|
618
774
|
os.makedirs(out_dir, exist_ok=True)
|
|
619
775
|
with open(lock_fpath, "w") as f:
|
|
620
776
|
ryaml.dump(env_export, f)
|
|
777
|
+
elif pip_freeze and spec_has_git_pip and os.path.isfile(lock_fpath):
|
|
778
|
+
# The env matched the spec so no full re-export was done, but the
|
|
779
|
+
# existing lock file may pre-date pip freeze enrichment. Update its
|
|
780
|
+
# pip section in place — no conda env export needed.
|
|
781
|
+
with open(lock_fpath) as f:
|
|
782
|
+
lock_data = ryaml.load(f) or {}
|
|
783
|
+
lock_pip = _get_pip_dependency_list(lock_data.get("dependencies", []))
|
|
784
|
+
enriched = _enrich_pip_deps_from_freeze(lock_pip, pip_freeze)
|
|
785
|
+
if enriched != lock_pip:
|
|
786
|
+
log_func("Enriching existing lock file pip section with git URLs")
|
|
787
|
+
for dep_entry in lock_data.get("dependencies", []):
|
|
788
|
+
if isinstance(dep_entry, dict) and "pip" in dep_entry:
|
|
789
|
+
dep_entry["pip"] = enriched
|
|
790
|
+
break
|
|
791
|
+
with open(lock_fpath, "w") as f:
|
|
792
|
+
ryaml.dump(lock_data, f)
|
|
621
793
|
return res
|