calkit-python 0.30.8__tar.gz → 0.30.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.github/workflows/test.yml +2 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/PKG-INFO +1 -1
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/__init__.py +2 -1
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/main.py +7 -1
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/overleaf.py +151 -74
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/update.py +31 -3
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/core.py +20 -0
- calkit_python-0.30.10/calkit/overleaf.py +15 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/cli/test_main.py +25 -0
- calkit_python-0.30.10/calkit/tests/cli/test_overleaf.py +90 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/dependencies.md +11 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/overleaf.md +35 -2
- {calkit_python-0.30.8 → calkit_python-0.30.10}/pyproject.toml +1 -1
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.github/FUNDING.yml +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.github/workflows/docs.yml +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.github/workflows/format.yml +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.github/workflows/publish-test.yml +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.github/workflows/publish.yml +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.gitignore +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.pre-commit-config.yaml +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/.python-version +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/CITATION.cff +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/CONTRIBUTING.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/LICENSE +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/Makefile +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/README.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/__main__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/calc.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/check.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/check.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/cloud.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/config.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/core.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/describe.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/import_.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/list.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/new.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/notebooks.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/office.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cli/slurm.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/cloud.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/conda.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/config.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/datasets.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/docker.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/dvc.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/environments.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/git.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/github.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/gui.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/invenio.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/jupyter.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/licenses.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/magics.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/matlab.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/models/__init__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/models/core.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/models/io.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/models/iteration.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/models/pipeline.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/notebooks.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/office.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/ops.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/pipeline.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/releases.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/server.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/core.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/cli/test_check.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/cli/test_config.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/cli/test_new.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/cli/test_notebooks.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/models/__init__.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/models/test_iteration.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/models/test_pipeline.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_conda.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_dvc.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_invenio.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_notebooks.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_pipeline.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/CNAME +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/apps.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/calculations.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/cli-reference.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/cloud-integration.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/datasets.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/environments.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/examples.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/help.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/img/connect-zenodo.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/img/jupyterlab-params.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/img/vscode-nb-params.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/index.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/installation.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/local-server.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/notebooks.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/pipeline/index.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/pipeline/running-and-logging.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/pipeline/slurm.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/quickstart.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/references.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/releases.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/existing-project.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/github-actions.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/actions-repo-secrets.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/quick-actions.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/index.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/office.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/docs/version-control.md +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/mkdocs.yml +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/scripts/install.ps1 +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/scripts/install.sh +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/test/nb-julia.ipynb +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/test/nb-params.ipynb +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/test/nb-subdir.ipynb +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/test/pipeline.ipynb +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/test/test-log.log +0 -0
- {calkit_python-0.30.8 → calkit_python-0.30.10}/uv.lock +0 -0
|
@@ -15,6 +15,8 @@ jobs:
|
|
|
15
15
|
git config --global user.name github-actions[bot]
|
|
16
16
|
git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com
|
|
17
17
|
git config --global init.defaultBranch main
|
|
18
|
+
- name: Configure Git push behavior
|
|
19
|
+
run: git config --global push.autoSetupRemote true
|
|
18
20
|
- name: Setup uv
|
|
19
21
|
uses: astral-sh/setup-uv@v5
|
|
20
22
|
- name: Setup Miniforge
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
__version__ = "0.30.
|
|
1
|
+
__version__ = "0.30.10"
|
|
2
2
|
|
|
3
3
|
from .core import * # noqa: F403, I001
|
|
4
4
|
from . import git # noqa: F401
|
|
@@ -16,4 +16,5 @@ from . import github # noqa: F401
|
|
|
16
16
|
from . import invenio # noqa: F401
|
|
17
17
|
from . import releases # noqa: F401
|
|
18
18
|
from . import licenses # noqa: F401
|
|
19
|
+
from . import overleaf # noqa: F401
|
|
19
20
|
from .notebooks import declare_notebook # noqa: F401
|
|
@@ -990,6 +990,9 @@ def run(
|
|
|
990
990
|
"""Check dependencies and run the pipeline."""
|
|
991
991
|
os.environ["CALKIT_PIPELINE_RUNNING"] = "1"
|
|
992
992
|
dotenv.load_dotenv(dotenv_path=".env", verbose=verbose)
|
|
993
|
+
ck_info = calkit.load_calkit_info()
|
|
994
|
+
# Set env vars
|
|
995
|
+
calkit.set_env_vars(ck_info=ck_info)
|
|
993
996
|
if not quiet:
|
|
994
997
|
typer.echo("Getting system information")
|
|
995
998
|
system_info = calkit.get_system_info()
|
|
@@ -1013,7 +1016,6 @@ def run(
|
|
|
1013
1016
|
os.environ.pop("CALKIT_PIPELINE_RUNNING", None)
|
|
1014
1017
|
raise_error(str(e))
|
|
1015
1018
|
# Compile the pipeline
|
|
1016
|
-
ck_info = calkit.load_calkit_info()
|
|
1017
1019
|
if ck_info.get("pipeline", {}):
|
|
1018
1020
|
if not quiet:
|
|
1019
1021
|
typer.echo("Compiling DVC pipeline")
|
|
@@ -1251,6 +1253,7 @@ def run_in_env(
|
|
|
1251
1253
|
):
|
|
1252
1254
|
dotenv.load_dotenv(dotenv_path=".env", verbose=verbose)
|
|
1253
1255
|
ck_info = calkit.load_calkit_info(process_includes="environments")
|
|
1256
|
+
calkit.set_env_vars(ck_info=ck_info)
|
|
1254
1257
|
envs = ck_info.get("environments", {})
|
|
1255
1258
|
if not envs:
|
|
1256
1259
|
raise_error("No environments defined in calkit.yaml")
|
|
@@ -1314,6 +1317,8 @@ def run_in_env(
|
|
|
1314
1317
|
if "env-vars" in env:
|
|
1315
1318
|
warn("The 'env-vars' key is deprecated; use 'env_vars' instead.")
|
|
1316
1319
|
env_vars.update(env["env-vars"])
|
|
1320
|
+
# Add project-level env vars (non-secret)
|
|
1321
|
+
env_vars.update(ck_info.get("env_vars", {}))
|
|
1317
1322
|
# Also add any project-level environmental variable dependencies
|
|
1318
1323
|
project_env_vars = calkit.get_env_var_dep_names()
|
|
1319
1324
|
if project_env_vars:
|
|
@@ -1668,6 +1673,7 @@ def run_procedure(
|
|
|
1668
1673
|
return value
|
|
1669
1674
|
|
|
1670
1675
|
ck_info = calkit.load_calkit_info(process_includes="procedures")
|
|
1676
|
+
calkit.set_env_vars(ck_info=ck_info)
|
|
1671
1677
|
procs = ck_info.get("procedures", {})
|
|
1672
1678
|
if name not in procs:
|
|
1673
1679
|
raise_error(f"'{name}' is not defined as a procedure")
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import filecmp
|
|
6
|
+
import json
|
|
6
7
|
import os
|
|
7
8
|
import shutil
|
|
8
9
|
import subprocess
|
|
@@ -36,17 +37,6 @@ def import_publication(
|
|
|
36
37
|
help="Directory at which to save in the project, e.g., 'paper'."
|
|
37
38
|
),
|
|
38
39
|
],
|
|
39
|
-
sync_paths: Annotated[
|
|
40
|
-
list[str],
|
|
41
|
-
typer.Option(
|
|
42
|
-
"--sync-path",
|
|
43
|
-
"-s",
|
|
44
|
-
help=(
|
|
45
|
-
"Paths to sync from the Overleaf project, e.g., 'main.tex'. "
|
|
46
|
-
"Note that multiple can be specified."
|
|
47
|
-
),
|
|
48
|
-
),
|
|
49
|
-
],
|
|
50
40
|
title: Annotated[
|
|
51
41
|
str,
|
|
52
42
|
typer.Option(
|
|
@@ -55,6 +45,14 @@ def import_publication(
|
|
|
55
45
|
help="Title of the publication.",
|
|
56
46
|
),
|
|
57
47
|
],
|
|
48
|
+
target_path: Annotated[
|
|
49
|
+
str | None,
|
|
50
|
+
typer.Option(
|
|
51
|
+
"--target",
|
|
52
|
+
"-T",
|
|
53
|
+
help="Target TeX file path inside Overleaf project.",
|
|
54
|
+
),
|
|
55
|
+
] = None,
|
|
58
56
|
description: Annotated[
|
|
59
57
|
str | None,
|
|
60
58
|
typer.Option(
|
|
@@ -70,6 +68,17 @@ def import_publication(
|
|
|
70
68
|
help="What of the publication this is, e.g., 'journal-article'.",
|
|
71
69
|
),
|
|
72
70
|
] = None,
|
|
71
|
+
sync_paths: Annotated[
|
|
72
|
+
list[str],
|
|
73
|
+
typer.Option(
|
|
74
|
+
"--sync-path",
|
|
75
|
+
"-s",
|
|
76
|
+
help=(
|
|
77
|
+
"Paths to sync from the Overleaf project, e.g., 'main.tex'. "
|
|
78
|
+
"Note that multiple can be specified."
|
|
79
|
+
),
|
|
80
|
+
),
|
|
81
|
+
] = [],
|
|
73
82
|
push_paths: Annotated[
|
|
74
83
|
list[str],
|
|
75
84
|
typer.Option(
|
|
@@ -82,18 +91,6 @@ def import_publication(
|
|
|
82
91
|
),
|
|
83
92
|
),
|
|
84
93
|
] = [],
|
|
85
|
-
pdf_path: Annotated[
|
|
86
|
-
str | None,
|
|
87
|
-
typer.Option(
|
|
88
|
-
"--pdf-path",
|
|
89
|
-
"-o",
|
|
90
|
-
help=(
|
|
91
|
-
"PDF output file in the Overleaf project, e.g., 'main.pdf'. "
|
|
92
|
-
"If not provided, it will be determined from the first sync "
|
|
93
|
-
"path."
|
|
94
|
-
),
|
|
95
|
-
),
|
|
96
|
-
] = None,
|
|
97
94
|
no_commit: Annotated[
|
|
98
95
|
bool,
|
|
99
96
|
typer.Option("--no-commit", help="Do not commit changes to repo."),
|
|
@@ -127,13 +124,19 @@ def import_publication(
|
|
|
127
124
|
typer.echo("Storing Overleaf token in Calkit config")
|
|
128
125
|
config.overleaf_token = overleaf_token
|
|
129
126
|
config.write()
|
|
130
|
-
if
|
|
127
|
+
if (
|
|
128
|
+
not src_url.startswith("https://www.overleaf.com/project/")
|
|
129
|
+
and calkit.config.get_env() != "test"
|
|
130
|
+
):
|
|
131
131
|
raise_error(
|
|
132
132
|
"Invalid URL; must start with 'https://www.overleaf.com/project/'"
|
|
133
133
|
)
|
|
134
134
|
overleaf_project_id = src_url.split("/")[-1]
|
|
135
135
|
if not overleaf_project_id:
|
|
136
136
|
raise_error("Invalid Overleaf project ID")
|
|
137
|
+
# Check target path
|
|
138
|
+
if target_path is not None and not target_path.endswith(".tex"):
|
|
139
|
+
raise_error("Target path should have a .tex extension")
|
|
137
140
|
# Make sure destination directory exists, and isn't a file
|
|
138
141
|
if os.path.isfile(dest_dir):
|
|
139
142
|
raise_error("Destination must be a directory, not a file")
|
|
@@ -141,21 +144,6 @@ def import_publication(
|
|
|
141
144
|
ck_info = calkit.load_calkit_info(process_includes="environments")
|
|
142
145
|
pubs = ck_info.get("publications", [])
|
|
143
146
|
# TODO: Don't allow the same Overleaf project ID in multiple publications
|
|
144
|
-
# Determine the PDF output path
|
|
145
|
-
if pdf_path is None:
|
|
146
|
-
# Use the first sync path as the PDF path
|
|
147
|
-
pdf_path = sync_paths[0].removesuffix(".tex") + ".pdf"
|
|
148
|
-
typer.echo(f"Using PDF path: {pdf_path}")
|
|
149
|
-
tex_path = pdf_path.removesuffix(".pdf") + ".tex"
|
|
150
|
-
pub_path = PurePosixPath(dest_dir, pdf_path).as_posix()
|
|
151
|
-
pub_paths = [pub.get("path") for pub in pubs]
|
|
152
|
-
if not overwrite and pub_path in pub_paths:
|
|
153
|
-
raise_error(
|
|
154
|
-
f"A publication already exists in this project at {pub_path}"
|
|
155
|
-
)
|
|
156
|
-
elif overwrite and pub_path in pub_paths:
|
|
157
|
-
# Note: This publication will go to the end of the list
|
|
158
|
-
pubs = [p for p in pubs if p.get("path") != pub_path]
|
|
159
147
|
repo = git.Repo()
|
|
160
148
|
# Clone the Overleaf project into .calkit/overleaf if it doesn't exist
|
|
161
149
|
# otherwise pull
|
|
@@ -163,8 +151,8 @@ def import_publication(
|
|
|
163
151
|
os.makedirs(overleaf_dir, exist_ok=True)
|
|
164
152
|
git_ignore(overleaf_dir, no_commit=no_commit)
|
|
165
153
|
overleaf_project_dir = os.path.join(overleaf_dir, overleaf_project_id)
|
|
166
|
-
git_clone_url = (
|
|
167
|
-
|
|
154
|
+
git_clone_url = calkit.overleaf.get_git_remote_url(
|
|
155
|
+
project_id=overleaf_project_id, token=overleaf_token
|
|
168
156
|
)
|
|
169
157
|
if os.path.isdir(overleaf_project_dir):
|
|
170
158
|
warn("This Overleaf project has already been cloned; removing")
|
|
@@ -176,6 +164,36 @@ def import_publication(
|
|
|
176
164
|
overleaf_project_dir,
|
|
177
165
|
depth=1,
|
|
178
166
|
)
|
|
167
|
+
# Detect target path if not specified
|
|
168
|
+
if target_path is None:
|
|
169
|
+
ol_contents = os.listdir(overleaf_project_dir)
|
|
170
|
+
for cand in ["main.tex", "report.tex", "paper.tex"]:
|
|
171
|
+
if cand in ol_contents:
|
|
172
|
+
target_path = cand
|
|
173
|
+
break
|
|
174
|
+
if target_path is None:
|
|
175
|
+
# Fall back to lone .tex file if there is one
|
|
176
|
+
tex_files = [p for p in ol_contents if p.endswith(".tex")]
|
|
177
|
+
if len(tex_files) == 1:
|
|
178
|
+
target_path = tex_files[0]
|
|
179
|
+
if target_path is None:
|
|
180
|
+
raise_error(
|
|
181
|
+
"Target TeX file path cannot be detected; "
|
|
182
|
+
"please specify with --target"
|
|
183
|
+
)
|
|
184
|
+
# Determine the PDF output path
|
|
185
|
+
pdf_path = target_path.removesuffix(".tex") + ".pdf" # type: ignore
|
|
186
|
+
typer.echo(f"Using PDF path: {pdf_path}")
|
|
187
|
+
tex_path = pdf_path.removesuffix(".pdf") + ".tex"
|
|
188
|
+
pub_path = PurePosixPath(dest_dir, pdf_path).as_posix()
|
|
189
|
+
pub_paths = [pub.get("path") for pub in pubs]
|
|
190
|
+
if not overwrite and pub_path in pub_paths:
|
|
191
|
+
raise_error(
|
|
192
|
+
f"A publication already exists in this project at {pub_path}"
|
|
193
|
+
)
|
|
194
|
+
elif overwrite and pub_path in pub_paths:
|
|
195
|
+
# Note: This publication will go to the end of the list
|
|
196
|
+
pubs = [p for p in pubs if p.get("path") != pub_path]
|
|
179
197
|
# Check that we have a LaTeX environment
|
|
180
198
|
typer.echo("Checking that this project has a LaTeX environment")
|
|
181
199
|
envs = ck_info.get("environments", {})
|
|
@@ -197,6 +215,8 @@ def import_publication(
|
|
|
197
215
|
description="TeXlive via Docker.",
|
|
198
216
|
)
|
|
199
217
|
ck_info["environments"] = envs
|
|
218
|
+
with open("calkit.yaml", "w") as f:
|
|
219
|
+
calkit.ryaml.dump(ck_info, f)
|
|
200
220
|
# Check that we have a build stage
|
|
201
221
|
# TODO: Use Calkit pipeline for this
|
|
202
222
|
typer.echo("Checking for a build stage in the pipeline")
|
|
@@ -224,7 +244,6 @@ def import_publication(
|
|
|
224
244
|
name=stage_name,
|
|
225
245
|
environment=tex_env_name,
|
|
226
246
|
target_path=PurePosixPath(dest_dir, tex_path).as_posix(),
|
|
227
|
-
outputs=[pub_path],
|
|
228
247
|
inputs=[
|
|
229
248
|
os.path.join(dest_dir, p) for p in sync_paths + push_paths
|
|
230
249
|
],
|
|
@@ -234,6 +253,7 @@ def import_publication(
|
|
|
234
253
|
repo.git.add("calkit.yaml")
|
|
235
254
|
# Add to publications in calkit.yaml
|
|
236
255
|
typer.echo("Adding publication to calkit.yaml")
|
|
256
|
+
ck_info = calkit.load_calkit_info()
|
|
237
257
|
new_pub = dict(
|
|
238
258
|
path=pub_path,
|
|
239
259
|
title=title,
|
|
@@ -305,12 +325,12 @@ def sync(
|
|
|
305
325
|
help="Enable verbose output.",
|
|
306
326
|
),
|
|
307
327
|
] = False,
|
|
308
|
-
|
|
328
|
+
resolve: Annotated[
|
|
309
329
|
bool,
|
|
310
330
|
typer.Option(
|
|
311
|
-
"--
|
|
312
|
-
"-
|
|
313
|
-
help="
|
|
331
|
+
"--resolve",
|
|
332
|
+
"-r",
|
|
333
|
+
help="Mark merge conflicts as resolved before committing.",
|
|
314
334
|
),
|
|
315
335
|
] = False,
|
|
316
336
|
):
|
|
@@ -327,11 +347,33 @@ def sync(
|
|
|
327
347
|
calkit_config = calkit.config.read()
|
|
328
348
|
overleaf_token = calkit_config.overleaf_token
|
|
329
349
|
if not overleaf_token:
|
|
350
|
+
# See if we can get it from the cloud
|
|
351
|
+
if calkit_config.token is not None:
|
|
352
|
+
try:
|
|
353
|
+
resp = calkit.cloud.get("/user/overleaf-token")
|
|
354
|
+
overleaf_token = resp["access_token"]
|
|
355
|
+
calkit_config.overleaf_token = overleaf_token
|
|
356
|
+
calkit_config.write()
|
|
357
|
+
except Exception:
|
|
358
|
+
raise_error(
|
|
359
|
+
"Overleaf token not set; "
|
|
360
|
+
"Please set it using 'calkit config set overleaf_token'"
|
|
361
|
+
)
|
|
362
|
+
repo = git.Repo()
|
|
363
|
+
conflict_fpath = os.path.join(".calkit", "overleaf", "CONFLICT.json")
|
|
364
|
+
in_am_session = "in the middle of an am session" in repo.git.status()
|
|
365
|
+
# Check if we're in the middle of resolving a merge conflict
|
|
366
|
+
if in_am_session and not resolve:
|
|
330
367
|
raise_error(
|
|
331
|
-
"
|
|
332
|
-
"
|
|
368
|
+
"You are in the middle of resolving a merge conflict; "
|
|
369
|
+
"use 'calkit overleaf sync --resolve' after editing file(s)"
|
|
333
370
|
)
|
|
334
|
-
|
|
371
|
+
elif resolve:
|
|
372
|
+
if not os.path.isfile(conflict_fpath):
|
|
373
|
+
raise_error("No merge conflict to resolve")
|
|
374
|
+
# Figure out which wdir has the conflict in it
|
|
375
|
+
with open(conflict_fpath) as f:
|
|
376
|
+
resolving_info = json.load(f)
|
|
335
377
|
for pub in pubs:
|
|
336
378
|
overleaf_config = pub.get("overleaf", {})
|
|
337
379
|
if not overleaf_config:
|
|
@@ -354,6 +396,16 @@ def sync(
|
|
|
354
396
|
"No working directory defined for this publication; "
|
|
355
397
|
"please set it in the publication's Overleaf config"
|
|
356
398
|
)
|
|
399
|
+
if resolve and wdir == resolving_info["wdir"]:
|
|
400
|
+
repo.git.add(wdir)
|
|
401
|
+
if repo.git.diff(["--staged", wdir]):
|
|
402
|
+
repo.git.commit(
|
|
403
|
+
[wdir, "-m", f"Resolve Overleaf merge conflict in {wdir}"]
|
|
404
|
+
)
|
|
405
|
+
if in_am_session:
|
|
406
|
+
repo.git.am("--skip")
|
|
407
|
+
elif resolve:
|
|
408
|
+
continue
|
|
357
409
|
# If there are any uncommitted changes in the publication working
|
|
358
410
|
# directory, raise an error
|
|
359
411
|
if repo.git.diff(wdir) or repo.index.diff("HEAD", wdir):
|
|
@@ -365,9 +417,8 @@ def sync(
|
|
|
365
417
|
overleaf_project_dir = os.path.join(
|
|
366
418
|
".calkit", "overleaf", overleaf_project_id
|
|
367
419
|
)
|
|
368
|
-
overleaf_remote_url = (
|
|
369
|
-
|
|
370
|
-
f"{overleaf_project_id}"
|
|
420
|
+
overleaf_remote_url = calkit.overleaf.get_git_remote_url(
|
|
421
|
+
project_id=overleaf_project_id, token=str(overleaf_token)
|
|
371
422
|
)
|
|
372
423
|
if not os.path.isdir(overleaf_project_dir):
|
|
373
424
|
overleaf_repo = git.Repo.clone_from(
|
|
@@ -389,7 +440,10 @@ def sync(
|
|
|
389
440
|
"it matches one in your Overleaf account settings "
|
|
390
441
|
"(https://overleaf.com/user/settings)"
|
|
391
442
|
)
|
|
392
|
-
|
|
443
|
+
if resolve:
|
|
444
|
+
last_sync_commit = resolving_info["last_overleaf_commit"]
|
|
445
|
+
else:
|
|
446
|
+
last_sync_commit = pub["overleaf"].get("last_sync_commit")
|
|
393
447
|
if last_sync_commit:
|
|
394
448
|
commits_since = list(
|
|
395
449
|
overleaf_repo.iter_commits(rev=f"{last_sync_commit}..HEAD")
|
|
@@ -398,6 +452,8 @@ def sync(
|
|
|
398
452
|
f"There have been {len(commits_since)} changes on "
|
|
399
453
|
"Overleaf since last sync"
|
|
400
454
|
)
|
|
455
|
+
else:
|
|
456
|
+
commits_since = []
|
|
401
457
|
# Determine which paths to sync and push
|
|
402
458
|
# TODO: Support glob patterns
|
|
403
459
|
git_sync_paths = pub["overleaf"].get("sync_paths", [])
|
|
@@ -405,6 +461,14 @@ def sync(
|
|
|
405
461
|
dvc_sync_paths = pub["overleaf"].get("dvc_sync_paths", [])
|
|
406
462
|
sync_paths = git_sync_paths + dvc_sync_paths
|
|
407
463
|
push_paths = pub["overleaf"].get("push_paths", [])
|
|
464
|
+
implicit_sync_paths = os.listdir(overleaf_repo.working_dir)
|
|
465
|
+
for p in implicit_sync_paths:
|
|
466
|
+
if p.startswith("."):
|
|
467
|
+
continue
|
|
468
|
+
if p not in sync_paths:
|
|
469
|
+
sync_paths.append(p)
|
|
470
|
+
if p not in git_sync_paths and p not in dvc_sync_paths:
|
|
471
|
+
git_sync_paths.append(p)
|
|
408
472
|
git_sync_paths_in_project = [
|
|
409
473
|
os.path.join(wdir, p) for p in git_sync_paths
|
|
410
474
|
]
|
|
@@ -439,7 +503,6 @@ def sync(
|
|
|
439
503
|
"git",
|
|
440
504
|
"am",
|
|
441
505
|
"--3way",
|
|
442
|
-
"--reject",
|
|
443
506
|
"--directory",
|
|
444
507
|
wdir,
|
|
445
508
|
"-",
|
|
@@ -447,25 +510,38 @@ def sync(
|
|
|
447
510
|
input=patch,
|
|
448
511
|
text=True,
|
|
449
512
|
encoding="utf-8",
|
|
513
|
+
capture_output=True,
|
|
450
514
|
)
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
515
|
+
# Handle merge conflicts
|
|
516
|
+
if (
|
|
517
|
+
process.returncode != 0
|
|
518
|
+
and "merge conflict" in process.stdout.lower()
|
|
519
|
+
):
|
|
520
|
+
msg = ""
|
|
521
|
+
for line in process.stdout.split("\n"):
|
|
522
|
+
if "merge conflict" in line.lower():
|
|
523
|
+
msg += line + "\n"
|
|
524
|
+
# Save a file to track this merge conflict
|
|
525
|
+
c = overleaf_repo.head.commit.hexsha
|
|
526
|
+
with open(conflict_fpath, "w") as f:
|
|
527
|
+
json.dump(
|
|
528
|
+
{
|
|
529
|
+
"wdir": wdir,
|
|
530
|
+
"last_overleaf_commit": c,
|
|
531
|
+
"pub_path": pub["path"],
|
|
532
|
+
},
|
|
533
|
+
f,
|
|
468
534
|
)
|
|
535
|
+
raise_error(
|
|
536
|
+
f"{msg}Edit the file(s) and then call:\n\n"
|
|
537
|
+
" calkit overleaf sync --resolve"
|
|
538
|
+
)
|
|
539
|
+
elif process.returncode != 0:
|
|
540
|
+
raise_error(f"Could not apply:\n{process.stdout}")
|
|
541
|
+
elif resolve:
|
|
542
|
+
# We have no patch since the last sync, but we need to update
|
|
543
|
+
# our latest sync commit
|
|
544
|
+
typer.echo("Merge conflict resolved")
|
|
469
545
|
else:
|
|
470
546
|
typer.echo("No changes to apply")
|
|
471
547
|
else:
|
|
@@ -535,6 +611,8 @@ def sync(
|
|
|
535
611
|
with open("calkit.yaml", "w") as f:
|
|
536
612
|
calkit.ryaml.dump(ck_info, f)
|
|
537
613
|
repo.git.add("calkit.yaml")
|
|
614
|
+
if resolve and os.path.isfile(conflict_fpath):
|
|
615
|
+
os.remove(conflict_fpath)
|
|
538
616
|
# Stage the changes in the project repo
|
|
539
617
|
# Add any DVC sync paths to DVC
|
|
540
618
|
for dvc_sync_path in dvc_sync_paths_in_project:
|
|
@@ -660,9 +738,8 @@ def get_status(
|
|
|
660
738
|
overleaf_project_dir = os.path.join(
|
|
661
739
|
".calkit", "overleaf", overleaf_project_id
|
|
662
740
|
)
|
|
663
|
-
overleaf_remote_url = (
|
|
664
|
-
|
|
665
|
-
f"{overleaf_project_id}"
|
|
741
|
+
overleaf_remote_url = calkit.overleaf.get_git_remote_url(
|
|
742
|
+
project_id=overleaf_project_id, token=str(overleaf_token)
|
|
666
743
|
)
|
|
667
744
|
if not os.path.isdir(overleaf_project_dir):
|
|
668
745
|
overleaf_repo = git.Repo.clone_from(
|
|
@@ -64,7 +64,7 @@ def update_license(
|
|
|
64
64
|
] = False,
|
|
65
65
|
):
|
|
66
66
|
"""Update license with a reasonable default
|
|
67
|
-
(MIT for code, CC-BY-4.0 for other files)
|
|
67
|
+
(MIT for code, CC-BY-4.0 for other files).
|
|
68
68
|
"""
|
|
69
69
|
with open("LICENSE", "w") as f:
|
|
70
70
|
f.write(
|
|
@@ -202,14 +202,38 @@ def update_release(
|
|
|
202
202
|
# TODO: Enable reuploading artifact releases
|
|
203
203
|
if path != "." or release_type != "project":
|
|
204
204
|
raise_error("Can only handle updating project releases")
|
|
205
|
-
|
|
205
|
+
release_dir = f".calkit/releases/{name}"
|
|
206
|
+
release_files_dir = release_dir + "/files"
|
|
207
|
+
os.makedirs(release_files_dir, exist_ok=True)
|
|
208
|
+
# Save a metadata file with each DVC file's MD5 checksum
|
|
209
|
+
dvc_md5s = calkit.releases.make_dvc_md5s(
|
|
210
|
+
zipfile="archive.zip" if path == "." else None,
|
|
211
|
+
paths=None if path == "." else [path],
|
|
212
|
+
)
|
|
213
|
+
dvc_md5s_path = release_dir + "/dvc-md5s.yaml"
|
|
214
|
+
typer.echo(f"Saving DVC MD5 info to {dvc_md5s_path}")
|
|
215
|
+
with open(dvc_md5s_path, "w") as f:
|
|
216
|
+
calkit.ryaml.dump(dvc_md5s, f)
|
|
217
|
+
# Create a README for the Invenio release
|
|
218
|
+
typer.echo("Creating README.md for release")
|
|
219
|
+
title = ck_info.get("title")
|
|
220
|
+
if title is None:
|
|
221
|
+
raise_error("Project has no title")
|
|
222
|
+
readme_txt = f"# {title}\n"
|
|
223
|
+
git_rev = repo.git.rev_parse(["--short", "HEAD"])
|
|
224
|
+
readme_txt += (
|
|
225
|
+
f"\nThis is a {release_type} release ({name}) generated with "
|
|
226
|
+
f"Calkit from Git rev {git_rev}.\n"
|
|
227
|
+
)
|
|
228
|
+
readme_path = release_files_dir + "/README.md"
|
|
229
|
+
with open(readme_path, "w") as f:
|
|
230
|
+
f.write(readme_txt)
|
|
206
231
|
zip_path = release_files_dir + "/archive.zip"
|
|
207
232
|
all_paths = calkit.releases.ls_files()
|
|
208
233
|
typer.echo(f"Adding files to {zip_path}")
|
|
209
234
|
with zipfile.ZipFile(zip_path, "w") as zipf:
|
|
210
235
|
for fpath in all_paths:
|
|
211
236
|
zipf.write(fpath)
|
|
212
|
-
files = os.listdir(release_files_dir)
|
|
213
237
|
try:
|
|
214
238
|
files_in_record = [
|
|
215
239
|
entry["key"]
|
|
@@ -224,6 +248,10 @@ def update_release(
|
|
|
224
248
|
"Failed to get existing files in record: "
|
|
225
249
|
f"{e.__class__.__name__}: {e}"
|
|
226
250
|
)
|
|
251
|
+
# Check size of files dir
|
|
252
|
+
size = calkit.get_size(release_files_dir)
|
|
253
|
+
typer.echo(f"Release size: {(size / 1e6):.1f} MB")
|
|
254
|
+
files = os.listdir(release_files_dir)
|
|
227
255
|
for filename in files:
|
|
228
256
|
if filename in files_in_record:
|
|
229
257
|
typer.echo(f"Deleting existing file {filename} from draft")
|
|
@@ -602,3 +602,23 @@ def get_md5(path: str, exclude_files: list[str] | None = None) -> str:
|
|
|
602
602
|
with open(path) as f:
|
|
603
603
|
content = f.read()
|
|
604
604
|
return hashlib.md5(content.encode()).hexdigest()
|
|
605
|
+
|
|
606
|
+
|
|
607
|
+
def set_env_vars(ck_info: dict, cli: bool = True) -> None:
|
|
608
|
+
"""Set environmental variables according to the values read from
|
|
609
|
+
``calkit.yaml``.
|
|
610
|
+
"""
|
|
611
|
+
env_vars = ck_info.get("env_vars", {})
|
|
612
|
+
if not isinstance(env_vars, dict):
|
|
613
|
+
msg = (
|
|
614
|
+
"Environmental variables in Calkit project info must be a "
|
|
615
|
+
"map/dictionary"
|
|
616
|
+
)
|
|
617
|
+
if cli:
|
|
618
|
+
from calkit.cli import raise_error
|
|
619
|
+
|
|
620
|
+
raise_error(msg)
|
|
621
|
+
else:
|
|
622
|
+
raise ValueError(msg)
|
|
623
|
+
for k, v in env_vars.items():
|
|
624
|
+
os.environ[str(k)] = str(v)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Functionality for working with Overleaf."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import calkit
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_git_remote_url(project_id: str, token: str) -> str:
|
|
9
|
+
"""Form the Git remote URL for an Overleaf project.
|
|
10
|
+
|
|
11
|
+
If running against a test environment, this will use a local directory.
|
|
12
|
+
"""
|
|
13
|
+
if calkit.config.get_env() == "test":
|
|
14
|
+
return os.path.join("/tmp", "overleaf", project_id)
|
|
15
|
+
return f"https://git:{token}@git.overleaf.com/{project_id}"
|
|
@@ -50,6 +50,18 @@ def test_run_in_env(tmp_dir):
|
|
|
50
50
|
stdin=stdin,
|
|
51
51
|
check=True,
|
|
52
52
|
)
|
|
53
|
+
# Check that we can pass project env vars into the container
|
|
54
|
+
ck_info = calkit.load_calkit_info()
|
|
55
|
+
ck_info["env_vars"] = {"MY_COOL_ENV_VAR": "my cool value"}
|
|
56
|
+
with open("calkit.yaml", "w") as f:
|
|
57
|
+
calkit.ryaml.dump(ck_info, f)
|
|
58
|
+
p = subprocess.run(
|
|
59
|
+
["calkit", "xenv", "echo", "$MY_COOL_ENV_VAR"],
|
|
60
|
+
text=True,
|
|
61
|
+
capture_output=True,
|
|
62
|
+
check=True,
|
|
63
|
+
)
|
|
64
|
+
assert "my cool value" in p.stdout
|
|
53
65
|
# Now let's create a 2nd Docker env and make sure we need to call it by
|
|
54
66
|
# name when trying to run
|
|
55
67
|
subprocess.check_call(
|
|
@@ -452,6 +464,19 @@ def test_run(tmp_dir):
|
|
|
452
464
|
subprocess.check_call(
|
|
453
465
|
["calkit", "save", "-am", "Run pipeline", "--no-push"]
|
|
454
466
|
)
|
|
467
|
+
# Test that we can set env vars at the project level
|
|
468
|
+
ck_info = calkit.load_calkit_info()
|
|
469
|
+
ck_info["env_vars"] = {"MY_ENV_VAR": "some-value"}
|
|
470
|
+
with open("calkit.yaml", "w") as f:
|
|
471
|
+
calkit.ryaml.dump(ck_info, f)
|
|
472
|
+
with open("script.py", "w") as f:
|
|
473
|
+
f.write("import os\nprint(os.environ['MY_ENV_VAR'])")
|
|
474
|
+
out = subprocess.check_output(["calkit", "run"], text=True)
|
|
475
|
+
print(out)
|
|
476
|
+
assert "some-value" in out
|
|
477
|
+
subprocess.check_call(
|
|
478
|
+
["calkit", "save", "-am", "Run pipeline", "--no-push"]
|
|
479
|
+
)
|
|
455
480
|
# Make sure we can run on a detached head
|
|
456
481
|
repo = git.Repo()
|
|
457
482
|
repo.git.checkout("HEAD^")
|