calkit-python 0.16.2__tar.gz → 0.16.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.16.2 → calkit_python-0.16.3}/.gitignore +1 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/PKG-INFO +2 -1
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/__init__.py +1 -1
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/check.py +30 -4
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/main.py +8 -6
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/conda.py +12 -3
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/cli/test_main.py +27 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/environments.md +15 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/pyproject.toml +1 -0
- calkit_python-0.16.3/uv.lock +3735 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/.github/FUNDING.yml +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/.github/workflows/docs.yml +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/.github/workflows/publish-test.yml +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/.github/workflows/publish.yml +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/LICENSE +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/README.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/calc.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/check.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/__init__.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/config.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/core.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/import_.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/list.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/new.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/notebooks.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/office.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cli/update.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/cloud.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/config.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/core.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/datasets.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/docker.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/dvc.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/git.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/gui.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/jupyter.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/magics.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/models.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/office.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/ops.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/server.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/__init__.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/core.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/__init__.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/article/paper.tex +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/core.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/jfm/jfm.bst +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/jfm/jfm.cls +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/jfm/lineno-FLM.sty +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/jfm/paper.tex +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/templates/latex/jfm/upmath.sty +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/__init__.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/cli/__init__.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/cli/test_list.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/cli/test_new.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_calc.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_check.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_conda.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_core.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_dvc.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_jupyter.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_magics.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/calkit/tests/test_templates.py +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/CNAME +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/apps.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/calculations.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/calkit-yaml.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/cli-reference.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/cloud-integration.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/examples.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/help.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/img/c-to-the-k-white.svg +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/img/calkit-no-bg.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/index.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/installation.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/pipeline/index.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/pipeline/manual-steps.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/references.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/adding-latex-pub-docker.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/conda-envs.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/first-project.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/building-codespace.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/codespaces-secrets-2.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/editor-split.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/go-to-linked-code.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/issue-from-selection.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/new-project.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/new-pub-2.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/new-token.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/paper.tex.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/project-home-3.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/push.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/latex-codespaces/stage.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/anakin-excel.jpg +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/chart-more-rows.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/create-project.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/elsevier-research-data-guidelines.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/excel-chart.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/excel-data.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/insert-link-to-file.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/needs-clone.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/new-stage.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/phd-comics-version-control.webp +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/pipeline-out-of-date.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/status-more-rows.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/uncommitted-changes.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/untracked-data.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/updated-publication.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/word-to-pdf-stage-2.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/office/workflow-page.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/clone.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/create-project.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/datasets-page.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/figure-on-website-updated.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/figure-on-website.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/new-token.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/reclone.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/openfoam/status-after-import-dataset.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/img/run-proc.png +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/latex-codespaces.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/matlab.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/notebook-pipeline.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/office.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/openfoam.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/tutorials/procedures.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/docs/version-control.md +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/mkdocs.yml +0 -0
- {calkit_python-0.16.2 → calkit_python-0.16.3}/test/pipeline.ipynb +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: calkit-python
|
|
3
|
-
Version: 0.16.
|
|
3
|
+
Version: 0.16.3
|
|
4
4
|
Summary: Reproducibility simplified.
|
|
5
5
|
Project-URL: Homepage, https://calkit.org
|
|
6
6
|
Project-URL: Issues, https://github.com/calkit/calkit/issues
|
|
@@ -12,6 +12,7 @@ Classifier: Operating System :: OS Independent
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3
|
|
13
13
|
Requires-Python: >=3.8
|
|
14
14
|
Requires-Dist: arithmeval
|
|
15
|
+
Requires-Dist: checksumdir
|
|
15
16
|
Requires-Dist: docx2pdf
|
|
16
17
|
Requires-Dist: dvc
|
|
17
18
|
Requires-Dist: eval-type-backport; python_version < '3.10'
|
|
@@ -9,6 +9,7 @@ import os
|
|
|
9
9
|
import subprocess
|
|
10
10
|
from typing import Annotated
|
|
11
11
|
|
|
12
|
+
import checksumdir
|
|
12
13
|
import typer
|
|
13
14
|
|
|
14
15
|
import calkit
|
|
@@ -65,6 +66,14 @@ def check_docker_env(
|
|
|
65
66
|
platform: Annotated[
|
|
66
67
|
str, typer.Option("--platform", help="Which platform(s) to build for.")
|
|
67
68
|
] = None,
|
|
69
|
+
deps: Annotated[
|
|
70
|
+
list[str],
|
|
71
|
+
typer.Option(
|
|
72
|
+
"--dep",
|
|
73
|
+
"-d",
|
|
74
|
+
help="Declare an explicit dependency for this Docker image.",
|
|
75
|
+
),
|
|
76
|
+
] = [],
|
|
68
77
|
quiet: Annotated[
|
|
69
78
|
bool, typer.Option("--quiet", "-q", help="Be quiet.")
|
|
70
79
|
] = False,
|
|
@@ -81,6 +90,14 @@ def check_docker_env(
|
|
|
81
90
|
_ = out[0].pop("DockerVersion")
|
|
82
91
|
return out
|
|
83
92
|
|
|
93
|
+
def get_md5(path: str, exclude_files: list[str] | None = None) -> str:
|
|
94
|
+
if os.path.isdir(path):
|
|
95
|
+
return checksumdir.dirhash(dep, excluded_files=exclude_files)
|
|
96
|
+
else:
|
|
97
|
+
with open(path) as f:
|
|
98
|
+
content = f.read()
|
|
99
|
+
return hashlib.md5(content.encode()).hexdigest()
|
|
100
|
+
|
|
84
101
|
outfile = open(os.devnull, "w") if quiet else None
|
|
85
102
|
typer.echo(f"Checking for existing image with tag {tag}", file=outfile)
|
|
86
103
|
# First call Docker inspect
|
|
@@ -90,10 +107,12 @@ def check_docker_env(
|
|
|
90
107
|
typer.echo(f"No image with tag {tag} found locally", file=outfile)
|
|
91
108
|
inspect = []
|
|
92
109
|
typer.echo(f"Reading Dockerfile from {fpath}", file=outfile)
|
|
93
|
-
|
|
94
|
-
dockerfile = f.read()
|
|
95
|
-
dockerfile_md5 = hashlib.md5(dockerfile.encode()).hexdigest()
|
|
110
|
+
dockerfile_md5 = get_md5(fpath)
|
|
96
111
|
lock_fpath = fpath + "-lock.json"
|
|
112
|
+
# Compute MD5s of any dependencies
|
|
113
|
+
deps_md5s = {}
|
|
114
|
+
for dep in deps:
|
|
115
|
+
deps_md5s[dep] = get_md5(dep, exclude_files=lock_fpath)
|
|
97
116
|
rebuild = True
|
|
98
117
|
if os.path.isfile(lock_fpath):
|
|
99
118
|
typer.echo(f"Reading lock file: {lock_fpath}", file=outfile)
|
|
@@ -109,6 +128,12 @@ def check_docker_env(
|
|
|
109
128
|
rebuild = inspect[0]["RootFS"]["Layers"] != lock[0]["RootFS"][
|
|
110
129
|
"Layers"
|
|
111
130
|
] or dockerfile_md5 != lock[0].get("DockerfileMD5")
|
|
131
|
+
if not rebuild:
|
|
132
|
+
for dep, md5 in deps_md5s.items():
|
|
133
|
+
if md5 != lock[0].get("DepsMD5s", {}).get(dep):
|
|
134
|
+
typer.echo(f"Found modified dependency: {dep}")
|
|
135
|
+
rebuild = True
|
|
136
|
+
break
|
|
112
137
|
if rebuild:
|
|
113
138
|
wdir, fname = os.path.split(fpath)
|
|
114
139
|
if not wdir:
|
|
@@ -117,10 +142,11 @@ def check_docker_env(
|
|
|
117
142
|
if platform is not None:
|
|
118
143
|
cmd += ["--platform", platform]
|
|
119
144
|
cmd.append(".")
|
|
120
|
-
subprocess.
|
|
145
|
+
subprocess.check_output(cmd, cwd=wdir)
|
|
121
146
|
# Write the lock file
|
|
122
147
|
inspect = get_docker_inspect()
|
|
123
148
|
inspect[0]["DockerfileMD5"] = dockerfile_md5
|
|
149
|
+
inspect[0]["DepsMD5s"] = deps_md5s
|
|
124
150
|
with open(lock_fpath, "w") as f:
|
|
125
151
|
json.dump(inspect, f, indent=4)
|
|
126
152
|
|
|
@@ -57,7 +57,8 @@ def _to_shell_cmd(cmd: list[str]) -> str:
|
|
|
57
57
|
"""
|
|
58
58
|
quoted_cmd = []
|
|
59
59
|
for part in cmd:
|
|
60
|
-
|
|
60
|
+
# Find quotes within quotes and escape them
|
|
61
|
+
if " " in part or '"' in part[1:-1] or "'" in part[1:-1]:
|
|
61
62
|
part = part.replace('"', r"\"")
|
|
62
63
|
quoted_cmd.append(f'"{part}"')
|
|
63
64
|
else:
|
|
@@ -708,12 +709,11 @@ def run_in_env(
|
|
|
708
709
|
if env_name not in envs:
|
|
709
710
|
raise_error(f"Environment '{env_name}' does not exist")
|
|
710
711
|
env = envs[env_name]
|
|
711
|
-
if wdir is not None:
|
|
712
|
-
cwd = os.path.abspath(wdir)
|
|
713
|
-
else:
|
|
714
|
-
cwd = os.getcwd()
|
|
715
712
|
image_name = env.get("image", env_name)
|
|
716
713
|
docker_wdir = env.get("wdir", "/work")
|
|
714
|
+
docker_wdir_mount = docker_wdir
|
|
715
|
+
if wdir is not None:
|
|
716
|
+
docker_wdir = os.path.join(docker_wdir, wdir)
|
|
717
717
|
shell = env.get("shell", "sh")
|
|
718
718
|
platform = env.get("platform")
|
|
719
719
|
if env["kind"] == "docker":
|
|
@@ -724,6 +724,7 @@ def run_in_env(
|
|
|
724
724
|
tag=env["image"],
|
|
725
725
|
fpath=env["path"],
|
|
726
726
|
platform=env.get("platform"),
|
|
727
|
+
deps=env.get("deps", []),
|
|
727
728
|
quiet=True,
|
|
728
729
|
)
|
|
729
730
|
shell_cmd = _to_shell_cmd(cmd)
|
|
@@ -733,13 +734,14 @@ def run_in_env(
|
|
|
733
734
|
]
|
|
734
735
|
if platform:
|
|
735
736
|
docker_cmd += ["--platform", platform]
|
|
737
|
+
docker_cmd += env.get("args", [])
|
|
736
738
|
docker_cmd += [
|
|
737
739
|
"-it" if sys.stdin.isatty() else "-i",
|
|
738
740
|
"--rm",
|
|
739
741
|
"-w",
|
|
740
742
|
docker_wdir,
|
|
741
743
|
"-v",
|
|
742
|
-
f"{
|
|
744
|
+
f"{os.getcwd()}:{docker_wdir_mount}",
|
|
743
745
|
image_name,
|
|
744
746
|
shell,
|
|
745
747
|
"-c",
|
|
@@ -4,9 +4,10 @@ import json
|
|
|
4
4
|
import os
|
|
5
5
|
import re
|
|
6
6
|
import subprocess
|
|
7
|
+
import warnings
|
|
7
8
|
|
|
8
9
|
from packaging.specifiers import SpecifierSet
|
|
9
|
-
from packaging.version import Version
|
|
10
|
+
from packaging.version import InvalidVersion, Version
|
|
10
11
|
from pydantic import BaseModel
|
|
11
12
|
|
|
12
13
|
import calkit
|
|
@@ -20,14 +21,22 @@ def _check_single(req: str, actual: str, conda: bool = False) -> bool:
|
|
|
20
21
|
if conda and req_spec.startswith("="):
|
|
21
22
|
req_spec = "=" + req_spec
|
|
22
23
|
if not req_spec.endswith(".*"):
|
|
23
|
-
req_spec
|
|
24
|
+
if len(req_spec.split(".")) < 3:
|
|
25
|
+
req_spec += ".*"
|
|
24
26
|
actual_name, actual_vers = re.split("[=<>]+", actual, maxsplit=1)
|
|
25
27
|
if actual_name != req_name:
|
|
26
28
|
return False
|
|
27
29
|
actual_spec = actual.removeprefix(actual_name)
|
|
28
30
|
if conda and actual_spec.startswith("="):
|
|
29
31
|
actual_spec = "=" + actual_spec
|
|
30
|
-
|
|
32
|
+
try:
|
|
33
|
+
version = Version(actual_vers)
|
|
34
|
+
except InvalidVersion:
|
|
35
|
+
warnings.warn(
|
|
36
|
+
f"Cannot properly check {actual_name} version {actual_vers}"
|
|
37
|
+
)
|
|
38
|
+
# TODO: Check exact version only
|
|
39
|
+
return True
|
|
31
40
|
spec = SpecifierSet(req_spec)
|
|
32
41
|
return spec.contains(version)
|
|
33
42
|
|
|
@@ -85,6 +85,26 @@ def test_run_in_env(tmp_dir):
|
|
|
85
85
|
ck_info = calkit.load_calkit_info()
|
|
86
86
|
env = ck_info["environments"]["py3.10"]
|
|
87
87
|
assert env.get("path") is None
|
|
88
|
+
# Test that we can run a command that changes directory first
|
|
89
|
+
os.makedirs("my-new-dir/another", exist_ok=True)
|
|
90
|
+
out = (
|
|
91
|
+
subprocess.check_output(
|
|
92
|
+
"calkit xenv -n py3.10 --wdir my-new-dir -- ls",
|
|
93
|
+
shell=True,
|
|
94
|
+
)
|
|
95
|
+
.decode()
|
|
96
|
+
.strip()
|
|
97
|
+
)
|
|
98
|
+
assert out == "another"
|
|
99
|
+
out = (
|
|
100
|
+
subprocess.check_output(
|
|
101
|
+
"calkit xenv -n py3.10 --wdir my-new-dir -- ls ..",
|
|
102
|
+
shell=True,
|
|
103
|
+
)
|
|
104
|
+
.decode()
|
|
105
|
+
.strip()
|
|
106
|
+
)
|
|
107
|
+
assert "my-new-dir" in out.split("\n")
|
|
88
108
|
|
|
89
109
|
|
|
90
110
|
def test_run_in_venv(tmp_dir):
|
|
@@ -206,6 +226,13 @@ def test_to_shell_cmd():
|
|
|
206
226
|
shell_cmd = _to_shell_cmd(cmd)
|
|
207
227
|
assert shell_cmd == 'python -c "print(\\"hello world\\")"'
|
|
208
228
|
subprocess.check_call(shell_cmd, shell=True)
|
|
229
|
+
cmd = [
|
|
230
|
+
"sh",
|
|
231
|
+
"-c",
|
|
232
|
+
"cd dir1 && ls",
|
|
233
|
+
]
|
|
234
|
+
good_shell_cmd = 'sh -c "cd dir1 && ls"'
|
|
235
|
+
assert _to_shell_cmd(cmd) == good_shell_cmd
|
|
209
236
|
|
|
210
237
|
|
|
211
238
|
def test_add(tmp_dir):
|
|
@@ -154,6 +154,21 @@ and another call to `calkit xenv -n foam2` will kick off a rebuild
|
|
|
154
154
|
automatically,
|
|
155
155
|
since the lock file will no longer match the Dockerfile.
|
|
156
156
|
|
|
157
|
+
If you're copying local files into the Docker image,
|
|
158
|
+
you can declare these
|
|
159
|
+
dependencies in the environment definition so the content of those will be
|
|
160
|
+
tracked as well:
|
|
161
|
+
|
|
162
|
+
```yaml
|
|
163
|
+
# In calkit.yaml
|
|
164
|
+
environments:
|
|
165
|
+
foam2:
|
|
166
|
+
kind: docker
|
|
167
|
+
image: foam2
|
|
168
|
+
deps:
|
|
169
|
+
- src/mySolver.C
|
|
170
|
+
```
|
|
171
|
+
|
|
157
172
|
This highlights Calkit's declarative design philosophy.
|
|
158
173
|
Simply declare the environment and use it in a pipeline stage
|
|
159
174
|
and Calkit will ensure it is built and up to date.
|