calkit-python 0.35.6__tar.gz → 0.36.0__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.6 → calkit_python-0.36.0}/.gitignore +1 -1
- calkit_python-0.36.0/.vscode/launch.json +17 -0
- calkit_python-0.36.0/.vscode/tasks.json +15 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/PKG-INFO +1 -1
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/main/core.py +131 -21
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/new.py +227 -51
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/notebooks.py +119 -13
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/update.py +154 -2
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/dvc.py +9 -8
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/jupyterlab/routes.py +2 -4
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/package.json +14 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/schemas/calkit/package.json.orig +14 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/pipeline.py +305 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/releases.py +81 -10
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/server.py +3 -3
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_new.py +107 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_notebooks.py +36 -0
- calkit_python-0.36.0/calkit/tests/cli/test_update.py +22 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_pipeline.py +77 -0
- calkit_python-0.36.0/calkit/tests/test_releases.py +150 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/cli-reference.md +149 -41
- {calkit_python-0.35.6 → calkit_python-0.36.0}/package.json +14 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/pyproject.toml +1 -0
- calkit_python-0.36.0/vscode-ext/.gitignore +3 -0
- calkit_python-0.36.0/vscode-ext/.vscodeignore +5 -0
- calkit_python-0.36.0/vscode-ext/CHANGELOG.md +6 -0
- calkit_python-0.36.0/vscode-ext/LICENSE +19 -0
- calkit_python-0.36.0/vscode-ext/README.md +66 -0
- calkit_python-0.36.0/vscode-ext/images/calkit-no-bg.png +0 -0
- calkit_python-0.36.0/vscode-ext/package-lock.json +77 -0
- calkit_python-0.36.0/vscode-ext/package.json +138 -0
- calkit_python-0.36.0/vscode-ext/scripts/set-proposed-api.js +25 -0
- calkit_python-0.36.0/vscode-ext/src/environments.ts +224 -0
- calkit_python-0.36.0/vscode-ext/src/extension.ts +3510 -0
- calkit_python-0.36.0/vscode-ext/src/notebooks.ts +79 -0
- calkit_python-0.36.0/vscode-ext/src/test/environments.test.ts +130 -0
- calkit_python-0.36.0/vscode-ext/src/test/notebooks.test.ts +70 -0
- calkit_python-0.36.0/vscode-ext/src/types.ts +25 -0
- calkit_python-0.36.0/vscode-ext/tsconfig.json +14 -0
- calkit_python-0.35.6/calkit/tests/test_releases.py +0 -44
- {calkit_python-0.35.6 → calkit_python-0.36.0}/.pre-commit-config.yaml +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/.prettierignore +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/.python-version +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/.yarnrc.yml +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/CITATION.cff +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/CODE_OF_CONDUCT.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/CONTRIBUTING.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/LICENSE +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/Makefile +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/README.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/babel.config.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/__main__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/calc.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/check.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/check.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/cloud.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/config.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/core.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/describe.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/import_.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/latex.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/list.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/main/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/main/xr.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/office.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/overleaf.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cli/slurm.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/cloud.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/conda.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/config.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/core.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/datasets.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/detect.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/docker.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/environments.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/fs.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/git.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/github.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/gui.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/invenio.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/julia.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/jupyter.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/jupyterlab/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/schemas/calkit/plugin.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/502.9a2c5772a15466e923ef.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/695.2c41003a452d43d2b358.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/867.a42a046aa5108f54f8fb.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/909.651be47ca47390b78a92.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/946.050af2abf7845cfbdbd2.js.LICENSE.txt +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/b2f1c3efe70cb539d121.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/remoteEntry.c091821b3d7f2d287a67.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/style.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/labextension/static/third-party-licenses.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/licenses.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/magics.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/matlab.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/models/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/models/core.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/models/io.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/models/iteration.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/models/pipeline.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/notebooks.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/office.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/ops.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/overleaf.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/core.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/main/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/main/test_core.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/main/test_xr.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_check.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_config.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_import.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_latex.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/cli/test_overleaf.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/jupyterlab/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/jupyterlab/test_routes.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/models/__init__.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/models/test_iteration.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/models/test_pipeline.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_conda.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_detect.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_docker.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_dvc.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_environments.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_fs.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_git.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_invenio.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_julia.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_matlab.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_notebooks.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/conftest.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/CNAME +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/apps.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/calculations.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/cloud-integration.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/datasets.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/dependencies.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/environments.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/examples.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/governance.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/help.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/calkit-fragmentation-compendium.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/connect-zenodo.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/jupyterlab/all-green.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/jupyterlab/collect-data-stale.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/jupyterlab/new-env.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/jupyterlab/new-notebook.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/jupyterlab/pipeline-badge.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/jupyterlab-params.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/plos-osi-code-2024-03.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/img/vscode-nb-params.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/index.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/installation.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/jupyterlab.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/local-server.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/notebooks.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/overleaf.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/pipeline/index.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/pipeline/running-and-logging.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/pipeline/slurm.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/quickstart.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/references.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/releases.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/reproducibility.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/existing-project.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/github-actions.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/actions-repo-secrets.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/quick-actions.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/index.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/jupyterlab.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/office.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/docs/version-control.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/install.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/jest.config.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/jupyter-config/server-config/calkit.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/mkdocs.yml +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/schema/plugin.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/scripts/generate-cli-reference.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/scripts/install.ps1 +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/scripts/install.sh +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/scripts/make-calk9.sh +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/scripts/sync-docs.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/__tests__/useQueries.spec.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/calkit-config.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/cell-output-marker.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/commit-dialog.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/environment-editor.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/notebook-registration.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/notebook-toolbar.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/pipeline-status-bar.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/project-info-editor.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/sidebar-settings.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/sidebar.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/components/stage-editor.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/feature-flags.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/file-browser-menu.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/hooks/__tests__/useQueries.test.tsx +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/hooks/useQueries.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/icons.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/index.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/io-tracker.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/pipeline-state.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/queryClient.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/request.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/src/shims-mainmenu.d.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/base.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/cell-output-marker.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/environment-editor.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/environment-selector.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/img/calkit-no-bg.png +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/index.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/index.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/notebook-toolbar.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/pipeline-status-bar.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/style/sidebar.css +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/test/dvc-md5-dir/osx-arm64.txt +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/test/nb-julia.ipynb +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/test/nb-params.ipynb +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/test/nb-subdir.ipynb +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/test/pipeline.ipynb +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/test/script.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/test/test-log.log +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/tsconfig.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/tsconfig.test.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/ui-tests/.gitignore +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/ui-tests/README.md +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/ui-tests/jupyter_server_test_config.py +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/ui-tests/package.json +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/ui-tests/playwright.config.js +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/ui-tests/tests/calkit.spec.ts +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/ui-tests/yarn.lock +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/uv.lock +0 -0
- {calkit_python-0.35.6 → calkit_python-0.36.0}/yarn.lock +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Run Calkit VS Code Extension",
|
|
6
|
+
"type": "extensionHost",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"runtimeExecutable": "${execPath}",
|
|
9
|
+
"args": [
|
|
10
|
+
"--extensionDevelopmentPath=${workspaceFolder}/vscode-ext",
|
|
11
|
+
"--enable-proposed-api=calkit.calkit-vscode"
|
|
12
|
+
],
|
|
13
|
+
"outFiles": ["${workspaceFolder}/vscode-ext/out/**/*.js"],
|
|
14
|
+
"preLaunchTask": "npm: compile (vscode-ext)"
|
|
15
|
+
}
|
|
16
|
+
]
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "2.0.0",
|
|
3
|
+
"tasks": [
|
|
4
|
+
{
|
|
5
|
+
"type": "shell",
|
|
6
|
+
"command": "npm",
|
|
7
|
+
"args": ["run", "dev:compile"],
|
|
8
|
+
"options": {
|
|
9
|
+
"cwd": "${workspaceFolder}/vscode-ext"
|
|
10
|
+
},
|
|
11
|
+
"label": "npm: compile (vscode-ext)",
|
|
12
|
+
"problemMatcher": ["$tsc"]
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -55,7 +55,7 @@ from calkit.cli.office import office_app
|
|
|
55
55
|
from calkit.cli.overleaf import overleaf_app
|
|
56
56
|
from calkit.cli.slurm import slurm_app
|
|
57
57
|
from calkit.cli.update import update_app
|
|
58
|
-
from calkit.dvc import
|
|
58
|
+
from calkit.dvc import get_dvc_repo, run_dvc_command
|
|
59
59
|
from calkit.environments import get_env_lock_fpath
|
|
60
60
|
from calkit.models import Procedure
|
|
61
61
|
|
|
@@ -249,13 +249,18 @@ def get_status(
|
|
|
249
249
|
),
|
|
250
250
|
),
|
|
251
251
|
] = None,
|
|
252
|
+
as_json: Annotated[
|
|
253
|
+
bool, typer.Option("--json", help="Output status as JSON.")
|
|
254
|
+
] = False,
|
|
252
255
|
):
|
|
253
256
|
"""View status (project, version control, and/or pipeline)."""
|
|
254
257
|
ck_info = calkit.load_calkit_info()
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
# If there's anything in ck_info and this isn't a Git repo, initialize one
|
|
259
|
+
if ck_info:
|
|
260
|
+
try:
|
|
261
|
+
git.Repo()
|
|
262
|
+
except InvalidGitRepositoryError:
|
|
263
|
+
git.Repo.init()
|
|
259
264
|
valid_categories = ["project", "git", "dvc", "pipeline"]
|
|
260
265
|
if categories is not None:
|
|
261
266
|
for category in categories:
|
|
@@ -266,11 +271,94 @@ def get_status(
|
|
|
266
271
|
)
|
|
267
272
|
else:
|
|
268
273
|
categories = valid_categories
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
calkit.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
+
pipeline_status = None
|
|
275
|
+
if "pipeline" in categories or "dvc" in categories:
|
|
276
|
+
pipeline_status = calkit.pipeline.get_status(
|
|
277
|
+
ck_info=ck_info,
|
|
278
|
+
targets=targets,
|
|
279
|
+
check_environments=True,
|
|
280
|
+
clean_notebooks=True,
|
|
281
|
+
compile_to_dvc=True,
|
|
282
|
+
)
|
|
283
|
+
for error in pipeline_status.errors:
|
|
284
|
+
warn(error)
|
|
285
|
+
if pipeline_status.failed_environment_checks:
|
|
286
|
+
warn(
|
|
287
|
+
"Failed pipeline environment checks for: "
|
|
288
|
+
+ ", ".join(pipeline_status.failed_environment_checks)
|
|
289
|
+
)
|
|
290
|
+
if as_json:
|
|
291
|
+
status_dict = {}
|
|
292
|
+
if "project" in categories:
|
|
293
|
+
status = calkit.get_latest_project_status()
|
|
294
|
+
status_dict["project"] = (
|
|
295
|
+
None
|
|
296
|
+
if status is None
|
|
297
|
+
else {
|
|
298
|
+
"status": status.status,
|
|
299
|
+
"message": status.message,
|
|
300
|
+
"timestamp": status.timestamp.isoformat(),
|
|
301
|
+
}
|
|
302
|
+
)
|
|
303
|
+
if "git" in categories:
|
|
304
|
+
try:
|
|
305
|
+
repo = git.Repo()
|
|
306
|
+
changed_files = calkit.git.get_changed_files(repo=repo)
|
|
307
|
+
staged_files = calkit.git.get_staged_files(repo=repo)
|
|
308
|
+
untracked_files = calkit.git.get_untracked_files(repo=repo)
|
|
309
|
+
if targets:
|
|
310
|
+
target_prefixes = [
|
|
311
|
+
Path(target).as_posix().rstrip("/")
|
|
312
|
+
for target in targets
|
|
313
|
+
]
|
|
314
|
+
|
|
315
|
+
def _matches_target(path: str) -> bool:
|
|
316
|
+
path = Path(path).as_posix()
|
|
317
|
+
return any(
|
|
318
|
+
path == prefix or path.startswith(prefix + "/")
|
|
319
|
+
for prefix in target_prefixes
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
changed_files = [
|
|
323
|
+
path for path in changed_files if _matches_target(path)
|
|
324
|
+
]
|
|
325
|
+
staged_files = [
|
|
326
|
+
path for path in staged_files if _matches_target(path)
|
|
327
|
+
]
|
|
328
|
+
untracked_files = [
|
|
329
|
+
path
|
|
330
|
+
for path in untracked_files
|
|
331
|
+
if _matches_target(path)
|
|
332
|
+
]
|
|
333
|
+
status_dict["git"] = {
|
|
334
|
+
"branch": None
|
|
335
|
+
if repo.head.is_detached
|
|
336
|
+
else repo.active_branch.name,
|
|
337
|
+
"is_dirty": repo.is_dirty(untracked_files=True),
|
|
338
|
+
"changed_files": changed_files,
|
|
339
|
+
"staged_files": staged_files,
|
|
340
|
+
"untracked_files": untracked_files,
|
|
341
|
+
}
|
|
342
|
+
except InvalidGitRepositoryError:
|
|
343
|
+
status_dict["git"] = {"error": "Not a Git repository"}
|
|
344
|
+
if "dvc" in categories:
|
|
345
|
+
try:
|
|
346
|
+
dvc_repo = calkit.dvc.get_dvc_repo()
|
|
347
|
+
data_status = dvc_repo.data_status()
|
|
348
|
+
if isinstance(data_status, dict):
|
|
349
|
+
data_status.pop("git", None)
|
|
350
|
+
status_dict["dvc"] = data_status
|
|
351
|
+
except Exception as e:
|
|
352
|
+
status_dict["dvc"] = {"error": f"{e.__class__.__name__}: {e}"}
|
|
353
|
+
if "pipeline" in categories or "dvc" in categories:
|
|
354
|
+
if pipeline_status is None:
|
|
355
|
+
status_dict["pipeline"] = None
|
|
356
|
+
else:
|
|
357
|
+
status_dict["pipeline"] = pipeline_status.model_dump(
|
|
358
|
+
mode="json"
|
|
359
|
+
)
|
|
360
|
+
print(json.dumps(status_dict, indent=2, default=str))
|
|
361
|
+
return
|
|
274
362
|
if "project" in categories:
|
|
275
363
|
print_sep("Project")
|
|
276
364
|
# Print latest status
|
|
@@ -307,10 +395,36 @@ def get_status(
|
|
|
307
395
|
typer.echo()
|
|
308
396
|
if "pipeline" in categories or "dvc" in categories:
|
|
309
397
|
print_sep("Pipeline")
|
|
310
|
-
|
|
311
|
-
if
|
|
312
|
-
|
|
313
|
-
|
|
398
|
+
# Nicely format the results from pipeline status
|
|
399
|
+
if pipeline_status and pipeline_status.errors:
|
|
400
|
+
warn("Pipeline status unavailable due to errors.")
|
|
401
|
+
return
|
|
402
|
+
if pipeline_status and not pipeline_status.has_pipeline:
|
|
403
|
+
typer.echo("This project has no pipeline.")
|
|
404
|
+
return
|
|
405
|
+
elif pipeline_status and pipeline_status.is_stale:
|
|
406
|
+
for stage_name in pipeline_status.stale_stage_names:
|
|
407
|
+
stale_stage = pipeline_status.stale_stages.get(stage_name)
|
|
408
|
+
if stale_stage is None:
|
|
409
|
+
continue
|
|
410
|
+
typer.echo(f"{typer.style(stage_name, fg='yellow')}:")
|
|
411
|
+
# Show stale outputs for this stage
|
|
412
|
+
if stale_stage.stale_outputs:
|
|
413
|
+
typer.echo(" stale outputs:")
|
|
414
|
+
for output_path in stale_stage.stale_outputs:
|
|
415
|
+
typer.echo(f" {output_path}")
|
|
416
|
+
# Show modified outputs from this stage
|
|
417
|
+
if stale_stage.modified_outputs:
|
|
418
|
+
typer.echo(" modified outputs:")
|
|
419
|
+
for output_path in stale_stage.modified_outputs:
|
|
420
|
+
typer.echo(f" {output_path}")
|
|
421
|
+
# Show modified inputs making the stage stale
|
|
422
|
+
if stale_stage.modified_inputs:
|
|
423
|
+
typer.echo(" modified inputs:")
|
|
424
|
+
for input_path in stale_stage.modified_inputs:
|
|
425
|
+
typer.echo(f" {input_path}")
|
|
426
|
+
elif pipeline_status:
|
|
427
|
+
typer.echo("Pipeline is up to date.")
|
|
314
428
|
|
|
315
429
|
|
|
316
430
|
@app.command(name="diff")
|
|
@@ -403,8 +517,7 @@ def add(
|
|
|
403
517
|
raise_error("Not currently in a Git repo; run `calkit init` first")
|
|
404
518
|
repo = git.Repo()
|
|
405
519
|
try:
|
|
406
|
-
|
|
407
|
-
dvc_repo = dvc.repo.Repo()
|
|
520
|
+
dvc_repo = get_dvc_repo()
|
|
408
521
|
except NotDvcRepoError:
|
|
409
522
|
warn("DVC not initialized yet; initializing")
|
|
410
523
|
dvc_repo = dvc.repo.Repo.init()
|
|
@@ -1139,10 +1252,8 @@ def run(
|
|
|
1139
1252
|
os.environ.pop("CALKIT_PIPELINE_RUNNING", None)
|
|
1140
1253
|
raise_error(f"Pipeline compilation failed: {e}")
|
|
1141
1254
|
# Initialize DVC repo if necessary
|
|
1142
|
-
# Register the ck:// scheme before accessing DVC repo
|
|
1143
|
-
register_ck_scheme()
|
|
1144
1255
|
try:
|
|
1145
|
-
|
|
1256
|
+
get_dvc_repo()
|
|
1146
1257
|
except Exception:
|
|
1147
1258
|
if not quiet:
|
|
1148
1259
|
typer.echo("Initializing DVC repo")
|
|
@@ -1203,8 +1314,7 @@ def run(
|
|
|
1203
1314
|
git_staged_files_before = calkit.git.get_staged_files(repo=repo)
|
|
1204
1315
|
git_untracked_files_before = calkit.git.get_untracked_files(repo=repo)
|
|
1205
1316
|
# Get status of DVC repo before running
|
|
1206
|
-
|
|
1207
|
-
dvc_repo = dvc.repo.Repo()
|
|
1317
|
+
dvc_repo = get_dvc_repo()
|
|
1208
1318
|
dvc_status_before = dvc_repo.status()
|
|
1209
1319
|
dvc_data_status_before = dvc_repo.data_status()
|
|
1210
1320
|
dvc_data_status_before.pop("git", None) # Remove git status
|
|
@@ -17,6 +17,7 @@ from git.exc import GitCommandError, InvalidGitRepositoryError, NoSuchPathError
|
|
|
17
17
|
from typing_extensions import Annotated
|
|
18
18
|
|
|
19
19
|
import calkit
|
|
20
|
+
import calkit.pipeline
|
|
20
21
|
from calkit.cli import raise_error, warn
|
|
21
22
|
from calkit.cli.check import check_environment
|
|
22
23
|
from calkit.cli.update import update_devcontainer
|
|
@@ -1332,6 +1333,75 @@ def new_uv_env(
|
|
|
1332
1333
|
repo.git.commit(["-m", f"Add uv environment {name}"])
|
|
1333
1334
|
|
|
1334
1335
|
|
|
1336
|
+
@new_app.command("slurm-env")
|
|
1337
|
+
def new_slurm_env(
|
|
1338
|
+
name: Annotated[
|
|
1339
|
+
str, typer.Option("--name", "-n", help="Environment name.")
|
|
1340
|
+
],
|
|
1341
|
+
host: Annotated[
|
|
1342
|
+
str,
|
|
1343
|
+
typer.Option("--host", help="Host where SLURM commands should run."),
|
|
1344
|
+
] = "localhost",
|
|
1345
|
+
default_options: Annotated[
|
|
1346
|
+
list[str],
|
|
1347
|
+
typer.Option(
|
|
1348
|
+
"--default-option",
|
|
1349
|
+
help=(
|
|
1350
|
+
"Default sbatch/srun option string (for example --gpus=1). "
|
|
1351
|
+
"Repeat for multiple options."
|
|
1352
|
+
),
|
|
1353
|
+
),
|
|
1354
|
+
] = [],
|
|
1355
|
+
description: Annotated[
|
|
1356
|
+
str | None, typer.Option("--description", help="Description.")
|
|
1357
|
+
] = None,
|
|
1358
|
+
overwrite: Annotated[
|
|
1359
|
+
bool,
|
|
1360
|
+
typer.Option(
|
|
1361
|
+
"--overwrite",
|
|
1362
|
+
"-f",
|
|
1363
|
+
help="Overwrite any existing environment with this name.",
|
|
1364
|
+
),
|
|
1365
|
+
] = False,
|
|
1366
|
+
no_commit: Annotated[
|
|
1367
|
+
bool, typer.Option("--no-commit", help="Do not commit changes.")
|
|
1368
|
+
] = False,
|
|
1369
|
+
):
|
|
1370
|
+
"""Create a new SLURM environment."""
|
|
1371
|
+
host = host.strip()
|
|
1372
|
+
if not host:
|
|
1373
|
+
raise_error("Host is required")
|
|
1374
|
+
ck_info = calkit.load_calkit_info()
|
|
1375
|
+
envs = ck_info.get("environments", {})
|
|
1376
|
+
if isinstance(envs, list):
|
|
1377
|
+
typer.echo("Converting environments from list to dict")
|
|
1378
|
+
envs = {env.pop("name"): env for env in envs}
|
|
1379
|
+
if name in envs and not overwrite:
|
|
1380
|
+
raise_error(
|
|
1381
|
+
f"Environment with name {name} already exists "
|
|
1382
|
+
"(use -f to overwrite)"
|
|
1383
|
+
)
|
|
1384
|
+
normalized_default_options = [
|
|
1385
|
+
opt.strip() for opt in default_options if opt.strip()
|
|
1386
|
+
]
|
|
1387
|
+
env = {"kind": "slurm", "host": host}
|
|
1388
|
+
if normalized_default_options:
|
|
1389
|
+
env["default_options"] = normalized_default_options # type: ignore
|
|
1390
|
+
if description is not None:
|
|
1391
|
+
env["description"] = description
|
|
1392
|
+
envs[name] = env
|
|
1393
|
+
ck_info["environments"] = envs
|
|
1394
|
+
with open("calkit.yaml", "w") as f:
|
|
1395
|
+
ryaml.dump(ck_info, f)
|
|
1396
|
+
if not no_commit:
|
|
1397
|
+
repo = git.Repo()
|
|
1398
|
+
repo.git.add("calkit.yaml")
|
|
1399
|
+
if repo.git.diff(["--staged", "calkit.yaml"]):
|
|
1400
|
+
repo.git.commit(
|
|
1401
|
+
["calkit.yaml", "-m", f"Add SLURM environment {name}"]
|
|
1402
|
+
)
|
|
1403
|
+
|
|
1404
|
+
|
|
1335
1405
|
@new_app.command("uv-venv")
|
|
1336
1406
|
def new_uv_venv(
|
|
1337
1407
|
name: Annotated[
|
|
@@ -1614,21 +1684,29 @@ def new_pixi_env(
|
|
|
1614
1684
|
@new_app.command("julia-env")
|
|
1615
1685
|
def new_julia_env(
|
|
1616
1686
|
packages: Annotated[
|
|
1617
|
-
list[str],
|
|
1618
|
-
typer.Argument(
|
|
1619
|
-
|
|
1687
|
+
list[str] | None,
|
|
1688
|
+
typer.Argument(
|
|
1689
|
+
help="Optional packages to include in the environment."
|
|
1690
|
+
),
|
|
1691
|
+
] = None,
|
|
1620
1692
|
name: Annotated[
|
|
1621
1693
|
str, typer.Option("--name", "-n", help="Environment name.")
|
|
1622
|
-
],
|
|
1694
|
+
] = "main",
|
|
1623
1695
|
path: Annotated[
|
|
1624
|
-
str
|
|
1625
|
-
|
|
1696
|
+
str | None,
|
|
1697
|
+
typer.Option("--path", help="Path for Project.toml file."),
|
|
1698
|
+
] = None,
|
|
1626
1699
|
description: Annotated[
|
|
1627
1700
|
str | None, typer.Option("--description", help="Description.")
|
|
1628
1701
|
] = None,
|
|
1629
1702
|
julia_version: Annotated[
|
|
1630
|
-
str
|
|
1631
|
-
|
|
1703
|
+
str | None,
|
|
1704
|
+
typer.Option(
|
|
1705
|
+
"--julia",
|
|
1706
|
+
"-j",
|
|
1707
|
+
help="Julia version. Auto-detected if not supplied.",
|
|
1708
|
+
),
|
|
1709
|
+
] = None,
|
|
1632
1710
|
overwrite: Annotated[
|
|
1633
1711
|
bool,
|
|
1634
1712
|
typer.Option(
|
|
@@ -1640,8 +1718,17 @@ def new_julia_env(
|
|
|
1640
1718
|
no_commit: Annotated[
|
|
1641
1719
|
bool, typer.Option("--no-commit", help="Do not commit changes.")
|
|
1642
1720
|
] = False,
|
|
1721
|
+
no_check: Annotated[
|
|
1722
|
+
bool,
|
|
1723
|
+
typer.Option(
|
|
1724
|
+
"--no-check",
|
|
1725
|
+
help="Do not check environment is up-to-date after creation.",
|
|
1726
|
+
),
|
|
1727
|
+
] = False,
|
|
1643
1728
|
):
|
|
1644
|
-
"""Create a new Julia environment."""
|
|
1729
|
+
"""Create a new Julia environment or add an existing one to calkit.yaml."""
|
|
1730
|
+
if path is None:
|
|
1731
|
+
path = "Project.toml"
|
|
1645
1732
|
if not os.path.basename(path) == "Project.toml":
|
|
1646
1733
|
raise_error(
|
|
1647
1734
|
"Julia environment paths must point to a Project.toml file"
|
|
@@ -1664,27 +1751,57 @@ def new_julia_env(
|
|
|
1664
1751
|
f"Environment with name {name} already exists "
|
|
1665
1752
|
"(use -f to overwrite)"
|
|
1666
1753
|
)
|
|
1667
|
-
#
|
|
1754
|
+
# Detect Julia version if not supplied
|
|
1755
|
+
if julia_version is None:
|
|
1756
|
+
try:
|
|
1757
|
+
julia_version = calkit.julia.get_version()
|
|
1758
|
+
except ValueError as e:
|
|
1759
|
+
raise_error(
|
|
1760
|
+
f"Failed to detect Julia version: {e}. "
|
|
1761
|
+
"Use --julia to specify a version."
|
|
1762
|
+
)
|
|
1763
|
+
# Check for duplicate Julia environments with same path and version
|
|
1764
|
+
for env_name, env_config in envs.items():
|
|
1765
|
+
if (
|
|
1766
|
+
env_config.get("kind") == "julia"
|
|
1767
|
+
and env_config.get("path") == path
|
|
1768
|
+
and env_config.get("julia") == julia_version
|
|
1769
|
+
):
|
|
1770
|
+
raise_error(
|
|
1771
|
+
f"Julia environment '{env_name}' already exists with path "
|
|
1772
|
+
f"'{path}' and version '{julia_version}'; "
|
|
1773
|
+
f"Use a different path, version, or --overwrite to replace it"
|
|
1774
|
+
)
|
|
1668
1775
|
env_dir = os.path.dirname(path)
|
|
1669
1776
|
if env_dir:
|
|
1670
1777
|
os.makedirs(env_dir, exist_ok=True)
|
|
1671
1778
|
else:
|
|
1672
1779
|
env_dir = "."
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1780
|
+
project_exists = os.path.isfile(path)
|
|
1781
|
+
created_project_file = False
|
|
1782
|
+
# If packages are provided, initialize via Julia/Pkg.
|
|
1783
|
+
if packages:
|
|
1784
|
+
# First make sure the Julia version is installed
|
|
1785
|
+
cmd = ["juliaup", "add", julia_version]
|
|
1786
|
+
try:
|
|
1787
|
+
subprocess.run(cmd, check=True)
|
|
1788
|
+
except subprocess.CalledProcessError:
|
|
1789
|
+
raise_error(f"Failed to install Julia version {julia_version}")
|
|
1790
|
+
cmd = ["julia", f"+{julia_version}", f"--project={env_dir}", "-e"]
|
|
1791
|
+
install_cmd = f'using Pkg; Pkg.activate("{env_dir}");'
|
|
1792
|
+
for package in packages or []:
|
|
1793
|
+
install_cmd += f' Pkg.add("{package}");'
|
|
1794
|
+
cmd.append(install_cmd)
|
|
1795
|
+
try:
|
|
1796
|
+
subprocess.run(cmd, check=True)
|
|
1797
|
+
except subprocess.CalledProcessError:
|
|
1798
|
+
raise_error("Failed to create new Julia environment")
|
|
1799
|
+
elif not project_exists:
|
|
1800
|
+
# Allow creating a Julia environment scaffold without requiring Julia
|
|
1801
|
+
# tooling at creation time. IJulia or other packages can be added later.
|
|
1802
|
+
with open(path, "w") as f:
|
|
1803
|
+
f.write("[deps]\n")
|
|
1804
|
+
created_project_file = True
|
|
1688
1805
|
typer.echo("Adding environment to calkit.yaml")
|
|
1689
1806
|
env = dict(kind="julia", path=path, julia=julia_version)
|
|
1690
1807
|
if description is not None:
|
|
@@ -1693,11 +1810,18 @@ def new_julia_env(
|
|
|
1693
1810
|
ck_info["environments"] = envs
|
|
1694
1811
|
with open("calkit.yaml", "w") as f:
|
|
1695
1812
|
ryaml.dump(ck_info, f)
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1813
|
+
if not no_commit:
|
|
1814
|
+
repo.git.add("calkit.yaml")
|
|
1815
|
+
if packages or created_project_file:
|
|
1816
|
+
repo.git.add(path)
|
|
1817
|
+
if packages:
|
|
1818
|
+
repo.git.add(os.path.join(env_dir, "Manifest.toml"))
|
|
1819
|
+
if not no_check and packages:
|
|
1820
|
+
env_lock_fpath = check_environment(env_name=name)
|
|
1821
|
+
if env_lock_fpath is not None:
|
|
1822
|
+
repo.git.add(env_lock_fpath)
|
|
1823
|
+
if repo.git.diff("--staged"):
|
|
1824
|
+
repo.git.commit(["-m", f"Add Julia env {name}"])
|
|
1701
1825
|
|
|
1702
1826
|
|
|
1703
1827
|
@new_app.command("renv")
|
|
@@ -2523,6 +2647,26 @@ def new_release(
|
|
|
2523
2647
|
repo = git.Repo()
|
|
2524
2648
|
if name in repo.tags:
|
|
2525
2649
|
raise_error(f"Git tag with name '{name}' already exists")
|
|
2650
|
+
# Check that the pipeline is up-to-date
|
|
2651
|
+
typer.echo("Checking pipeline is up-to-date for release")
|
|
2652
|
+
status = calkit.pipeline.get_status(
|
|
2653
|
+
ck_info=ck_info,
|
|
2654
|
+
check_environments=True,
|
|
2655
|
+
clean_notebooks=True,
|
|
2656
|
+
compile_to_dvc=True,
|
|
2657
|
+
)
|
|
2658
|
+
if status.errors:
|
|
2659
|
+
raise_error("Pipeline checks failed: " + "; ".join(status.errors))
|
|
2660
|
+
if status.failed_environment_checks:
|
|
2661
|
+
raise_error(
|
|
2662
|
+
"Pipeline environment checks failed for: "
|
|
2663
|
+
+ ", ".join(status.failed_environment_checks)
|
|
2664
|
+
)
|
|
2665
|
+
if status.is_stale:
|
|
2666
|
+
raise_error(
|
|
2667
|
+
"Pipeline is not up-to-date; out-of-date stages: "
|
|
2668
|
+
+ ", ".join(status.stale_stage_names)
|
|
2669
|
+
)
|
|
2526
2670
|
release_dir = f".calkit/releases/{name}"
|
|
2527
2671
|
release_files_dir = release_dir + "/files"
|
|
2528
2672
|
os.makedirs(release_files_dir, exist_ok=True)
|
|
@@ -2543,8 +2687,14 @@ def new_release(
|
|
|
2543
2687
|
all_paths = calkit.releases.ls_files()
|
|
2544
2688
|
typer.echo(f"Adding files to {zip_path}")
|
|
2545
2689
|
with zipfile.ZipFile(zip_path, "w") as zipf:
|
|
2546
|
-
|
|
2547
|
-
|
|
2690
|
+
calkit.releases.add_paths_to_zip(zipf, all_paths)
|
|
2691
|
+
typer.echo("Checking extracted project release archive")
|
|
2692
|
+
try:
|
|
2693
|
+
calkit.releases.check_project_release_archive(
|
|
2694
|
+
zip_path, verbose=verbose
|
|
2695
|
+
)
|
|
2696
|
+
except Exception as e:
|
|
2697
|
+
raise_error(str(e))
|
|
2548
2698
|
title = ck_info.get("title")
|
|
2549
2699
|
if title is None:
|
|
2550
2700
|
warn("Project has no title")
|
|
@@ -2888,10 +3038,12 @@ def new_release(
|
|
|
2888
3038
|
+ new_lines[first_content_line_index:]
|
|
2889
3039
|
)
|
|
2890
3040
|
readme_txt = "\n".join(new_lines)
|
|
2891
|
-
with open("README.md", "w") as f:
|
|
2892
|
-
f.write(readme_txt)
|
|
2893
3041
|
if not dry_run:
|
|
2894
|
-
|
|
3042
|
+
with open("README.md", "w") as f:
|
|
3043
|
+
f.write(readme_txt)
|
|
3044
|
+
repo.git.add("README.md")
|
|
3045
|
+
else:
|
|
3046
|
+
typer.echo(f"Would have updated README.md to:\n{readme_txt}")
|
|
2895
3047
|
# Create Git tag
|
|
2896
3048
|
git_tag_message = release_description
|
|
2897
3049
|
if git_tag_message is None:
|
|
@@ -2919,13 +3071,15 @@ def new_release(
|
|
|
2919
3071
|
ck_info["releases"] = releases
|
|
2920
3072
|
# Create CITATION.cff file
|
|
2921
3073
|
if release_type == "project":
|
|
2922
|
-
typer.echo("Writing CITATION.cff")
|
|
2923
3074
|
cff = calkit.releases.create_citation_cff(
|
|
2924
3075
|
ck_info=ck_info, release_name=name, release_date=release_date
|
|
2925
3076
|
)
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
3077
|
+
if dry_run:
|
|
3078
|
+
typer.echo(f"Would write CITATION.cff:\n{cff}")
|
|
3079
|
+
else:
|
|
3080
|
+
typer.echo("Writing CITATION.cff")
|
|
3081
|
+
with open("CITATION.cff", "w") as f:
|
|
3082
|
+
calkit.ryaml.dump(cff, f)
|
|
2929
3083
|
repo.git.add("CITATION.cff")
|
|
2930
3084
|
# Add to references so it can be cited
|
|
2931
3085
|
typer.echo("Adding BibTeX entry to references")
|
|
@@ -2944,28 +3098,50 @@ def new_release(
|
|
|
2944
3098
|
reflib = bibtexparser.load(f)
|
|
2945
3099
|
else:
|
|
2946
3100
|
reflib = bibtexparser.bibdatabase.BibDatabase()
|
|
3101
|
+
bibtex_doi = doi
|
|
3102
|
+
if bibtex_doi is None and dry_run:
|
|
3103
|
+
mock_suffix = "".join(
|
|
3104
|
+
ch if (ch.isalnum() or ch in ".-_") else "-"
|
|
3105
|
+
for ch in name.lower()
|
|
3106
|
+
)
|
|
3107
|
+
bibtex_doi = f"10.0000/calkit-dry-run.{mock_suffix}"
|
|
2947
3108
|
invenio_bibtex = calkit.releases.create_bibtex(
|
|
2948
3109
|
authors=authors,
|
|
2949
3110
|
release_date=release_date,
|
|
2950
3111
|
title=title, # type: ignore
|
|
2951
|
-
doi=
|
|
3112
|
+
doi=bibtex_doi,
|
|
2952
3113
|
record_id=record_id, # type: ignore
|
|
2953
3114
|
service=to, # type: ignore
|
|
2954
3115
|
)
|
|
2955
|
-
|
|
3116
|
+
new_entries = bibtexparser.loads(invenio_bibtex).entries
|
|
3117
|
+
if not new_entries:
|
|
3118
|
+
raise ValueError("Failed to parse generated BibTeX entry")
|
|
3119
|
+
new_entry = new_entries[0]
|
|
2956
3120
|
# Search through entries for one with the same DOI, and replace if
|
|
2957
3121
|
# there is a match
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
3122
|
+
new_doi = new_entry.get("doi")
|
|
3123
|
+
matching_indices = []
|
|
3124
|
+
if new_doi:
|
|
3125
|
+
matching_indices = [
|
|
3126
|
+
n
|
|
3127
|
+
for n, entry in enumerate(reflib.entries)
|
|
3128
|
+
if entry.get("doi") == new_doi
|
|
3129
|
+
]
|
|
3130
|
+
if matching_indices:
|
|
3131
|
+
typer.echo(
|
|
3132
|
+
"Found matching DOI in existing references "
|
|
3133
|
+
f"({len(matching_indices)} entr"
|
|
3134
|
+
f"{'y' if len(matching_indices) == 1 else 'ies'}); "
|
|
3135
|
+
"replacing"
|
|
3136
|
+
)
|
|
3137
|
+
for n in reversed(matching_indices):
|
|
3138
|
+
_ = reflib.entries.pop(n)
|
|
2965
3139
|
reflib.entries.append(new_entry)
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
3140
|
+
if dry_run:
|
|
3141
|
+
typer.echo(f"Would write updated references to {ref_path}")
|
|
3142
|
+
else:
|
|
3143
|
+
with open(ref_path, "w") as f:
|
|
3144
|
+
bibtexparser.dump(reflib, f)
|
|
2969
3145
|
repo.git.add(ref_path)
|
|
2970
3146
|
except Exception as e:
|
|
2971
3147
|
warn(f"Failed to add to references: {e}")
|