calkit-python 0.27.1__tar.gz → 0.27.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.27.1 → calkit_python-0.27.3}/PKG-INFO +1 -1
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/__init__.py +1 -1
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/main.py +13 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/models/iteration.py +10 -1
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/models/pipeline.py +72 -11
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/pipeline.py +30 -6
- calkit_python-0.27.3/calkit/tests/models/test_iteration.py +16 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/models/test_pipeline.py +17 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_pipeline.py +54 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/pipeline/index.md +22 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.github/FUNDING.yml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.github/workflows/docs.yml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.github/workflows/format.yml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.github/workflows/publish-test.yml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.github/workflows/publish.yml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.github/workflows/test.yml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.gitignore +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.pre-commit-config.yaml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/.python-version +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/CITATION.cff +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/CONTRIBUTING.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/LICENSE +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/Makefile +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/README.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/__main__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/calc.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/check.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/check.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/cloud.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/config.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/core.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/describe.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/import_.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/list.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/new.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/notebooks.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/office.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/overleaf.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cli/update.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/cloud.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/conda.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/config.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/core.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/datasets.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/docker.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/dvc.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/environments.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/git.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/github.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/gui.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/jupyter.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/magics.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/matlab.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/models/__init__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/models/core.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/models/io.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/notebooks.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/office.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/ops.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/releases.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/server.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/core.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/cli/test_check.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/cli/test_config.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/cli/test_main.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/cli/test_new.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/cli/test_notebooks.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/models/__init__.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_conda.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_dvc.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_notebooks.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/calkit/zenodo.py +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/CNAME +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/apps.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/calculations.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/cli-reference.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/cloud-integration.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/datasets.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/dependencies.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/environments.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/examples.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/help.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/img/connect-zenodo.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/img/jupyterlab-params.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/img/vscode-nb-params.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/index.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/installation.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/local-server.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/notebooks.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/overleaf.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/pipeline/running-and-logging.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/quickstart.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/references.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/releases.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/existing-project.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/index.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/office.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/docs/version-control.md +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/mkdocs.yml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/pyproject.toml +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/scripts/install.ps1 +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/scripts/install.sh +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/test/nb-subdir.ipynb +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/test/pipeline.ipynb +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/test/test-log.log +0 -0
- {calkit_python-0.27.1 → calkit_python-0.27.3}/uv.lock +0 -0
|
@@ -620,9 +620,22 @@ def pull(
|
|
|
620
620
|
list[str],
|
|
621
621
|
typer.Option("--dvc-arg", help="Additional DVC args."),
|
|
622
622
|
] = [],
|
|
623
|
+
force: Annotated[
|
|
624
|
+
bool,
|
|
625
|
+
typer.Option(
|
|
626
|
+
"--force",
|
|
627
|
+
"-f",
|
|
628
|
+
help="Force pull, potentially overwriting local changes.",
|
|
629
|
+
),
|
|
630
|
+
] = False,
|
|
623
631
|
):
|
|
624
632
|
"""Pull with both Git and DVC."""
|
|
625
633
|
typer.echo("Git pulling")
|
|
634
|
+
if force:
|
|
635
|
+
if "-f" not in git_args and "--force" not in git_args:
|
|
636
|
+
git_args.append("-f")
|
|
637
|
+
if "-f" not in dvc_args and "--force" not in dvc_args:
|
|
638
|
+
dvc_args.append("-f")
|
|
626
639
|
try:
|
|
627
640
|
subprocess.check_call(["git", "pull"] + git_args)
|
|
628
641
|
except subprocess.CalledProcessError:
|
|
@@ -16,10 +16,19 @@ class RangeIteration(BaseModel):
|
|
|
16
16
|
|
|
17
17
|
@property
|
|
18
18
|
def values(self) -> list[int | float]:
|
|
19
|
+
# Determine precision from inputs
|
|
20
|
+
def get_decimal_places(num):
|
|
21
|
+
return len(str(num).split(".")[-1]) if "." in str(num) else 0
|
|
22
|
+
|
|
23
|
+
max_precision = max(
|
|
24
|
+
get_decimal_places(self.range.start),
|
|
25
|
+
get_decimal_places(self.range.stop),
|
|
26
|
+
get_decimal_places(self.range.step),
|
|
27
|
+
)
|
|
19
28
|
vals = []
|
|
20
29
|
current = self.range.start
|
|
21
30
|
while current < self.range.stop:
|
|
22
|
-
vals.append(current)
|
|
31
|
+
vals.append(round(current, max_precision))
|
|
23
32
|
current += self.range.step
|
|
24
33
|
return vals
|
|
25
34
|
|
|
@@ -5,7 +5,7 @@ from __future__ import annotations
|
|
|
5
5
|
from pathlib import PurePosixPath
|
|
6
6
|
from typing import Any, Literal
|
|
7
7
|
|
|
8
|
-
from pydantic import BaseModel, ConfigDict, Discriminator
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, Discriminator, field_validator
|
|
9
9
|
from typing_extensions import Annotated
|
|
10
10
|
|
|
11
11
|
from calkit.models.io import InputsFromStageOutputs, PathOutput
|
|
@@ -21,18 +21,79 @@ from calkit.notebooks import (
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class StageIteration(BaseModel):
|
|
24
|
-
|
|
25
|
-
values: list[int | float | str | RangeIteration | ParameterIteration]
|
|
24
|
+
"""A model for the ``iterate_over`` key in a stage definition.
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
If ``arg_name`` is a list, ``values`` also must be a list of lists with
|
|
27
|
+
each sublist the length of ``arg_name``.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
arg_name: str | list[str]
|
|
31
|
+
values: list[
|
|
32
|
+
int
|
|
33
|
+
| float
|
|
34
|
+
| str
|
|
35
|
+
| RangeIteration
|
|
36
|
+
| ParameterIteration
|
|
37
|
+
| list[int | float | str]
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
@field_validator("values")
|
|
41
|
+
@classmethod
|
|
42
|
+
def validate_values_structure(cls, v, info):
|
|
43
|
+
"""Validate that values are structured correctly based on arg_name."""
|
|
44
|
+
arg_name = info.data.get("arg_name")
|
|
45
|
+
# If arg_name is a list, check that values contains lists of the
|
|
46
|
+
# correct length
|
|
47
|
+
if isinstance(arg_name, list):
|
|
48
|
+
expected_length = len(arg_name)
|
|
49
|
+
for i, value in enumerate(v):
|
|
50
|
+
# TODO: Support RangeIteration and ParameterIteration
|
|
51
|
+
if isinstance(value, (RangeIteration, ParameterIteration)):
|
|
52
|
+
raise ValueError(
|
|
53
|
+
"RangeIteration and ParameterIteration are not "
|
|
54
|
+
"allowed when arg_name is a list"
|
|
55
|
+
)
|
|
56
|
+
# Check if the value is a list and has the correct length
|
|
57
|
+
if not isinstance(value, list):
|
|
58
|
+
raise ValueError(
|
|
59
|
+
f"When arg_name is a list, all values must be lists; "
|
|
60
|
+
f"Value at index {i} is {type(value).__name__}"
|
|
61
|
+
)
|
|
62
|
+
if len(value) != expected_length:
|
|
63
|
+
raise ValueError(
|
|
64
|
+
f"When arg_name has {expected_length} elements, "
|
|
65
|
+
f"each value list must have {expected_length} "
|
|
66
|
+
f"elements; Value at index {i} has {len(value)} "
|
|
67
|
+
"elements"
|
|
68
|
+
)
|
|
69
|
+
return v
|
|
70
|
+
|
|
71
|
+
def expand_values(
|
|
72
|
+
self, params: ParametersType
|
|
73
|
+
) -> list[int | float | str | dict[str, int | float | str]]:
|
|
28
74
|
vals = []
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
75
|
+
if isinstance(self.arg_name, list):
|
|
76
|
+
# Expand into a list of dictionaries, in which case the DVC arg
|
|
77
|
+
# name must be auto-generated
|
|
78
|
+
for vals_list in self.values:
|
|
79
|
+
if not isinstance(vals_list, list):
|
|
80
|
+
raise ValueError(
|
|
81
|
+
"Expected a list for vals_list, got "
|
|
82
|
+
f"{type(vals_list).__name__}"
|
|
83
|
+
)
|
|
84
|
+
v = {}
|
|
85
|
+
for n, name in enumerate(self.arg_name):
|
|
86
|
+
v[name] = vals_list[n]
|
|
87
|
+
vals.append(v)
|
|
88
|
+
else:
|
|
89
|
+
# arg_name is a string
|
|
90
|
+
for vals_i in self.values:
|
|
91
|
+
if isinstance(vals_i, ParameterIteration):
|
|
92
|
+
vals += vals_i.values_from_params(params)
|
|
93
|
+
elif isinstance(vals_i, RangeIteration):
|
|
94
|
+
vals += vals_i.values
|
|
95
|
+
else:
|
|
96
|
+
vals.append(vals_i)
|
|
36
97
|
return vals
|
|
37
98
|
|
|
38
99
|
|
|
@@ -28,7 +28,23 @@ def _expand_matrix(input_dict: dict[str, list]) -> list[dict]:
|
|
|
28
28
|
list_of_dicts = []
|
|
29
29
|
for combination in combinations:
|
|
30
30
|
list_of_dicts.append(dict(zip(keys, combination)))
|
|
31
|
-
|
|
31
|
+
# After expanding the matrix, flatten any nested dictionaries in the result
|
|
32
|
+
# This handles cases where list-of-lists iterations produce dictionaries as
|
|
33
|
+
# values, by concatenating parent and child keys (e.g., "parent.child")
|
|
34
|
+
# so all permutations are represented as flat dictionaries
|
|
35
|
+
final_list = []
|
|
36
|
+
for item in list_of_dicts:
|
|
37
|
+
keys = list(item.keys())
|
|
38
|
+
vals = list(item.values())
|
|
39
|
+
vd = {}
|
|
40
|
+
for key, val in zip(keys, vals):
|
|
41
|
+
if isinstance(val, dict):
|
|
42
|
+
for k, v in val.items():
|
|
43
|
+
vd[f"{key}.{k}"] = v
|
|
44
|
+
else:
|
|
45
|
+
vd[key] = val
|
|
46
|
+
final_list.append(vd)
|
|
47
|
+
return final_list
|
|
32
48
|
|
|
33
49
|
|
|
34
50
|
def to_dvc(
|
|
@@ -90,16 +106,24 @@ def to_dvc(
|
|
|
90
106
|
# stage
|
|
91
107
|
if stage.iterate_over is not None:
|
|
92
108
|
# Process a list of iterations into a DVC matrix stage
|
|
109
|
+
# Initialize a DVC matrix
|
|
93
110
|
dvc_matrix = {}
|
|
111
|
+
# Initialize a dict for doing string formatting on the DVC stage
|
|
94
112
|
format_dict = {}
|
|
95
|
-
for iteration in stage.iterate_over:
|
|
113
|
+
for n, iteration in enumerate(stage.iterate_over):
|
|
96
114
|
arg_name = iteration.arg_name
|
|
97
|
-
|
|
115
|
+
exp_vals = iteration.expand_values(
|
|
98
116
|
params=ck_info.get("parameters", {})
|
|
99
117
|
)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
118
|
+
if isinstance(arg_name, list):
|
|
119
|
+
dvc_arg_name = f"_arg{n}"
|
|
120
|
+
for arg_name_i in arg_name:
|
|
121
|
+
item_string = f"${{item.{dvc_arg_name}.{arg_name_i}}}"
|
|
122
|
+
format_dict[arg_name_i] = item_string
|
|
123
|
+
else:
|
|
124
|
+
dvc_arg_name = arg_name
|
|
125
|
+
format_dict[arg_name] = f"${{item.{arg_name}}}"
|
|
126
|
+
dvc_matrix[dvc_arg_name] = exp_vals
|
|
103
127
|
try:
|
|
104
128
|
cmd = dvc_stage["cmd"]
|
|
105
129
|
cmd = cmd.format(**format_dict)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Tests for ``calkit.models.iteration``."""
|
|
2
|
+
|
|
3
|
+
from calkit.models.iteration import RangeIteration, RangeIterationParams
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_rangeiteration():
|
|
7
|
+
r = RangeIteration(range=RangeIterationParams(start=0, stop=10, step=2))
|
|
8
|
+
assert r.values == [0, 2, 4, 6, 8]
|
|
9
|
+
r = RangeIteration(
|
|
10
|
+
range=RangeIterationParams(start=0.05, stop=0.25, step=0.1)
|
|
11
|
+
)
|
|
12
|
+
assert r.values == [0.05, 0.15]
|
|
13
|
+
r = RangeIteration(range=RangeIterationParams(start=0.5, stop=1, step=0.2))
|
|
14
|
+
assert r.values == [0.5, 0.7, 0.9]
|
|
15
|
+
r = RangeIteration(range=RangeIterationParams(start=0, stop=1, step=0.2))
|
|
16
|
+
assert r.values == [0.0, 0.2, 0.4, 0.6, 0.8]
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"""Tests for ``calkit.models.pipeline``."""
|
|
2
2
|
|
|
3
|
+
import pytest
|
|
4
|
+
from pydantic import ValidationError
|
|
5
|
+
|
|
3
6
|
from calkit.models.pipeline import (
|
|
4
7
|
JupyterNotebookStage,
|
|
5
8
|
LatexStage,
|
|
6
9
|
PythonScriptStage,
|
|
10
|
+
StageIteration,
|
|
7
11
|
WordToPdfStage,
|
|
8
12
|
)
|
|
9
13
|
|
|
@@ -102,3 +106,16 @@ def test_jupyternotebookstage():
|
|
|
102
106
|
assert "html" not in dvc_stage["cmd"]
|
|
103
107
|
assert " -p param1=value1 " in dvc_stage["cmd"]
|
|
104
108
|
assert " -p param2=value2 " in dvc_stage["cmd"]
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_stageiteration():
|
|
112
|
+
StageIteration(
|
|
113
|
+
arg_name="param1",
|
|
114
|
+
values=[1, 2, 3],
|
|
115
|
+
)
|
|
116
|
+
with pytest.raises(ValidationError):
|
|
117
|
+
StageIteration(arg_name=["param1", "param2"], values=[1, 2, 3])
|
|
118
|
+
i = StageIteration(arg_name=["param1", "param2"], values=[[1, 2], [3, 4]])
|
|
119
|
+
i.values
|
|
120
|
+
exp_vals = i.expand_values(params={})
|
|
121
|
+
assert exp_vals == [{"param1": 1, "param2": 2}, {"param1": 3, "param2": 4}]
|
|
@@ -277,6 +277,60 @@ def test_to_dvc_notebook_stage():
|
|
|
277
277
|
assert "something" in stage["matrix"]["param3"]
|
|
278
278
|
|
|
279
279
|
|
|
280
|
+
def test_to_dvc_list_of_list_iteration():
|
|
281
|
+
# Test that we can define iteration over a list of lists
|
|
282
|
+
ck_info = {
|
|
283
|
+
"pipeline": {
|
|
284
|
+
"stages": {
|
|
285
|
+
"get-data": {
|
|
286
|
+
"kind": "python-script",
|
|
287
|
+
"environment": "something",
|
|
288
|
+
"script_path": "something/my-cool-script.py",
|
|
289
|
+
"args": ["--a1={var1}", "--a2={var2}"],
|
|
290
|
+
"iterate_over": [
|
|
291
|
+
{
|
|
292
|
+
"arg_name": ["var1", "var2"],
|
|
293
|
+
"values": [[1, "a"], [2, "b"], [3, "c"]],
|
|
294
|
+
},
|
|
295
|
+
],
|
|
296
|
+
"outputs": [
|
|
297
|
+
"out-{var1}-{var2}.out",
|
|
298
|
+
"out2-{var1}-{var2}.out",
|
|
299
|
+
],
|
|
300
|
+
},
|
|
301
|
+
"process-data": {
|
|
302
|
+
"kind": "python-script",
|
|
303
|
+
"script_path": "something.py",
|
|
304
|
+
"environment": "py",
|
|
305
|
+
"inputs": [
|
|
306
|
+
{"from_stage_outputs": "get-data"},
|
|
307
|
+
"something.else.txt",
|
|
308
|
+
],
|
|
309
|
+
},
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
dvc_stages = calkit.pipeline.to_dvc(ck_info=ck_info, write=False)
|
|
314
|
+
stage = dvc_stages["get-data"]
|
|
315
|
+
assert "--a1=${item._arg0.var1} --a2=${item._arg0.var2}" in stage["cmd"]
|
|
316
|
+
matrix = stage["matrix"]
|
|
317
|
+
assert matrix == {
|
|
318
|
+
"_arg0": [
|
|
319
|
+
{"var1": 1, "var2": "a"},
|
|
320
|
+
{"var1": 2, "var2": "b"},
|
|
321
|
+
{"var1": 3, "var2": "c"},
|
|
322
|
+
]
|
|
323
|
+
}
|
|
324
|
+
assert stage["outs"] == [
|
|
325
|
+
"out-${item._arg0.var1}-${item._arg0.var2}.out",
|
|
326
|
+
"out2-${item._arg0.var1}-${item._arg0.var2}.out",
|
|
327
|
+
]
|
|
328
|
+
print(dvc_stages)
|
|
329
|
+
stage2 = dvc_stages["process-data"]
|
|
330
|
+
assert "out-1-a.out" in stage2["deps"]
|
|
331
|
+
assert "out2-2-b.out" in stage2["deps"]
|
|
332
|
+
|
|
333
|
+
|
|
280
334
|
def test_remove_stage(tmp_dir):
|
|
281
335
|
subprocess.check_call(["calkit", "init"])
|
|
282
336
|
# Test that we can remove a stage from the pipeline
|
|
@@ -105,6 +105,28 @@ pipeline:
|
|
|
105
105
|
- models/{var}.h5
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
+
### Over a table (or list of lists)
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
pipeline:
|
|
112
|
+
stages:
|
|
113
|
+
my-iter-stage:
|
|
114
|
+
kind: python-script
|
|
115
|
+
script_path: scripts/my-script.py
|
|
116
|
+
args:
|
|
117
|
+
- "--model={var1}"
|
|
118
|
+
- "--n_estimators={var2}"
|
|
119
|
+
iterate_over:
|
|
120
|
+
- arg_name: [var1, var2]
|
|
121
|
+
values:
|
|
122
|
+
- [some-model, 5]
|
|
123
|
+
- [some-other-model, 7]
|
|
124
|
+
inputs:
|
|
125
|
+
- data/raw
|
|
126
|
+
outputs:
|
|
127
|
+
- models/{var1}-{var2}.h5
|
|
128
|
+
```
|
|
129
|
+
|
|
108
130
|
### Over ranges of numbers
|
|
109
131
|
|
|
110
132
|
```yaml
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/editor-split.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/new-project.png
RENAMED
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/new-pub-2.png
RENAMED
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/new-token.png
RENAMED
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/paper.tex.png
RENAMED
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/latex-codespaces/project-home-3.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/insert-link-to-file.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/pipeline-out-of-date.png
RENAMED
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/status-more-rows.png
RENAMED
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/uncommitted-changes.png
RENAMED
|
File without changes
|
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/updated-publication.png
RENAMED
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/office/word-to-pdf-stage-2.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/create-project.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{calkit_python-0.27.1 → calkit_python-0.27.3}/docs/tutorials/img/openfoam/figure-on-website.png
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|