calkit-python 0.35.1__tar.gz → 0.35.3__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.35.1 → calkit_python-0.35.3}/.gitignore +2 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/PKG-INFO +1 -1
- calkit_python-0.35.3/calkit/cli/main/__init__.py +2 -0
- calkit_python-0.35.1/calkit/cli/main.py → calkit_python-0.35.3/calkit/cli/main/core.py +21 -501
- calkit_python-0.35.3/calkit/cli/main/xr.py +680 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/new.py +15 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/detect.py +29 -5
- calkit_python-0.35.3/calkit/docker.py +470 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/environments.py +10 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/models/core.py +1 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/models/pipeline.py +11 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/overleaf.py +73 -14
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/pipeline.py +1 -0
- calkit_python-0.35.1/calkit/tests/cli/test_main.py → calkit_python-0.35.3/calkit/tests/cli/main/test_core.py +19 -601
- calkit_python-0.35.3/calkit/tests/cli/main/test_xr.py +726 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_overleaf.py +39 -0
- calkit_python-0.35.3/calkit/tests/models/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_detect.py +8 -0
- calkit_python-0.35.3/calkit/tests/test_docker.py +70 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_pipeline.py +6 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/environments.md +24 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/pipeline/index.md +58 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/uv.lock +3 -3
- calkit_python-0.35.1/calkit/docker.py +0 -69
- {calkit_python-0.35.1 → calkit_python-0.35.3}/.pre-commit-config.yaml +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/.prettierignore +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/.python-version +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/.yarnrc.yml +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/CITATION.cff +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/CODE_OF_CONDUCT.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/CONTRIBUTING.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/LICENSE +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/Makefile +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/README.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/babel.config.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/__main__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/calc.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/check.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/check.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/cloud.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/config.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/core.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/describe.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/import_.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/latex.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/list.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/notebooks.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/office.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/overleaf.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/slurm.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cli/update.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/cloud.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/conda.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/config.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/core.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/datasets.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/dvc.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/fs.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/git.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/github.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/gui.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/invenio.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/julia.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/jupyter.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/jupyterlab/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/jupyterlab/routes.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/package.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/schemas/calkit/package.json.orig +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/schemas/calkit/plugin.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/909.651be47ca47390b78a92.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/remoteEntry.c091821b3d7f2d287a67.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/style.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/labextension/static/third-party-licenses.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/licenses.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/magics.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/matlab.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/models/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/models/io.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/models/iteration.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/notebooks.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/office.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/ops.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/releases.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/server.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/core.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.35.1/calkit/tests/jupyterlab → calkit_python-0.35.3/calkit/tests/cli/main}/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_check.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_config.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_import.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_latex.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_new.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/cli/test_notebooks.py +0 -0
- {calkit_python-0.35.1/calkit/tests/models → calkit_python-0.35.3/calkit/tests/jupyterlab}/__init__.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/jupyterlab/test_routes.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/models/test_iteration.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/models/test_pipeline.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_conda.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_dvc.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_environments.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_fs.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_git.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_invenio.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_julia.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_matlab.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_notebooks.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/conftest.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/CNAME +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/apps.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/calculations.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/cli-reference.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/cloud-integration.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/datasets.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/dependencies.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/examples.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/governance.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/help.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/calkit-fragmentation-compendium.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/connect-zenodo.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/jupyterlab/all-green.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/jupyterlab/collect-data-stale.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/jupyterlab/new-env.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/jupyterlab/new-notebook.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/jupyterlab/pipeline-badge.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/jupyterlab-params.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/plos-osi-code-2024-03.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/img/vscode-nb-params.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/index.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/installation.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/jupyterlab.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/local-server.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/notebooks.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/overleaf.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/pipeline/running-and-logging.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/pipeline/slurm.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/quickstart.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/references.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/releases.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/reproducibility.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/existing-project.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/github-actions.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/actions-repo-secrets.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/quick-actions.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/index.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/jupyterlab.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/office.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/docs/version-control.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/install.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/jest.config.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/jupyter-config/server-config/calkit.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/mkdocs.yml +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/package.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/pyproject.toml +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/schema/plugin.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/scripts/install.ps1 +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/scripts/install.sh +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/scripts/make-calk9.sh +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/scripts/sync-docs.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/__tests__/useQueries.spec.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/calkit-config.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/cell-output-marker.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/commit-dialog.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/environment-editor.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/notebook-registration.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/notebook-toolbar.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/pipeline-status-bar.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/project-info-editor.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/sidebar-settings.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/sidebar.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/components/stage-editor.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/feature-flags.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/file-browser-menu.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/hooks/__tests__/useQueries.test.tsx +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/hooks/useQueries.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/icons.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/index.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/io-tracker.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/pipeline-state.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/queryClient.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/request.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/src/shims-mainmenu.d.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/base.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/cell-output-marker.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/environment-editor.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/environment-selector.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/img/calkit-no-bg.png +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/index.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/index.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/notebook-toolbar.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/pipeline-status-bar.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/style/sidebar.css +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/test/dvc-md5-dir/osx-arm64.txt +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/test/nb-julia.ipynb +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/test/nb-params.ipynb +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/test/nb-subdir.ipynb +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/test/pipeline.ipynb +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/test/script.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/test/test-log.log +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/tsconfig.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/tsconfig.test.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/ui-tests/.gitignore +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/ui-tests/README.md +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/ui-tests/jupyter_server_test_config.py +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/ui-tests/package.json +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/ui-tests/playwright.config.js +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/ui-tests/tests/calkit.spec.ts +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/ui-tests/yarn.lock +0 -0
- {calkit_python-0.35.1 → calkit_python-0.35.3}/yarn.lock +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Core functionality in the main namespace of the CLI."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
@@ -1325,10 +1325,11 @@ def run(
|
|
|
1325
1325
|
if failed:
|
|
1326
1326
|
raise_error("Pipeline failed")
|
|
1327
1327
|
else:
|
|
1328
|
+
_enc = sys.stdout.encoding or "utf-8"
|
|
1328
1329
|
typer.echo(
|
|
1329
1330
|
"Pipeline completed successfully ✅".encode(
|
|
1330
|
-
|
|
1331
|
-
)
|
|
1331
|
+
_enc, errors="replace"
|
|
1332
|
+
).decode(_enc)
|
|
1332
1333
|
)
|
|
1333
1334
|
if save_after_run or save_message is not None:
|
|
1334
1335
|
if save_message is None:
|
|
@@ -1472,6 +1473,12 @@ def run_in_env(
|
|
|
1472
1473
|
if env["kind"] == "docker":
|
|
1473
1474
|
if "image" not in env:
|
|
1474
1475
|
raise_error("Image must be defined for Docker environments")
|
|
1476
|
+
command_mode = env.get("command_mode", "shell")
|
|
1477
|
+
if command_mode not in ["shell", "entrypoint"]:
|
|
1478
|
+
raise_error(
|
|
1479
|
+
"Invalid Docker environment 'command_mode': "
|
|
1480
|
+
f"{command_mode}; Use 'shell' or 'entrypoint'"
|
|
1481
|
+
)
|
|
1475
1482
|
if not no_check:
|
|
1476
1483
|
check_docker_env(
|
|
1477
1484
|
tag=env["image"],
|
|
@@ -1489,7 +1496,6 @@ def run_in_env(
|
|
|
1489
1496
|
args=env.get("args", []),
|
|
1490
1497
|
quiet=not verbose,
|
|
1491
1498
|
)
|
|
1492
|
-
shell_cmd = _to_shell_cmd(cmd)
|
|
1493
1499
|
docker_cmd = [
|
|
1494
1500
|
"docker",
|
|
1495
1501
|
"run",
|
|
@@ -1536,10 +1542,17 @@ def run_in_env(
|
|
|
1536
1542
|
"-v",
|
|
1537
1543
|
f"{os.getcwd()}:{docker_wdir_mount}",
|
|
1538
1544
|
image_name,
|
|
1539
|
-
shell,
|
|
1540
|
-
"-c",
|
|
1541
|
-
shell_cmd,
|
|
1542
1545
|
]
|
|
1546
|
+
if command_mode == "shell":
|
|
1547
|
+
shell_cmd = _to_shell_cmd(cmd)
|
|
1548
|
+
docker_cmd += [shell, "-c", shell_cmd]
|
|
1549
|
+
else:
|
|
1550
|
+
if not cmd:
|
|
1551
|
+
raise_error(
|
|
1552
|
+
"No command provided for Docker environment in "
|
|
1553
|
+
"'entrypoint' command mode"
|
|
1554
|
+
)
|
|
1555
|
+
docker_cmd += cmd
|
|
1543
1556
|
if verbose:
|
|
1544
1557
|
typer.echo(f"Running command: {docker_cmd}")
|
|
1545
1558
|
try:
|
|
@@ -1876,499 +1889,6 @@ def run_in_env(
|
|
|
1876
1889
|
raise_error("Environment kind not supported")
|
|
1877
1890
|
|
|
1878
1891
|
|
|
1879
|
-
@app.command(name="xr")
|
|
1880
|
-
def execute_and_record(
|
|
1881
|
-
cmd: Annotated[
|
|
1882
|
-
list[str],
|
|
1883
|
-
typer.Argument(
|
|
1884
|
-
help="Command to execute and record. "
|
|
1885
|
-
"If the first argument is a script, notebook or LaTeX file, "
|
|
1886
|
-
"it will be treated as a stage with that file as "
|
|
1887
|
-
"the target. Any command, including arguments, is supported."
|
|
1888
|
-
),
|
|
1889
|
-
],
|
|
1890
|
-
environment: Annotated[
|
|
1891
|
-
str | None,
|
|
1892
|
-
typer.Option(
|
|
1893
|
-
"--environment",
|
|
1894
|
-
"-e",
|
|
1895
|
-
help="Name of or path the spec file for the environment to use.",
|
|
1896
|
-
),
|
|
1897
|
-
] = None,
|
|
1898
|
-
inputs: Annotated[
|
|
1899
|
-
list[str],
|
|
1900
|
-
typer.Option(
|
|
1901
|
-
"--input",
|
|
1902
|
-
"-i",
|
|
1903
|
-
help="Input paths to record.",
|
|
1904
|
-
),
|
|
1905
|
-
] = [],
|
|
1906
|
-
outputs: Annotated[
|
|
1907
|
-
list[str],
|
|
1908
|
-
typer.Option(
|
|
1909
|
-
"--output",
|
|
1910
|
-
"-o",
|
|
1911
|
-
help="Output paths to record.",
|
|
1912
|
-
),
|
|
1913
|
-
] = [],
|
|
1914
|
-
no_detect_io: Annotated[
|
|
1915
|
-
bool,
|
|
1916
|
-
typer.Option(
|
|
1917
|
-
"--no-detect-io",
|
|
1918
|
-
help=(
|
|
1919
|
-
"Don't attempt to detect inputs and outputs from the command, "
|
|
1920
|
-
"script, or notebook."
|
|
1921
|
-
),
|
|
1922
|
-
),
|
|
1923
|
-
] = False,
|
|
1924
|
-
stage_name: Annotated[
|
|
1925
|
-
str | None,
|
|
1926
|
-
typer.Option(
|
|
1927
|
-
"--stage",
|
|
1928
|
-
help=(
|
|
1929
|
-
"Name of the DVC stage to create for this command. If not "
|
|
1930
|
-
"provided, a name will be generated automatically."
|
|
1931
|
-
),
|
|
1932
|
-
),
|
|
1933
|
-
] = None,
|
|
1934
|
-
dry_run: Annotated[
|
|
1935
|
-
bool,
|
|
1936
|
-
typer.Option(
|
|
1937
|
-
"--dry-run",
|
|
1938
|
-
"-d",
|
|
1939
|
-
help=(
|
|
1940
|
-
"Print the environment and stage that would be created "
|
|
1941
|
-
"without modifying calkit.yaml or executing the command."
|
|
1942
|
-
),
|
|
1943
|
-
),
|
|
1944
|
-
] = False,
|
|
1945
|
-
force: Annotated[
|
|
1946
|
-
bool,
|
|
1947
|
-
typer.Option(
|
|
1948
|
-
"--force",
|
|
1949
|
-
"-f",
|
|
1950
|
-
help="Force running stage even if it's up-to-date.",
|
|
1951
|
-
),
|
|
1952
|
-
] = False,
|
|
1953
|
-
verbose: Annotated[
|
|
1954
|
-
bool, typer.Option("--verbose", "-v", help="Print verbose output.")
|
|
1955
|
-
] = False,
|
|
1956
|
-
):
|
|
1957
|
-
"""Execute a command and if successful, record in the pipeline."""
|
|
1958
|
-
import io
|
|
1959
|
-
import shlex
|
|
1960
|
-
|
|
1961
|
-
from calkit.detect import (
|
|
1962
|
-
detect_io,
|
|
1963
|
-
generate_stage_name,
|
|
1964
|
-
)
|
|
1965
|
-
from calkit.environments import detect_env_for_stage
|
|
1966
|
-
from calkit.models.io import PathOutput
|
|
1967
|
-
from calkit.models.pipeline import (
|
|
1968
|
-
JuliaCommandStage,
|
|
1969
|
-
JuliaScriptStage,
|
|
1970
|
-
JupyterNotebookStage,
|
|
1971
|
-
LatexStage,
|
|
1972
|
-
MatlabCommandStage,
|
|
1973
|
-
MatlabScriptStage,
|
|
1974
|
-
PythonScriptStage,
|
|
1975
|
-
RScriptStage,
|
|
1976
|
-
ShellCommandStage,
|
|
1977
|
-
ShellScriptStage,
|
|
1978
|
-
)
|
|
1979
|
-
from calkit.pipeline import stages_are_similar
|
|
1980
|
-
|
|
1981
|
-
def _determine_output_storage(
|
|
1982
|
-
path: str,
|
|
1983
|
-
repo: git.Repo | None = None,
|
|
1984
|
-
dvc_paths: list[str] | None = None,
|
|
1985
|
-
) -> str:
|
|
1986
|
-
"""Determine storage type (git or dvc) for an output path.
|
|
1987
|
-
|
|
1988
|
-
Parameters
|
|
1989
|
-
----------
|
|
1990
|
-
path : str
|
|
1991
|
-
Path to check.
|
|
1992
|
-
repo : git.Repo | None
|
|
1993
|
-
Git repository. If None, only extension and size are checked.
|
|
1994
|
-
dvc_paths : list[str] | None
|
|
1995
|
-
List of paths tracked by DVC.
|
|
1996
|
-
|
|
1997
|
-
Returns
|
|
1998
|
-
-------
|
|
1999
|
-
str
|
|
2000
|
-
"git" or "dvc".
|
|
2001
|
-
"""
|
|
2002
|
-
if dvc_paths is None:
|
|
2003
|
-
dvc_paths = []
|
|
2004
|
-
# If already tracked by git, use git
|
|
2005
|
-
if repo is not None and repo.git.ls_files(path):
|
|
2006
|
-
return "git"
|
|
2007
|
-
# If already tracked by dvc, use dvc
|
|
2008
|
-
if path in dvc_paths:
|
|
2009
|
-
return "dvc"
|
|
2010
|
-
# Check extension
|
|
2011
|
-
if os.path.splitext(path)[-1] in DVC_EXTENSIONS:
|
|
2012
|
-
return "dvc"
|
|
2013
|
-
# Check size if file exists
|
|
2014
|
-
if os.path.exists(path):
|
|
2015
|
-
try:
|
|
2016
|
-
if calkit.get_size(path) > DVC_SIZE_THRESH_BYTES:
|
|
2017
|
-
return "dvc"
|
|
2018
|
-
except (OSError, IOError):
|
|
2019
|
-
# If we cannot determine file size (e.g., permission
|
|
2020
|
-
# or I/O issues), fall back to the default "git"
|
|
2021
|
-
# behavior below.
|
|
2022
|
-
pass
|
|
2023
|
-
# Default to git for small/unknown files
|
|
2024
|
-
return "git"
|
|
2025
|
-
|
|
2026
|
-
# First, read the pipeline before running so we can revert if the stage
|
|
2027
|
-
# fails
|
|
2028
|
-
ck_info = calkit.load_calkit_info()
|
|
2029
|
-
ck_info_orig = deepcopy(ck_info)
|
|
2030
|
-
pipeline = ck_info.get("pipeline", {})
|
|
2031
|
-
stages = pipeline.get("stages", {})
|
|
2032
|
-
# Strip and detect uv/pixi run prefix
|
|
2033
|
-
if len(cmd) >= 2 and cmd[0] == "uv" and cmd[1] == "run":
|
|
2034
|
-
if environment is None and os.path.isfile("pyproject.toml"):
|
|
2035
|
-
environment = "pyproject.toml"
|
|
2036
|
-
cmd = cmd[2:]
|
|
2037
|
-
elif len(cmd) >= 2 and cmd[0] == "pixi" and cmd[1] == "run":
|
|
2038
|
-
if environment is None and os.path.isfile("pixi.toml"):
|
|
2039
|
-
environment = "pixi.toml"
|
|
2040
|
-
cmd = cmd[2:]
|
|
2041
|
-
# Guard against empty command after stripping uv/pixi run
|
|
2042
|
-
if not cmd:
|
|
2043
|
-
raise_error(
|
|
2044
|
-
"No command specified after stripping environment prefix. "
|
|
2045
|
-
"Usage: calkit xr [uv|pixi run] <command> [args]"
|
|
2046
|
-
)
|
|
2047
|
-
# Detect what kind of stage this is based on the command
|
|
2048
|
-
# If the first argument is a notebook, we'll treat this as a notebook stage
|
|
2049
|
-
# If the first argument is `python`, check that the second argument is a
|
|
2050
|
-
# script, otherwise it's a shell-command stage
|
|
2051
|
-
# If the first argument ends with .tex, we'll treat this as a LaTeX stage
|
|
2052
|
-
first_arg = cmd[0]
|
|
2053
|
-
stage = {}
|
|
2054
|
-
language = None
|
|
2055
|
-
if first_arg.endswith(".ipynb"):
|
|
2056
|
-
cls = JupyterNotebookStage
|
|
2057
|
-
stage["kind"] = "jupyter-notebook"
|
|
2058
|
-
stage["notebook_path"] = first_arg
|
|
2059
|
-
storage = calkit.notebooks.determine_storage(first_arg)
|
|
2060
|
-
stage["html_storage"] = storage
|
|
2061
|
-
stage["executed_ipynb_storage"] = storage
|
|
2062
|
-
elif first_arg.endswith(".tex"):
|
|
2063
|
-
cls = LatexStage
|
|
2064
|
-
stage["kind"] = "latex"
|
|
2065
|
-
stage["target_path"] = first_arg
|
|
2066
|
-
language = "latex"
|
|
2067
|
-
# Determine PDF storage based on whether it's already in git
|
|
2068
|
-
pdf_path = first_arg.removesuffix(".tex") + ".pdf"
|
|
2069
|
-
try:
|
|
2070
|
-
repo = git.Repo(".")
|
|
2071
|
-
if repo.git.ls_files(pdf_path):
|
|
2072
|
-
stage["pdf_storage"] = "git"
|
|
2073
|
-
else:
|
|
2074
|
-
stage["pdf_storage"] = "dvc"
|
|
2075
|
-
except InvalidGitRepositoryError:
|
|
2076
|
-
# Not a git repo, default to dvc
|
|
2077
|
-
stage["pdf_storage"] = "dvc"
|
|
2078
|
-
elif first_arg == "python" and len(cmd) > 1 and cmd[1].endswith(".py"):
|
|
2079
|
-
cls = PythonScriptStage
|
|
2080
|
-
stage["kind"] = "python-script"
|
|
2081
|
-
stage["script_path"] = cmd[1]
|
|
2082
|
-
if len(cmd) > 2:
|
|
2083
|
-
stage["args"] = cmd[2:]
|
|
2084
|
-
language = "python"
|
|
2085
|
-
elif first_arg.endswith(".py"):
|
|
2086
|
-
cls = PythonScriptStage
|
|
2087
|
-
stage["kind"] = "python-script"
|
|
2088
|
-
stage["script_path"] = first_arg
|
|
2089
|
-
if len(cmd) > 1:
|
|
2090
|
-
stage["args"] = cmd[1:]
|
|
2091
|
-
language = "python"
|
|
2092
|
-
elif first_arg == "julia" and len(cmd) > 1 and cmd[1].endswith(".jl"):
|
|
2093
|
-
cls = JuliaScriptStage
|
|
2094
|
-
stage["kind"] = "julia-script"
|
|
2095
|
-
stage["script_path"] = cmd[1]
|
|
2096
|
-
if len(cmd) > 2:
|
|
2097
|
-
stage["args"] = cmd[2:]
|
|
2098
|
-
language = "julia"
|
|
2099
|
-
elif first_arg.endswith(".jl"):
|
|
2100
|
-
cls = JuliaScriptStage
|
|
2101
|
-
stage["kind"] = "julia-script"
|
|
2102
|
-
stage["script_path"] = first_arg
|
|
2103
|
-
if len(cmd) > 1:
|
|
2104
|
-
stage["args"] = cmd[1:]
|
|
2105
|
-
language = "julia"
|
|
2106
|
-
elif first_arg == "julia" and len(cmd) > 1:
|
|
2107
|
-
cls = JuliaCommandStage
|
|
2108
|
-
stage["kind"] = "julia-command"
|
|
2109
|
-
stage["command"] = " ".join(cmd[1:])
|
|
2110
|
-
language = "julia"
|
|
2111
|
-
elif first_arg == "matlab" and len(cmd) > 1 and cmd[1].endswith(".m"):
|
|
2112
|
-
cls = MatlabScriptStage
|
|
2113
|
-
stage["kind"] = "matlab-script"
|
|
2114
|
-
stage["script_path"] = cmd[1]
|
|
2115
|
-
language = "matlab"
|
|
2116
|
-
elif first_arg.endswith(".m"):
|
|
2117
|
-
cls = MatlabScriptStage
|
|
2118
|
-
stage["kind"] = "matlab-script"
|
|
2119
|
-
stage["script_path"] = first_arg
|
|
2120
|
-
language = "matlab"
|
|
2121
|
-
elif first_arg == "matlab" and len(cmd) > 1:
|
|
2122
|
-
cls = MatlabCommandStage
|
|
2123
|
-
stage["kind"] = "matlab-command"
|
|
2124
|
-
stage["command"] = " ".join(cmd[1:])
|
|
2125
|
-
language = "matlab"
|
|
2126
|
-
elif first_arg == "Rscript" and len(cmd) > 1 and cmd[1].endswith(".R"):
|
|
2127
|
-
cls = RScriptStage
|
|
2128
|
-
stage["kind"] = "r-script"
|
|
2129
|
-
stage["script_path"] = cmd[1]
|
|
2130
|
-
if len(cmd) > 2:
|
|
2131
|
-
stage["args"] = cmd[2:]
|
|
2132
|
-
language = "r"
|
|
2133
|
-
elif first_arg.endswith(".R"):
|
|
2134
|
-
cls = RScriptStage
|
|
2135
|
-
stage["kind"] = "r-script"
|
|
2136
|
-
stage["script_path"] = first_arg
|
|
2137
|
-
if len(cmd) > 1:
|
|
2138
|
-
stage["args"] = cmd[1:]
|
|
2139
|
-
language = "r"
|
|
2140
|
-
elif first_arg.endswith((".sh", ".bash", ".zsh")):
|
|
2141
|
-
cls = ShellScriptStage
|
|
2142
|
-
stage["kind"] = "shell-script"
|
|
2143
|
-
stage["script_path"] = first_arg
|
|
2144
|
-
if len(cmd) > 1:
|
|
2145
|
-
stage["args"] = cmd[1:]
|
|
2146
|
-
# Detect shell type from extension
|
|
2147
|
-
if first_arg.endswith(".bash"):
|
|
2148
|
-
stage["shell"] = "bash"
|
|
2149
|
-
elif first_arg.endswith(".zsh"):
|
|
2150
|
-
stage["shell"] = "zsh"
|
|
2151
|
-
else:
|
|
2152
|
-
stage["shell"] = "sh"
|
|
2153
|
-
language = "shell"
|
|
2154
|
-
else:
|
|
2155
|
-
cls = ShellCommandStage
|
|
2156
|
-
stage["kind"] = "shell-command"
|
|
2157
|
-
stage["command"] = " ".join(shlex.quote(arg) for arg in cmd)
|
|
2158
|
-
language = "shell"
|
|
2159
|
-
# Create a stage name if one isn't provided and check for existing similar
|
|
2160
|
-
# stages
|
|
2161
|
-
if stage_name is None:
|
|
2162
|
-
base_stage_name = generate_stage_name(cmd)
|
|
2163
|
-
stage_name = base_stage_name
|
|
2164
|
-
# If a stage with this name exists and is different, auto-increment
|
|
2165
|
-
if stage_name in stages:
|
|
2166
|
-
existing_stage = stages[stage_name]
|
|
2167
|
-
if not stages_are_similar(existing_stage, stage):
|
|
2168
|
-
# Find the next available increment
|
|
2169
|
-
counter = 2
|
|
2170
|
-
while f"{base_stage_name}-{counter}" in stages:
|
|
2171
|
-
candidate_stage = stages[f"{base_stage_name}-{counter}"]
|
|
2172
|
-
if stages_are_similar(candidate_stage, stage):
|
|
2173
|
-
# Found a matching stage with this incremented name
|
|
2174
|
-
stage_name = f"{base_stage_name}-{counter}"
|
|
2175
|
-
break
|
|
2176
|
-
counter += 1
|
|
2177
|
-
else:
|
|
2178
|
-
# No matching stage found, use the next available number
|
|
2179
|
-
stage_name = f"{base_stage_name}-{counter}"
|
|
2180
|
-
typer.echo(
|
|
2181
|
-
f"Stage '{base_stage_name}' already exists with different "
|
|
2182
|
-
f"configuration; using '{stage_name}' instead"
|
|
2183
|
-
)
|
|
2184
|
-
# Check if a similar stage already exists and reuse its environment if not
|
|
2185
|
-
# specified
|
|
2186
|
-
if stage_name in stages:
|
|
2187
|
-
existing_stage = stages[stage_name]
|
|
2188
|
-
if not stages_are_similar(existing_stage, stage):
|
|
2189
|
-
raise_error(
|
|
2190
|
-
f"A stage named '{stage_name}' already exists with "
|
|
2191
|
-
"different configuration; "
|
|
2192
|
-
f"Please specify a unique stage name with --stage"
|
|
2193
|
-
)
|
|
2194
|
-
return
|
|
2195
|
-
# If no environment was specified and a similar stage exists,
|
|
2196
|
-
# reuse its environment
|
|
2197
|
-
if environment is None and "environment" in existing_stage:
|
|
2198
|
-
environment = existing_stage["environment"]
|
|
2199
|
-
typer.echo(
|
|
2200
|
-
f"Reusing environment '{environment}' from existing "
|
|
2201
|
-
f"stage '{stage_name}'"
|
|
2202
|
-
)
|
|
2203
|
-
# Detect or create environment for this stage
|
|
2204
|
-
env_result = detect_env_for_stage(
|
|
2205
|
-
stage=stage,
|
|
2206
|
-
environment=environment,
|
|
2207
|
-
ck_info=ck_info,
|
|
2208
|
-
language=language,
|
|
2209
|
-
)
|
|
2210
|
-
# If we created an environment from dependencies, write the spec file
|
|
2211
|
-
if env_result.created_from_dependencies and not dry_run:
|
|
2212
|
-
typer.echo(
|
|
2213
|
-
"No existing environment detected; "
|
|
2214
|
-
"Attempting to create one based on detected dependencies"
|
|
2215
|
-
)
|
|
2216
|
-
if env_result.dependencies:
|
|
2217
|
-
typer.echo(
|
|
2218
|
-
f"Detected {language or 'code'} dependencies: "
|
|
2219
|
-
f"{', '.join(env_result.dependencies)}"
|
|
2220
|
-
)
|
|
2221
|
-
if env_result.spec_path and env_result.spec_content is not None:
|
|
2222
|
-
# Create the spec file
|
|
2223
|
-
spec_dir = os.path.dirname(env_result.spec_path)
|
|
2224
|
-
if spec_dir:
|
|
2225
|
-
os.makedirs(spec_dir, exist_ok=True)
|
|
2226
|
-
with open(env_result.spec_path, "w") as f:
|
|
2227
|
-
f.write(env_result.spec_content)
|
|
2228
|
-
typer.echo(f"Created environment spec: {env_result.spec_path}")
|
|
2229
|
-
# Add environment to calkit.yaml if it doesn't exist
|
|
2230
|
-
if not env_result.exists and not dry_run:
|
|
2231
|
-
envs = ck_info.get("environments", {})
|
|
2232
|
-
envs[env_result.name] = env_result.env
|
|
2233
|
-
ck_info["environments"] = envs
|
|
2234
|
-
with open("calkit.yaml", "w") as f:
|
|
2235
|
-
calkit.ryaml.dump(ck_info, f)
|
|
2236
|
-
ck_info = calkit.load_calkit_info()
|
|
2237
|
-
env_name = env_result.name
|
|
2238
|
-
stage["environment"] = env_name
|
|
2239
|
-
# Detect inputs and outputs if not disabled
|
|
2240
|
-
detected_inputs = []
|
|
2241
|
-
detected_outputs = []
|
|
2242
|
-
if not no_detect_io:
|
|
2243
|
-
try:
|
|
2244
|
-
io_info = detect_io(stage)
|
|
2245
|
-
detected_inputs = io_info["inputs"]
|
|
2246
|
-
detected_outputs = io_info["outputs"]
|
|
2247
|
-
except Exception as e:
|
|
2248
|
-
typer.echo(
|
|
2249
|
-
f"Warning: Failed to detect inputs/outputs: {e}",
|
|
2250
|
-
err=True,
|
|
2251
|
-
)
|
|
2252
|
-
# Initialize git repo and get DVC paths for storage determination
|
|
2253
|
-
try:
|
|
2254
|
-
repo = git.Repo(".")
|
|
2255
|
-
except InvalidGitRepositoryError:
|
|
2256
|
-
repo = None
|
|
2257
|
-
dvc_paths = []
|
|
2258
|
-
if repo is not None:
|
|
2259
|
-
try:
|
|
2260
|
-
dvc_paths = calkit.dvc.list_paths()
|
|
2261
|
-
except Exception:
|
|
2262
|
-
# DVC might not be initialized
|
|
2263
|
-
pass
|
|
2264
|
-
# Merge user-specified inputs/outputs with detected ones
|
|
2265
|
-
# User-specified take precedence and detected ones are added if not already
|
|
2266
|
-
# present
|
|
2267
|
-
all_inputs = list(inputs) # Start with user-specified
|
|
2268
|
-
for detected in detected_inputs:
|
|
2269
|
-
if detected not in all_inputs:
|
|
2270
|
-
all_inputs.append(detected)
|
|
2271
|
-
# Convert detected outputs to PathOutput models with storage determination
|
|
2272
|
-
detected_output_models: list[str | PathOutput] = []
|
|
2273
|
-
for detected in detected_outputs:
|
|
2274
|
-
storage = _determine_output_storage(detected, repo, dvc_paths)
|
|
2275
|
-
detected_output_models.append(
|
|
2276
|
-
PathOutput(
|
|
2277
|
-
path=detected,
|
|
2278
|
-
storage=storage, # type: ignore[arg-type]
|
|
2279
|
-
)
|
|
2280
|
-
)
|
|
2281
|
-
# Merge outputs
|
|
2282
|
-
all_outputs: list[str | PathOutput] = list(
|
|
2283
|
-
outputs
|
|
2284
|
-
) # Start with user-specified
|
|
2285
|
-
for detected in detected_output_models:
|
|
2286
|
-
# Check if this output path is already present
|
|
2287
|
-
detected_path = (
|
|
2288
|
-
detected.path if isinstance(detected, PathOutput) else detected
|
|
2289
|
-
)
|
|
2290
|
-
already_present = False
|
|
2291
|
-
for existing in all_outputs:
|
|
2292
|
-
existing_path = (
|
|
2293
|
-
existing.path if isinstance(existing, PathOutput) else existing
|
|
2294
|
-
)
|
|
2295
|
-
if existing_path == detected_path:
|
|
2296
|
-
already_present = True
|
|
2297
|
-
break
|
|
2298
|
-
if not already_present:
|
|
2299
|
-
all_outputs.append(detected)
|
|
2300
|
-
# Add inputs and outputs to stage
|
|
2301
|
-
if all_inputs:
|
|
2302
|
-
stage["inputs"] = all_inputs
|
|
2303
|
-
if all_outputs:
|
|
2304
|
-
# Convert PathOutput objects to dicts for serialization
|
|
2305
|
-
serialized_outputs = []
|
|
2306
|
-
for output in all_outputs:
|
|
2307
|
-
if isinstance(output, PathOutput):
|
|
2308
|
-
serialized_outputs.append(
|
|
2309
|
-
output.model_dump(exclude_unset=True)
|
|
2310
|
-
)
|
|
2311
|
-
else:
|
|
2312
|
-
serialized_outputs.append(output)
|
|
2313
|
-
stage["outputs"] = serialized_outputs
|
|
2314
|
-
# Create the stage, write to calkit.yaml, and run it to see if
|
|
2315
|
-
# it's successful
|
|
2316
|
-
try:
|
|
2317
|
-
cls.model_validate(stage)
|
|
2318
|
-
except Exception as e:
|
|
2319
|
-
raise_error(f"Failed to create stage: {e}")
|
|
2320
|
-
# If dry-run, print environment and stage then return
|
|
2321
|
-
if dry_run:
|
|
2322
|
-
# Print environment info
|
|
2323
|
-
if env_result.created_from_dependencies:
|
|
2324
|
-
typer.echo("Environment (would be created):")
|
|
2325
|
-
if env_result.spec_path and env_result.spec_content is not None:
|
|
2326
|
-
typer.echo(f" Spec file: {env_result.spec_path}")
|
|
2327
|
-
typer.echo(" Content:")
|
|
2328
|
-
for line in env_result.spec_content.split("\n"):
|
|
2329
|
-
typer.echo(f" {line}")
|
|
2330
|
-
elif not env_result.exists:
|
|
2331
|
-
typer.echo("Environment (would be added to calkit.yaml):")
|
|
2332
|
-
yaml_output = io.StringIO()
|
|
2333
|
-
calkit.ryaml.dump({env_result.name: env_result.env}, yaml_output)
|
|
2334
|
-
for line in yaml_output.getvalue().rstrip().split("\n"):
|
|
2335
|
-
typer.echo(f" {line}")
|
|
2336
|
-
else:
|
|
2337
|
-
typer.echo(f"Environment: {env_name} (already exists)")
|
|
2338
|
-
# Print stage
|
|
2339
|
-
typer.echo("\nStage (would be added to pipeline):")
|
|
2340
|
-
yaml_output = io.StringIO()
|
|
2341
|
-
calkit.ryaml.dump({stage_name: stage}, yaml_output)
|
|
2342
|
-
for line in yaml_output.getvalue().rstrip().split("\n"):
|
|
2343
|
-
typer.echo(f" {line}")
|
|
2344
|
-
return
|
|
2345
|
-
stages[stage_name] = stage
|
|
2346
|
-
pipeline["stages"] = stages
|
|
2347
|
-
ck_info["pipeline"] = pipeline
|
|
2348
|
-
with open("calkit.yaml", "w") as f:
|
|
2349
|
-
calkit.ryaml.dump(ck_info, f)
|
|
2350
|
-
try:
|
|
2351
|
-
# Format stage as YAML for display
|
|
2352
|
-
yaml_output = io.StringIO()
|
|
2353
|
-
calkit.ryaml.dump({stage_name: stage}, yaml_output)
|
|
2354
|
-
# Indent YAML by 2 spaces
|
|
2355
|
-
indented_yaml = "\n".join(
|
|
2356
|
-
" " + line if line.strip() else line
|
|
2357
|
-
for line in yaml_output.getvalue().rstrip().split("\n")
|
|
2358
|
-
)
|
|
2359
|
-
typer.echo(
|
|
2360
|
-
f"Adding stage to pipeline and attempting to execute:"
|
|
2361
|
-
f"\n{indented_yaml}"
|
|
2362
|
-
)
|
|
2363
|
-
run(targets=[stage_name], force=force, verbose=verbose)
|
|
2364
|
-
except Exception as e:
|
|
2365
|
-
# If the stage failed, write the old ck_info back to calkit.yaml to
|
|
2366
|
-
# remove the stage that we added
|
|
2367
|
-
with open("calkit.yaml", "w") as f:
|
|
2368
|
-
calkit.ryaml.dump(ck_info_orig, f)
|
|
2369
|
-
raise_error(f"Failed to execute stage: {e}")
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
1892
|
@app.command(name="runproc", help="Execute a procedure (alias for 'xproc').")
|
|
2373
1893
|
@app.command(name="xproc", help="Execute a procedure.")
|
|
2374
1894
|
def run_procedure(
|
|
@@ -2388,7 +1908,7 @@ def run_procedure(
|
|
|
2388
1908
|
typer.echo(out, nl=False)
|
|
2389
1909
|
time.sleep(dt)
|
|
2390
1910
|
seconds -= dt
|
|
2391
|
-
typer.echo()
|
|
1911
|
+
typer.echo("Done")
|
|
2392
1912
|
|
|
2393
1913
|
def convert_value(value, dtype):
|
|
2394
1914
|
if dtype == "int":
|