calkit-python 0.48.2__py3-none-any.whl → 0.49.0__py3-none-any.whl
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/calc.py +15 -9
- calkit/cli/__init__.py +65 -1
- calkit/cli/check.py +425 -32
- calkit/cli/delete.py +25 -0
- calkit/cli/describe.py +13 -2
- calkit/cli/latex.py +115 -147
- calkit/cli/list.py +52 -0
- calkit/cli/main/core.py +636 -131
- calkit/cli/main/xr.py +55 -29
- calkit/cli/new.py +67 -0
- calkit/cli/overleaf.py +139 -109
- calkit/cli/scheduler.py +217 -2
- calkit/cli/update.py +394 -6
- calkit/conda.py +455 -41
- calkit/conditions.py +251 -0
- calkit/config.py +2 -25
- calkit/core.py +226 -54
- calkit/dependencies.py +6 -16
- calkit/docker.py +112 -0
- calkit/docx.py +7 -1
- calkit/dvc/core.py +434 -4
- calkit/environments.py +1229 -72
- calkit/git.py +79 -6
- calkit/latex.py +191 -24
- calkit/models/base.py +13 -0
- calkit/models/core.py +386 -260
- calkit/models/io.py +33 -7
- calkit/models/iteration.py +6 -4
- calkit/models/pipeline.py +213 -33
- calkit/models/requirements.py +216 -0
- calkit/overleaf.py +89 -8
- calkit/pipeline.py +548 -18
- calkit/questions.py +91 -194
- calkit/tests/cli/main/test_core.py +645 -8
- calkit/tests/cli/main/test_xr.py +8 -0
- calkit/tests/cli/test_check.py +411 -0
- calkit/tests/cli/test_delete.py +53 -0
- calkit/tests/cli/test_describe.py +17 -0
- calkit/tests/cli/test_latex.py +83 -1
- calkit/tests/cli/test_list.py +61 -0
- calkit/tests/cli/test_new.py +60 -0
- calkit/tests/cli/test_overleaf.py +60 -1
- calkit/tests/cli/test_scheduler.py +146 -0
- calkit/tests/cli/test_update.py +332 -0
- calkit/tests/dvc/test_core.py +93 -0
- calkit/tests/models/test_core.py +136 -1
- calkit/tests/test_conda.py +325 -0
- calkit/tests/test_conditions.py +114 -0
- calkit/tests/test_core.py +125 -3
- calkit/tests/test_docker.py +81 -0
- calkit/tests/test_docx.py +69 -6
- calkit/tests/test_environments.py +840 -1
- calkit/tests/test_overleaf.py +76 -0
- calkit/tests/test_pipeline.py +466 -3
- calkit/tests/test_questions.py +132 -120
- calkit/tests/test_workspace.py +40 -2
- calkit/upgrade.py +1 -1
- calkit/workspace.py +88 -26
- {calkit_python-0.48.2.dist-info → calkit_python-0.49.0.dist-info}/METADATA +5 -3
- {calkit_python-0.48.2.dist-info → calkit_python-0.49.0.dist-info}/RECORD +76 -72
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/etc/jupyter/jupyter_server_config.d/calkit.json +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/package.json +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/package.json.orig +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/schemas/calkit/plugin.json +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/506.c34b070098184e33.js +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/57d13a7399cec3c5.png +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/616.528427eb54a4a0c0.js +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/740.6bf87276e9e5788a.js +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/899.f9b9f9bf705a6493.js +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/935.46ecc6bf99aa593a.js +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/remoteEntry.109a3a8379365e59.js +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/style.js +0 -0
- {calkit_python-0.48.2.data → calkit_python-0.49.0.data}/data/share/jupyter/labextensions/calkit/static/third-party-licenses.json +0 -0
- {calkit_python-0.48.2.dist-info → calkit_python-0.49.0.dist-info}/WHEEL +0 -0
- {calkit_python-0.48.2.dist-info → calkit_python-0.49.0.dist-info}/entry_points.txt +0 -0
- {calkit_python-0.48.2.dist-info → calkit_python-0.49.0.dist-info}/licenses/LICENSE +0 -0
calkit/calc.py
CHANGED
|
@@ -4,14 +4,20 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import Annotated, Literal
|
|
6
6
|
|
|
7
|
-
from pydantic import BaseModel, Discriminator, model_validator
|
|
7
|
+
from pydantic import BaseModel, ConfigDict, Discriminator, model_validator
|
|
8
8
|
|
|
9
9
|
DTYPES = {"int": int, "float": float, "str": str}
|
|
10
10
|
DEFAULT_IN_TYPE = "float"
|
|
11
11
|
DEFAULT_OUT_TYPE = "float"
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class
|
|
14
|
+
class _Model(BaseModel):
|
|
15
|
+
# As calkit.models.base.Model, which importing here would import
|
|
16
|
+
# calkit.models, which imports this
|
|
17
|
+
model_config = ConfigDict(defer_build=True)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Input(_Model):
|
|
15
21
|
name: str
|
|
16
22
|
description: str | None = None
|
|
17
23
|
dtype: Literal["int", "float", "str"] = DEFAULT_IN_TYPE
|
|
@@ -19,14 +25,14 @@ class Input(BaseModel):
|
|
|
19
25
|
max: int | float | None = None
|
|
20
26
|
|
|
21
27
|
|
|
22
|
-
class Output(
|
|
28
|
+
class Output(_Model):
|
|
23
29
|
name: str
|
|
24
30
|
description: str | None = None
|
|
25
31
|
dtype: Literal["int", "float", "str"] = DEFAULT_OUT_TYPE
|
|
26
32
|
template: str | None = None
|
|
27
33
|
|
|
28
34
|
|
|
29
|
-
class Calculation(
|
|
35
|
+
class Calculation(_Model):
|
|
30
36
|
kind: str
|
|
31
37
|
params: dict = {}
|
|
32
38
|
name: str | None = None
|
|
@@ -124,7 +130,7 @@ class Calculation(BaseModel):
|
|
|
124
130
|
return template.format(**(inputs | {out_name: res}))
|
|
125
131
|
|
|
126
132
|
|
|
127
|
-
class FormulaParams(
|
|
133
|
+
class FormulaParams(_Model):
|
|
128
134
|
formula: str
|
|
129
135
|
|
|
130
136
|
|
|
@@ -139,7 +145,7 @@ class Formula(Calculation):
|
|
|
139
145
|
return arithmetic_eval.evaluate(self.params.formula, inputs)
|
|
140
146
|
|
|
141
147
|
|
|
142
|
-
class LinearParams(
|
|
148
|
+
class LinearParams(_Model):
|
|
143
149
|
coeffs: dict[str, float]
|
|
144
150
|
offset: float = 0.0
|
|
145
151
|
|
|
@@ -163,7 +169,7 @@ class Linear(Calculation):
|
|
|
163
169
|
return val
|
|
164
170
|
|
|
165
171
|
|
|
166
|
-
class LookupTableParams(
|
|
172
|
+
class LookupTableParams(_Model):
|
|
167
173
|
x_values: list[float]
|
|
168
174
|
y_values: list[float]
|
|
169
175
|
method: Literal["floor", "ceil", "round", "interpolate"] = "interpolate"
|
|
@@ -176,7 +182,7 @@ class LookupTable(Calculation):
|
|
|
176
182
|
params: LookupTableParams
|
|
177
183
|
|
|
178
184
|
|
|
179
|
-
class HttpRequestParams(
|
|
185
|
+
class HttpRequestParams(_Model):
|
|
180
186
|
url: str
|
|
181
187
|
inputs_as_params: bool = True # Otherwise, use body
|
|
182
188
|
method: Literal["get", "post", "put"] = "get"
|
|
@@ -210,7 +216,7 @@ class HttpRequest(Calculation):
|
|
|
210
216
|
return resp.text
|
|
211
217
|
|
|
212
218
|
|
|
213
|
-
class XGBoostModelParams(
|
|
219
|
+
class XGBoostModelParams(_Model):
|
|
214
220
|
path: str
|
|
215
221
|
type: Literal["classifier", "regressor"]
|
|
216
222
|
|
calkit/cli/__init__.py
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
1
5
|
from .core import * # noqa: F403
|
|
2
6
|
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
import typer
|
|
9
|
+
|
|
3
10
|
|
|
4
11
|
def run() -> None:
|
|
12
|
+
import os
|
|
13
|
+
import sys
|
|
14
|
+
|
|
5
15
|
# Intercept ``--use-version`` before Typer/Click parses argv: Click
|
|
6
16
|
# processes eager options like ``--help`` and ``--version`` (and the
|
|
7
17
|
# group's ``no_args_is_help``) ahead of the callback body, so an
|
|
@@ -11,7 +21,61 @@ def run() -> None:
|
|
|
11
21
|
_maybe_exec_with_version()
|
|
12
22
|
from .main import app
|
|
13
23
|
|
|
14
|
-
|
|
24
|
+
# Completion lists commands, so needs them all
|
|
25
|
+
if any(k.startswith("_") and k.endswith("_COMPLETE") for k in os.environ):
|
|
26
|
+
app()
|
|
27
|
+
else:
|
|
28
|
+
_only_invoked(app, sys.argv[1:])()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _only_invoked(
|
|
32
|
+
app: typer.Typer, args: list[str], top: bool = True
|
|
33
|
+
) -> typer.Typer:
|
|
34
|
+
"""Narrow ``app`` to the command or group ``args`` invoke.
|
|
35
|
+
|
|
36
|
+
Typer builds every command's options before running one, which for all
|
|
37
|
+
of Calkit's takes a few tenths of a second, so this leaves out the ones
|
|
38
|
+
that won't run. Anything else, e.g., ``--help`` or a misspelled command,
|
|
39
|
+
keeps them all, so help and suggestions list everything.
|
|
40
|
+
decisions/calkit.yaml has a question on how much that saves.
|
|
41
|
+
"""
|
|
42
|
+
import copy
|
|
43
|
+
import re
|
|
44
|
+
|
|
45
|
+
from typer.main import get_command_name, solve_typer_info_defaults
|
|
46
|
+
|
|
47
|
+
from .main.core import APP_OPTIONS_WITH_VALUES
|
|
48
|
+
|
|
49
|
+
# Find the command name, skipping the top level's options
|
|
50
|
+
takes_value = {
|
|
51
|
+
flag for flags in APP_OPTIONS_WITH_VALUES.values() for flag in flags
|
|
52
|
+
}
|
|
53
|
+
i = 0
|
|
54
|
+
while i < len(args) and args[i].startswith("-") and top:
|
|
55
|
+
i += 2 if args[i] in takes_value else 1
|
|
56
|
+
if i >= len(args) or args[i].startswith("-"):
|
|
57
|
+
return app
|
|
58
|
+
name, rest = args[i], args[i + 1 :]
|
|
59
|
+
|
|
60
|
+
def names(spec: str | None) -> list[str]:
|
|
61
|
+
return re.split(r" ?[,|] ?", spec) if spec else []
|
|
62
|
+
|
|
63
|
+
narrowed = copy.copy(app)
|
|
64
|
+
for cmd in app.registered_commands:
|
|
65
|
+
default = cmd.callback and get_command_name(cmd.callback.__name__)
|
|
66
|
+
if name in names(cmd.name or default):
|
|
67
|
+
narrowed.registered_commands = [cmd]
|
|
68
|
+
narrowed.registered_groups = []
|
|
69
|
+
return narrowed
|
|
70
|
+
for group in app.registered_groups:
|
|
71
|
+
sub_app = group.typer_instance
|
|
72
|
+
if sub_app and name in names(solve_typer_info_defaults(group).name):
|
|
73
|
+
group = copy.copy(group)
|
|
74
|
+
group.typer_instance = _only_invoked(sub_app, rest, top=False)
|
|
75
|
+
narrowed.registered_commands = []
|
|
76
|
+
narrowed.registered_groups = [group]
|
|
77
|
+
return narrowed
|
|
78
|
+
return app
|
|
15
79
|
|
|
16
80
|
|
|
17
81
|
def _maybe_exec_with_version() -> None:
|