calkit-python 0.39.1__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.1 → calkit_python-0.39.2}/PKG-INFO +1 -1
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/main/core.py +41 -20
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/conda.py +182 -10
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/pipeline.py +67 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_conda.py +59 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_pipeline.py +27 -1
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.claude-plugin/marketplace.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.gitignore +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.pre-commit-config.yaml +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.prettierignore +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.python-version +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.vscode/launch.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.vscode/tasks.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/.yarnrc.yml +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/AGENTS.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/CITATION.cff +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/CODE_OF_CONDUCT.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/CONTRIBUTING.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/LICENSE +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/Makefile +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/README.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/agent-plugin/.claude-plugin/plugin.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/agent-plugin/skills/add-pipeline-stage/SKILL.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/agent-plugin/skills/conventions/SKILL.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/agent-plugin/skills/create-pipeline/SKILL.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/babel.config.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/__main__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/calc.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/check.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/check.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/cloud.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/config.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/describe.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/dev.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/import_.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/latex.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/list.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/main/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/main/xr.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/new.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/notebooks.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/office.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/overleaf.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/slurm.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cli/update.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/cloud.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/config.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/datasets.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/detect.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/docker.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/dvc/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/dvc/core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/dvc/zip.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/environments.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/fs.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/git.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/github.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/gui.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/invenio.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/julia.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/jupyter.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/jupyterlab/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/jupyterlab/routes.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/package.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/schemas/calkit/package.json.orig +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/schemas/calkit/plugin.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/909.e3f9cc3408834a7fdcc3.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/remoteEntry.65469af996e7a96aa983.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/style.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/labextension/static/third-party-licenses.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/licenses.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/magics.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/matlab.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/models/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/models/core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/models/io.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/models/iteration.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/models/pipeline.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/notebooks.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/office.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/ops.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/overleaf.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/releases.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/server.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/main/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/main/test_core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/main/test_subprojects.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/main/test_xr.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_check.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_cloud.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_config.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_import.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_latex.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_new.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_notebooks.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_overleaf.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/cli/test_update.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/dvc/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/dvc/test_core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/dvc/test_zip.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/jupyterlab/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/jupyterlab/test_routes.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/models/__init__.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/models/test_iteration.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/models/test_pipeline.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_cloud.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_detect.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_docker.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_environments.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_fs.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_git.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_invenio.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_julia.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_matlab.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_notebooks.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_releases.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/conftest.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/CNAME +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/ai-tools.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/apps.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/calculations.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/cli-reference.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/cloud-integration.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/datasets.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/dependencies.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/environments.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/examples.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/governance.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/help.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/calkit-fragmentation-compendium.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/connect-zenodo.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/jupyterlab/all-green.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/jupyterlab/collect-data-stale.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/jupyterlab/new-env.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/jupyterlab/new-notebook.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/jupyterlab/pipeline-badge.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/jupyterlab-params.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/plos-osi-code-2024-03.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/img/vscode-nb-params.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/index.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/installation.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/jupyterlab.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/local-server.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/notebooks.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/overleaf.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/pipeline/index.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/pipeline/running-and-logging.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/pipeline/slurm.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/quickstart.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/references.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/releases.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/reproducibility.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/subprojects.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/existing-project.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/github-actions.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/actions-repo-secrets.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/quick-actions.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/create-calkit-env.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/create-inner-env.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/create-new-calkit-env.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/select-calkit-env.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/slurm-job-running.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/slurm-launch-options.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/img/vscode-slurm-notebook/starting-slurm-job.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/index.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/jupyterlab.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/office.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/tutorials/vscode-slurm-notebook.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/docs/version-control.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/install.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/jest.config.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/jupyter-config/server-config/calkit.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/mkdocs.yml +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/package.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/pyproject.toml +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/schema/plugin.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/scripts/generate-docs-references.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/scripts/install.ps1 +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/scripts/install.sh +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/scripts/make-calk9.sh +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/scripts/sync-docs.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/__tests__/useQueries.spec.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/calkit-config.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/cell-output-marker.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/commit-dialog.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/environment-editor.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/notebook-registration.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/notebook-toolbar.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/pipeline-status-bar.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/project-info-editor.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/sidebar-settings.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/sidebar.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/components/stage-editor.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/feature-flags.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/file-browser-menu.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/hooks/__tests__/useQueries.test.tsx +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/hooks/useQueries.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/icons.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/index.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/io-tracker.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/pipeline-state.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/queryClient.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/request.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/src/shims-mainmenu.d.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/base.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/cell-output-marker.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/environment-editor.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/environment-selector.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/img/calkit-no-bg.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/index.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/index.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/notebook-toolbar.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/pipeline-status-bar.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/style/sidebar.css +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/test/dvc-md5-dir/osx-arm64.txt +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/test/nb-julia.ipynb +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/test/nb-params.ipynb +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/test/nb-subdir.ipynb +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/test/pipeline.ipynb +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/test/script.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/test/test-log.log +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/tsconfig.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/tsconfig.test.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/ui-tests/.gitignore +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/ui-tests/README.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/ui-tests/jupyter_server_test_config.py +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/ui-tests/package.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/ui-tests/playwright.config.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/ui-tests/tests/calkit.spec.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/ui-tests/yarn.lock +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/uv.lock +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/.gitignore +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/.vscodeignore +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/CHANGELOG.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/LICENSE +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/README.md +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/images/calkit-no-bg.png +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/package-lock.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/package.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/scripts/set-proposed-api.js +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/src/environments.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/src/extension.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/src/notebooks.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/src/test/environments.test.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/src/test/kernel-selection.test.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/src/test/notebooks.test.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/src/types.ts +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/vscode-ext/tsconfig.json +0 -0
- {calkit_python-0.39.1 → calkit_python-0.39.2}/yarn.lock +0 -0
|
@@ -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 (
|
|
@@ -1453,13 +1468,8 @@ def run(
|
|
|
1453
1468
|
raise_error("Failed to initialize Git repo")
|
|
1454
1469
|
# Set env vars
|
|
1455
1470
|
calkit.set_env_vars(ck_info=ck_info)
|
|
1456
|
-
# Clean all notebooks in the pipeline
|
|
1457
|
-
try:
|
|
1458
|
-
calkit.notebooks.clean_all_in_pipeline(ck_info=ck_info)
|
|
1459
|
-
except Exception as e:
|
|
1460
|
-
raise_error(f"Failed to clean notebooks: {e.__class__.__name__}: {e}")
|
|
1461
1471
|
if not quiet:
|
|
1462
|
-
|
|
1472
|
+
calkit.echo("💻 Getting system information")
|
|
1463
1473
|
# Get system information
|
|
1464
1474
|
system_info = calkit.get_system_info()
|
|
1465
1475
|
if save_logs:
|
|
@@ -1475,7 +1485,7 @@ def run(
|
|
|
1475
1485
|
json.dump(system_info, f, indent=2)
|
|
1476
1486
|
# First check any system-level dependencies exist
|
|
1477
1487
|
if not quiet:
|
|
1478
|
-
|
|
1488
|
+
calkit.echo("🔗 Checking system-level dependencies")
|
|
1479
1489
|
try:
|
|
1480
1490
|
calkit.check_system_deps(ck_info=ck_info, system_info=system_info)
|
|
1481
1491
|
except Exception as e:
|
|
@@ -1483,7 +1493,7 @@ def run(
|
|
|
1483
1493
|
raise_error(str(e))
|
|
1484
1494
|
# Check all environments in the pipeline (with caching)
|
|
1485
1495
|
# If any failed, warn the user that we might have problems running
|
|
1486
|
-
|
|
1496
|
+
calkit.echo("📦 Checking environments")
|
|
1487
1497
|
env_check_results = calkit.environments.check_all_in_pipeline(
|
|
1488
1498
|
ck_info=ck_info, targets=targets, force=force
|
|
1489
1499
|
)
|
|
@@ -1493,7 +1503,13 @@ def run(
|
|
|
1493
1503
|
failed = not result.get("success", False)
|
|
1494
1504
|
if failed:
|
|
1495
1505
|
warn(f"Failed to check environment '{env_name}'")
|
|
1496
|
-
#
|
|
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
|
|
1497
1513
|
subprojects = ck_info.get("subprojects", [])
|
|
1498
1514
|
if subprojects:
|
|
1499
1515
|
prev_cwd = os.getcwd()
|
|
@@ -1503,11 +1519,13 @@ def run(
|
|
|
1503
1519
|
sp = Path(subproject["path"]).as_posix()
|
|
1504
1520
|
if not os.path.isdir(sp):
|
|
1505
1521
|
continue
|
|
1506
|
-
if not quiet:
|
|
1507
|
-
typer.echo(f"Checking environments for subproject: {sp}")
|
|
1508
1522
|
os.chdir(sp)
|
|
1509
1523
|
try:
|
|
1510
1524
|
sp_ck_info = calkit.load_calkit_info()
|
|
1525
|
+
if not quiet:
|
|
1526
|
+
calkit.echo(
|
|
1527
|
+
f"📦 Checking environments for subproject: {sp}"
|
|
1528
|
+
)
|
|
1511
1529
|
sp_env_results = calkit.environments.check_all_in_pipeline(
|
|
1512
1530
|
ck_info=sp_ck_info, force=force
|
|
1513
1531
|
)
|
|
@@ -1519,9 +1537,12 @@ def run(
|
|
|
1519
1537
|
f"Failed to check environment '{env_name}' "
|
|
1520
1538
|
f"in subproject '{sp}'"
|
|
1521
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)
|
|
1522
1543
|
except Exception as e:
|
|
1523
1544
|
warn(
|
|
1524
|
-
f"Failed to
|
|
1545
|
+
f"Failed to prepare subproject '{sp}': "
|
|
1525
1546
|
f"{e.__class__.__name__}: {e}"
|
|
1526
1547
|
)
|
|
1527
1548
|
finally:
|
|
@@ -1533,7 +1554,7 @@ def run(
|
|
|
1533
1554
|
dvc_stages = None
|
|
1534
1555
|
if ck_info.get("pipeline", {}) or ck_info.get("subprojects"):
|
|
1535
1556
|
if not quiet:
|
|
1536
|
-
|
|
1557
|
+
calkit.echo("🔀 Compiling DVC pipeline")
|
|
1537
1558
|
try:
|
|
1538
1559
|
dvc_stages = calkit.pipeline.to_dvc(ck_info=ck_info, write=True)
|
|
1539
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
|
|
@@ -324,6 +324,60 @@ def _paths_overlap(a: str, b: str) -> bool:
|
|
|
324
324
|
return b.startswith(a + "/") or a.startswith(b + "/")
|
|
325
325
|
|
|
326
326
|
|
|
327
|
+
def _expand_dep_excluding_subprojects(
|
|
328
|
+
dep: str,
|
|
329
|
+
isolated_sp_paths: list[str],
|
|
330
|
+
root: str | None = None,
|
|
331
|
+
) -> list[str]:
|
|
332
|
+
"""Expand a directory dep to avoid traversing into isolated subprojects.
|
|
333
|
+
|
|
334
|
+
DVC cannot collect a directory dep that contains a nested DVC repo (i.e.
|
|
335
|
+
an isolated subproject identified by a ``.dvc/`` directory). This function
|
|
336
|
+
walks ``dep``, listing its contents and skipping any isolated subproject
|
|
337
|
+
directory, so the returned paths collectively cover the same files without
|
|
338
|
+
crossing into the subprojects.
|
|
339
|
+
|
|
340
|
+
``root`` is the directory relative to which ``dep`` and ``isolated_sp_paths``
|
|
341
|
+
are expressed (defaults to cwd).
|
|
342
|
+
"""
|
|
343
|
+
root_path = Path(root) if root else Path(".")
|
|
344
|
+
dep_path = root_path / dep
|
|
345
|
+
# Resolve once for reliable path comparison
|
|
346
|
+
dep_resolved = dep_path.resolve()
|
|
347
|
+
sp_set = {(root_path / sp).resolve() for sp in isolated_sp_paths}
|
|
348
|
+
nested = [
|
|
349
|
+
sp
|
|
350
|
+
for sp in sp_set
|
|
351
|
+
if sp != dep_resolved and sp.is_relative_to(dep_resolved)
|
|
352
|
+
]
|
|
353
|
+
if not nested or not dep_path.is_dir():
|
|
354
|
+
return [dep]
|
|
355
|
+
result: list[str] = []
|
|
356
|
+
|
|
357
|
+
def _walk(dir_path: Path) -> None:
|
|
358
|
+
try:
|
|
359
|
+
children = sorted(dir_path.iterdir())
|
|
360
|
+
except PermissionError:
|
|
361
|
+
return
|
|
362
|
+
for child in children:
|
|
363
|
+
child_resolved = child.resolve()
|
|
364
|
+
if child_resolved in sp_set:
|
|
365
|
+
# Skip the isolated subproject entirely
|
|
366
|
+
continue
|
|
367
|
+
if child.is_dir() and any(
|
|
368
|
+
sp.is_relative_to(child_resolved) for sp in nested
|
|
369
|
+
):
|
|
370
|
+
# This directory is an ancestor of an isolated SP; descend
|
|
371
|
+
_walk(child)
|
|
372
|
+
else:
|
|
373
|
+
rel = child.relative_to(root_path)
|
|
374
|
+
suffix = "/" if child.is_dir() else ""
|
|
375
|
+
result.append(rel.as_posix() + suffix)
|
|
376
|
+
|
|
377
|
+
_walk(dep_path)
|
|
378
|
+
return result if result else [dep]
|
|
379
|
+
|
|
380
|
+
|
|
327
381
|
def collapse_dvc_stages(
|
|
328
382
|
stages: dict,
|
|
329
383
|
cmd: str | None = None,
|
|
@@ -728,6 +782,7 @@ def to_dvc(
|
|
|
728
782
|
# For inline subprojects (no .dvc/ dir), DVC discovers them automatically
|
|
729
783
|
# via --all-pipelines so no wrapper stage is needed.
|
|
730
784
|
wrapper_stages: dict[str, dict] = {}
|
|
785
|
+
isolated_sp_paths: list[str] = []
|
|
731
786
|
for subproject in ck_info.get("subprojects", []):
|
|
732
787
|
if not isinstance(subproject, dict) or not subproject.get("path"):
|
|
733
788
|
raise ValueError("Subprojects must have a 'path' defined")
|
|
@@ -746,6 +801,7 @@ def to_dvc(
|
|
|
746
801
|
)
|
|
747
802
|
if not sp_is_isolated:
|
|
748
803
|
continue
|
|
804
|
+
isolated_sp_paths.append(sp)
|
|
749
805
|
if not sp_dvc_stages:
|
|
750
806
|
import warnings
|
|
751
807
|
|
|
@@ -915,6 +971,17 @@ def to_dvc(
|
|
|
915
971
|
dvc_stage["deps"] = formatted_deps
|
|
916
972
|
dvc_stage["outs"] = formatted_outs
|
|
917
973
|
dvc_stage["matrix"] = dvc_matrix
|
|
974
|
+
# Expand any directory deps that contain isolated subprojects so DVC
|
|
975
|
+
# doesn't try to traverse into their .dvcignore files
|
|
976
|
+
if isolated_sp_paths:
|
|
977
|
+
expanded_deps = []
|
|
978
|
+
for dep in dvc_stage.get("deps", []):
|
|
979
|
+
expanded_deps.extend(
|
|
980
|
+
_expand_dep_excluding_subprojects(
|
|
981
|
+
dep, isolated_sp_paths, root=wdir
|
|
982
|
+
)
|
|
983
|
+
)
|
|
984
|
+
dvc_stage["deps"] = expanded_deps
|
|
918
985
|
# Add a description to the DVC stage
|
|
919
986
|
desc = (
|
|
920
987
|
f"Automatically generated from the '{stage_name}' stage "
|
|
@@ -10,6 +10,7 @@ import calkit
|
|
|
10
10
|
from calkit.conda import (
|
|
11
11
|
_check_list,
|
|
12
12
|
_check_single,
|
|
13
|
+
_enrich_pip_deps_from_freeze,
|
|
13
14
|
_get_pip_dependency_list,
|
|
14
15
|
_split_env_dependencies,
|
|
15
16
|
check_env,
|
|
@@ -31,6 +32,64 @@ def test_check_single():
|
|
|
31
32
|
assert _check_single(
|
|
32
33
|
"python>=3.12,<3.13", "python==3.12.18", env_spec_dir=".", conda=False
|
|
33
34
|
)
|
|
35
|
+
# PEP 508 git direct reference in req matches plain installed version
|
|
36
|
+
assert _check_single(
|
|
37
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b",
|
|
38
|
+
"pyxdsm==0.4.0",
|
|
39
|
+
env_spec_dir=".",
|
|
40
|
+
conda=False,
|
|
41
|
+
)
|
|
42
|
+
# Different package name must not match
|
|
43
|
+
assert not _check_single(
|
|
44
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b",
|
|
45
|
+
"other==1.0",
|
|
46
|
+
env_spec_dir=".",
|
|
47
|
+
conda=False,
|
|
48
|
+
)
|
|
49
|
+
# Both sides git: same ref → match
|
|
50
|
+
assert _check_single(
|
|
51
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b",
|
|
52
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b",
|
|
53
|
+
env_spec_dir=".",
|
|
54
|
+
conda=False,
|
|
55
|
+
)
|
|
56
|
+
# Both sides git: short spec ref matches long installed ref (prefix)
|
|
57
|
+
assert _check_single(
|
|
58
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b",
|
|
59
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b07ca1234",
|
|
60
|
+
env_spec_dir=".",
|
|
61
|
+
conda=False,
|
|
62
|
+
)
|
|
63
|
+
# Both sides git: different refs → no match
|
|
64
|
+
assert not _check_single(
|
|
65
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b",
|
|
66
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@aabbcc1",
|
|
67
|
+
env_spec_dir=".",
|
|
68
|
+
conda=False,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_enrich_pip_deps_from_freeze():
|
|
73
|
+
pip_freeze = [
|
|
74
|
+
"numpy==1.24.3",
|
|
75
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b07ca",
|
|
76
|
+
"scipy==1.11.0",
|
|
77
|
+
]
|
|
78
|
+
spec_deps = [
|
|
79
|
+
"numpy==1.24.3",
|
|
80
|
+
"pyxdsm @ git+https://github.com/rebeccamccabe/pyXDSM.git@fc0b49b",
|
|
81
|
+
"scipy",
|
|
82
|
+
]
|
|
83
|
+
result = _enrich_pip_deps_from_freeze(spec_deps, pip_freeze)
|
|
84
|
+
# numpy and scipy get the exact freeze version
|
|
85
|
+
assert "numpy==1.24.3" in result
|
|
86
|
+
assert "scipy==1.11.0" in result
|
|
87
|
+
# pyxdsm gets the full git URL from freeze
|
|
88
|
+
assert any("fc0b49b07ca" in r for r in result)
|
|
89
|
+
# Editable installs are kept unchanged
|
|
90
|
+
editable = ["-e ../mypackage", "numpy==1.24.3"]
|
|
91
|
+
result2 = _enrich_pip_deps_from_freeze(editable, pip_freeze)
|
|
92
|
+
assert result2[0] == "-e ../mypackage"
|
|
34
93
|
|
|
35
94
|
|
|
36
95
|
def test_check_list():
|
|
@@ -9,7 +9,11 @@ import pytest
|
|
|
9
9
|
import calkit
|
|
10
10
|
import calkit.pipeline
|
|
11
11
|
from calkit.environments import get_env_lock_fpath
|
|
12
|
-
from calkit.pipeline import
|
|
12
|
+
from calkit.pipeline import (
|
|
13
|
+
_expand_dep_excluding_subprojects,
|
|
14
|
+
collapse_dvc_stages,
|
|
15
|
+
stages_are_similar,
|
|
16
|
+
)
|
|
13
17
|
|
|
14
18
|
|
|
15
19
|
def test_stages_are_similar():
|
|
@@ -1160,6 +1164,28 @@ def test_wrapper_stage_no_dep_out_overlap(tmp_dir):
|
|
|
1160
1164
|
), f"wrapper dep '{dep}' tree-overlaps out '{out}'"
|
|
1161
1165
|
|
|
1162
1166
|
|
|
1167
|
+
def test_expand_dep_excluding_subprojects(tmp_dir):
|
|
1168
|
+
# Directory dep not containing any isolated subproject returns as-is
|
|
1169
|
+
os.makedirs("src")
|
|
1170
|
+
open("src/a.py", "w").close()
|
|
1171
|
+
result = _expand_dep_excluding_subprojects("src", [])
|
|
1172
|
+
assert result == ["src"]
|
|
1173
|
+
# Directory dep containing an isolated subproject is expanded to siblings
|
|
1174
|
+
os.makedirs("sim/modules/SubProj/.dvc")
|
|
1175
|
+
open("sim/modules/other.py", "w").close()
|
|
1176
|
+
open("sim/run.py", "w").close()
|
|
1177
|
+
result = _expand_dep_excluding_subprojects("sim", ["sim/modules/SubProj"])
|
|
1178
|
+
assert "sim/run.py" in result
|
|
1179
|
+
assert "sim/modules/other.py" in result
|
|
1180
|
+
# The isolated subproject itself must not appear in the expansion
|
|
1181
|
+
assert not any("SubProj" in r for r in result)
|
|
1182
|
+
# A dep that is not a directory returns as-is
|
|
1183
|
+
result = _expand_dep_excluding_subprojects(
|
|
1184
|
+
"sim/run.py", ["sim/modules/SubProj"]
|
|
1185
|
+
)
|
|
1186
|
+
assert result == ["sim/run.py"]
|
|
1187
|
+
|
|
1188
|
+
|
|
1163
1189
|
def test_translate_run_targets(tmp_dir):
|
|
1164
1190
|
# Set up a parent project with one inline subproject and one isolated.
|
|
1165
1191
|
subprocess.check_call(["git", "init"])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{calkit_python-0.39.1 → calkit_python-0.39.2}/agent-plugin/skills/add-pipeline-stage/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|