runnable 0.3.0__tar.gz → 0.7.2__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- {runnable-0.3.0 → runnable-0.7.2}/PKG-INFO +24 -8
- {runnable-0.3.0 → runnable-0.7.2}/README.md +22 -5
- {runnable-0.3.0 → runnable-0.7.2}/pyproject.toml +25 -17
- {runnable-0.3.0 → runnable-0.7.2}/runnable/__init__.py +13 -15
- {runnable-0.3.0 → runnable-0.7.2}/runnable/cli.py +1 -4
- {runnable-0.3.0 → runnable-0.7.2}/runnable/context.py +2 -2
- {runnable-0.3.0 → runnable-0.7.2}/runnable/datastore.py +65 -23
- {runnable-0.3.0 → runnable-0.7.2}/runnable/defaults.py +4 -2
- {runnable-0.3.0 → runnable-0.7.2}/runnable/entrypoints.py +8 -16
- {runnable-0.3.0 → runnable-0.7.2}/runnable/executor.py +3 -44
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/__init__.py +32 -171
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/mocked/implementation.py +4 -59
- runnable-0.7.2/runnable/extensions/executor/retry/implementation.py +158 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/nodes.py +84 -82
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/file_system/implementation.py +0 -2
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/generic_chunked.py +0 -2
- runnable-0.7.2/runnable/extensions/secrets/env_secrets/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/nodes.py +6 -6
- {runnable-0.3.0 → runnable-0.7.2}/runnable/parameters.py +13 -80
- {runnable-0.3.0 → runnable-0.7.2}/runnable/sdk.py +169 -32
- runnable-0.7.2/runnable/tasks.py +466 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/utils.py +0 -15
- runnable-0.3.0/runnable/interaction.py +0 -404
- runnable-0.3.0/runnable/tasks.py +0 -395
- {runnable-0.3.0 → runnable-0.7.2}/LICENSE +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/catalog.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/exceptions.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/experiment_tracker.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/catalog/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/catalog/file_system/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/catalog/file_system/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/catalog/k8s_pvc/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/catalog/k8s_pvc/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/catalog/k8s_pvc/integration.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/argo/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/argo/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/argo/specification.yaml +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/k8s_job/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/k8s_job/implementation_FF.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/k8s_job/integration_FF.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/local/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/local/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/local_container/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/local_container/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/executor/mocked/__init__.py +0 -0
- {runnable-0.3.0/runnable/extensions/experiment_tracker → runnable-0.7.2/runnable/extensions/executor/retry}/__init__.py +0 -0
- {runnable-0.3.0/runnable/extensions/experiment_tracker/mlflow → runnable-0.7.2/runnable/extensions/experiment_tracker}/__init__.py +0 -0
- {runnable-0.3.0/runnable/extensions/run_log_store → runnable-0.7.2/runnable/extensions/experiment_tracker/mlflow}/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/experiment_tracker/mlflow/implementation.py +0 -0
- {runnable-0.3.0/runnable/extensions/run_log_store/chunked_file_system → runnable-0.7.2/runnable/extensions/run_log_store}/__init__.py +0 -0
- {runnable-0.3.0/runnable/extensions/run_log_store/chunked_k8s_pvc → runnable-0.7.2/runnable/extensions/run_log_store/chunked_file_system}/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/chunked_file_system/implementation.py +0 -0
- {runnable-0.3.0/runnable/extensions/run_log_store/file_system → runnable-0.7.2/runnable/extensions/run_log_store/chunked_k8s_pvc}/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/chunked_k8s_pvc/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/chunked_k8s_pvc/integration.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/db/implementation_FF.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/db/integration_FF.py +0 -0
- {runnable-0.3.0/runnable/extensions/run_log_store/k8s_pvc → runnable-0.7.2/runnable/extensions/run_log_store/file_system}/__init__.py +0 -0
- {runnable-0.3.0/runnable/extensions/secrets → runnable-0.7.2/runnable/extensions/run_log_store/k8s_pvc}/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/k8s_pvc/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/run_log_store/k8s_pvc/integration.py +0 -0
- {runnable-0.3.0/runnable/extensions/secrets/dotenv → runnable-0.7.2/runnable/extensions/secrets}/__init__.py +0 -0
- {runnable-0.3.0/runnable/extensions/secrets/env_secrets → runnable-0.7.2/runnable/extensions/secrets/dotenv}/__init__.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/secrets/dotenv/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/extensions/secrets/env_secrets/implementation.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/graph.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/integration.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/names.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/pickler.py +0 -0
- {runnable-0.3.0 → runnable-0.7.2}/runnable/secrets.py +0 -0
@@ -1,15 +1,14 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: runnable
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.7.2
|
4
4
|
Summary: A Compute agnostic pipelining software
|
5
5
|
Home-page: https://github.com/vijayvammi/runnable
|
6
6
|
License: Apache-2.0
|
7
7
|
Author: Vijay Vammi
|
8
8
|
Author-email: mesanthu@gmail.com
|
9
|
-
Requires-Python: >=3.
|
9
|
+
Requires-Python: >=3.9,<3.13
|
10
10
|
Classifier: License :: OSI Approved :: Apache Software License
|
11
11
|
Classifier: Programming Language :: Python :: 3
|
12
|
-
Classifier: Programming Language :: Python :: 3.8
|
13
12
|
Classifier: Programming Language :: Python :: 3.9
|
14
13
|
Classifier: Programming Language :: Python :: 3.10
|
15
14
|
Classifier: Programming Language :: Python :: 3.11
|
@@ -36,22 +35,39 @@ Description-Content-Type: text/markdown
|
|
36
35
|
|
37
36
|
|
38
37
|
|
39
|
-
# Hello from runnable
|
40
38
|
|
41
39
|
|
42
40
|
<p align="center">
|
43
|
-
|
41
|
+
|
42
|
+
,////,
|
43
|
+
/// 6|
|
44
|
+
// _|
|
45
|
+
_/_,-'
|
46
|
+
_.-/'/ \ ,/;,
|
47
|
+
,-' /' \_ \ / _/
|
48
|
+
`\ / _/\ ` /
|
49
|
+
| /, `\_/
|
50
|
+
| \'
|
51
|
+
/\_ /` /\
|
52
|
+
/' /_``--.__/\ `,. / \
|
53
|
+
|_/` `-._ `\/ `\ `.
|
54
|
+
`-.__/' `\ |
|
55
|
+
`\ \
|
56
|
+
`\ \
|
57
|
+
\_\__
|
58
|
+
\___)
|
59
|
+
|
44
60
|
</p>
|
45
61
|
<hr style="border:2px dotted orange">
|
46
62
|
|
47
63
|
<p align="center">
|
48
64
|
<a href="https://pypi.org/project/runnable/"><img alt="python:" src="https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-blue.svg"></a>
|
49
65
|
<a href="https://pypi.org/project/runnable/"><img alt="Pypi" src="https://badge.fury.io/py/runnable.svg"></a>
|
50
|
-
<a href="https://github.com/
|
66
|
+
<a href="https://github.com/vijayvammi/runnable/blob/main/LICENSE"><img alt"License" src="https://img.shields.io/badge/license-Apache%202.0-blue.svg"></a>
|
51
67
|
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
|
52
68
|
<a href="https://github.com/python/mypy"><img alt="MyPy Checked" src="https://www.mypy-lang.org/static/mypy_badge.svg"></a>
|
53
|
-
<a href="https://github.com/
|
54
|
-
<a href="https://github.com/
|
69
|
+
<a href="https://github.com/vijayvammi/runnable/actions/workflows/release.yaml"><img alt="Tests:" src="https://github.com/vijayvammi/runnable/actions/workflows/release.yaml/badge.svg">
|
70
|
+
<a href="https://github.com/vijayvammi/runnable/actions/workflows/docs.yaml"><img alt="Docs:" src="https://github.com/vijayvammi/runnable/actions/workflows/docs.yaml/badge.svg">
|
55
71
|
</p>
|
56
72
|
<hr style="border:2px dotted orange">
|
57
73
|
|
@@ -1,21 +1,38 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
# Hello from runnable
|
4
3
|
|
5
4
|
|
6
5
|
<p align="center">
|
7
|
-
|
6
|
+
|
7
|
+
,////,
|
8
|
+
/// 6|
|
9
|
+
// _|
|
10
|
+
_/_,-'
|
11
|
+
_.-/'/ \ ,/;,
|
12
|
+
,-' /' \_ \ / _/
|
13
|
+
`\ / _/\ ` /
|
14
|
+
| /, `\_/
|
15
|
+
| \'
|
16
|
+
/\_ /` /\
|
17
|
+
/' /_``--.__/\ `,. / \
|
18
|
+
|_/` `-._ `\/ `\ `.
|
19
|
+
`-.__/' `\ |
|
20
|
+
`\ \
|
21
|
+
`\ \
|
22
|
+
\_\__
|
23
|
+
\___)
|
24
|
+
|
8
25
|
</p>
|
9
26
|
<hr style="border:2px dotted orange">
|
10
27
|
|
11
28
|
<p align="center">
|
12
29
|
<a href="https://pypi.org/project/runnable/"><img alt="python:" src="https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10-blue.svg"></a>
|
13
30
|
<a href="https://pypi.org/project/runnable/"><img alt="Pypi" src="https://badge.fury.io/py/runnable.svg"></a>
|
14
|
-
<a href="https://github.com/
|
31
|
+
<a href="https://github.com/vijayvammi/runnable/blob/main/LICENSE"><img alt"License" src="https://img.shields.io/badge/license-Apache%202.0-blue.svg"></a>
|
15
32
|
<a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
|
16
33
|
<a href="https://github.com/python/mypy"><img alt="MyPy Checked" src="https://www.mypy-lang.org/static/mypy_badge.svg"></a>
|
17
|
-
<a href="https://github.com/
|
18
|
-
<a href="https://github.com/
|
34
|
+
<a href="https://github.com/vijayvammi/runnable/actions/workflows/release.yaml"><img alt="Tests:" src="https://github.com/vijayvammi/runnable/actions/workflows/release.yaml/badge.svg">
|
35
|
+
<a href="https://github.com/vijayvammi/runnable/actions/workflows/docs.yaml"><img alt="Docs:" src="https://github.com/vijayvammi/runnable/actions/workflows/docs.yaml/badge.svg">
|
19
36
|
</p>
|
20
37
|
<hr style="border:2px dotted orange">
|
21
38
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "runnable"
|
3
|
-
version = "0.
|
3
|
+
version = "0.7.2"
|
4
4
|
description = "A Compute agnostic pipelining software"
|
5
5
|
authors = ["Vijay Vammi <mesanthu@gmail.com>"]
|
6
6
|
license = "Apache-2.0"
|
@@ -10,25 +10,25 @@ repository = "https://github.com/vijayvammi/runnable"
|
|
10
10
|
documentation = "https://github.com/vijayvammi/runnable"
|
11
11
|
|
12
12
|
[tool.poetry.dependencies]
|
13
|
-
python = ">=3.
|
13
|
+
python = ">=3.9,<3.13"
|
14
14
|
"ruamel.yaml" = "*"
|
15
15
|
"ruamel.yaml.clib" = "*"
|
16
16
|
pydantic = "^2.5"
|
17
17
|
stevedore = "^3.5.0"
|
18
18
|
"click" = "*"
|
19
19
|
click-plugins = "^1.1.1"
|
20
|
-
typing-extensions ={ version= "*", python = "<3.8" }
|
21
|
-
docker ={ version = "*", optional = true }
|
22
|
-
sqlalchemy ={ version = "*", optional = true }
|
20
|
+
typing-extensions = { version = "*", python = "<3.8" }
|
21
|
+
docker = { version = "*", optional = true }
|
22
|
+
sqlalchemy = { version = "*", optional = true }
|
23
23
|
rich = "^13.5.2"
|
24
|
-
mlflow-skinny ={ version = "*", optional = true }
|
24
|
+
mlflow-skinny = { version = "*", optional = true }
|
25
25
|
ploomber-engine = "^0.0.31"
|
26
26
|
|
27
27
|
[tool.poetry.group.docs.dependencies]
|
28
28
|
mkdocs = "*"
|
29
29
|
mkdocs-material = "*"
|
30
30
|
mkdocs-section-index = "^0.3.5"
|
31
|
-
mkdocstrings = {extras = ["python"], version = "^0.24.0"}
|
31
|
+
mkdocstrings = { extras = ["python"], version = "^0.24.0" }
|
32
32
|
nbconvert = "^7.13.1"
|
33
33
|
mkdocs-click = "^0.8.1"
|
34
34
|
|
@@ -39,6 +39,13 @@ pyinstaller = "^5.13.2"
|
|
39
39
|
# Run the performace tests poetry run python -m pyflame -p ./flamegraph.pl runnable/entrypoints.py
|
40
40
|
pyflame = "^0.3.1"
|
41
41
|
|
42
|
+
|
43
|
+
[tool.poetry.group.tutorial.dependencies]
|
44
|
+
pandas = "^2.2.1"
|
45
|
+
numpy = "^1.26.4"
|
46
|
+
scikit-learn = "^1.4.1.post1"
|
47
|
+
en-core-web-sm = { url = "https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1.tar.gz" }
|
48
|
+
|
42
49
|
[tool.poetry.extras]
|
43
50
|
docker = ['docker']
|
44
51
|
notebook = ['ploomber-engine']
|
@@ -59,7 +66,7 @@ gitlint = "^0.19.1"
|
|
59
66
|
|
60
67
|
|
61
68
|
[tool.poetry.scripts]
|
62
|
-
runnable= 'runnable.cli:cli'
|
69
|
+
runnable = 'runnable.cli:cli'
|
63
70
|
|
64
71
|
|
65
72
|
# Plugins for Executors
|
@@ -68,6 +75,7 @@ runnable= 'runnable.cli:cli'
|
|
68
75
|
"local-container" = "runnable.extensions.executor.local_container.implementation:LocalContainerExecutor"
|
69
76
|
"argo" = "runnable.extensions.executor.argo.implementation:ArgoExecutor"
|
70
77
|
"mocked" = "runnable.extensions.executor.mocked.implementation:MockedExecutor"
|
78
|
+
"retry" = "runnable.extensions.executor.retry.implementation:RetryExecutor"
|
71
79
|
|
72
80
|
# Plugins for Catalog
|
73
81
|
[tool.poetry.plugins."catalog"]
|
@@ -122,7 +130,7 @@ line-length = 120
|
|
122
130
|
|
123
131
|
[tool.ruff]
|
124
132
|
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
|
125
|
-
select = ["E", "F","W","I001"]
|
133
|
+
select = ["E", "F", "W", "I001"]
|
126
134
|
|
127
135
|
ignore = []
|
128
136
|
|
@@ -152,12 +160,14 @@ exclude = [
|
|
152
160
|
"dist",
|
153
161
|
"node_modules",
|
154
162
|
"venv",
|
163
|
+
"examples/kubeflow",
|
164
|
+
"examples/tutorials/",
|
155
165
|
]
|
156
166
|
per-file-ignores = {}
|
157
167
|
|
158
168
|
# Builtins
|
159
169
|
|
160
|
-
builtins=["__version__"]
|
170
|
+
builtins = ["__version__"]
|
161
171
|
|
162
172
|
# Same as Black.
|
163
173
|
line-length = 120
|
@@ -204,9 +214,7 @@ branch = true
|
|
204
214
|
|
205
215
|
[tool.coverage.report]
|
206
216
|
# Regexes for lines to exclude from consideration
|
207
|
-
exclude_lines = [
|
208
|
-
"pragma: no cover"
|
209
|
-
]
|
217
|
+
exclude_lines = ["pragma: no cover"]
|
210
218
|
|
211
219
|
include_namespace_packages = true
|
212
220
|
show_missing = true
|
@@ -218,10 +226,10 @@ exclude_also = [
|
|
218
226
|
|
219
227
|
# Don't complain about abstract methods, they aren't run:
|
220
228
|
"@(abc\\.)?abstractmethod",
|
221
|
-
|
229
|
+
]
|
222
230
|
|
223
|
-
omit =[
|
231
|
+
omit = [
|
224
232
|
"runnable/cli.py",
|
225
233
|
"runnable/extensions/executor/demo_renderer/*",
|
226
|
-
"*FF.py"
|
227
|
-
|
234
|
+
"*FF.py",
|
235
|
+
]
|
@@ -9,22 +9,20 @@ from runnable import defaults
|
|
9
9
|
dictConfig(defaults.LOGGING_CONFIG)
|
10
10
|
logger = logging.getLogger(defaults.LOGGER_NAME)
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
track_this,
|
12
|
+
|
13
|
+
from runnable.sdk import (
|
14
|
+
Stub,
|
15
|
+
Pipeline,
|
16
|
+
Parallel,
|
17
|
+
Map,
|
18
|
+
Catalog,
|
19
|
+
Success,
|
20
|
+
Fail,
|
21
|
+
PythonTask,
|
22
|
+
NotebookTask,
|
23
|
+
ShellTask,
|
24
|
+
pickled,
|
26
25
|
) # noqa
|
27
|
-
from runnable.sdk import Stub, Pipeline, Task, Parallel, Map, Catalog, Success, Fail # noqa
|
28
26
|
|
29
27
|
|
30
28
|
# TODO: Think of model registry as a central place to store models.
|
@@ -41,8 +41,7 @@ def cli():
|
|
41
41
|
)
|
42
42
|
@click.option("--tag", default="", help="A tag attached to the run")
|
43
43
|
@click.option("--run-id", help="An optional run_id, one would be generated if not provided")
|
44
|
-
|
45
|
-
def execute(file, config_file, parameters_file, log_level, tag, run_id, use_cached): # pragma: no cover
|
44
|
+
def execute(file, config_file, parameters_file, log_level, tag, run_id): # pragma: no cover
|
46
45
|
"""
|
47
46
|
Execute a pipeline
|
48
47
|
|
@@ -59,7 +58,6 @@ def execute(file, config_file, parameters_file, log_level, tag, run_id, use_cach
|
|
59
58
|
[default: ]
|
60
59
|
--run-id TEXT An optional run_id, one would be generated if not
|
61
60
|
provided
|
62
|
-
--use-cached TEXT Provide the previous run_id to re-run.
|
63
61
|
"""
|
64
62
|
logger.setLevel(log_level)
|
65
63
|
entrypoints.execute(
|
@@ -67,7 +65,6 @@ def execute(file, config_file, parameters_file, log_level, tag, run_id, use_cach
|
|
67
65
|
pipeline_file=file,
|
68
66
|
tag=tag,
|
69
67
|
run_id=run_id,
|
70
|
-
use_cached=use_cached,
|
71
68
|
parameters_file=parameters_file,
|
72
69
|
)
|
73
70
|
|
@@ -7,6 +7,7 @@ from runnable.datastore import BaseRunLogStore
|
|
7
7
|
from runnable.executor import BaseExecutor
|
8
8
|
from runnable.experiment_tracker import BaseExperimentTracker
|
9
9
|
from runnable.graph import Graph
|
10
|
+
from runnable.pickler import BasePickler
|
10
11
|
from runnable.secrets import BaseSecrets
|
11
12
|
|
12
13
|
|
@@ -16,6 +17,7 @@ class Context(BaseModel):
|
|
16
17
|
secrets_handler: SerializeAsAny[BaseSecrets]
|
17
18
|
catalog_handler: SerializeAsAny[BaseCatalog]
|
18
19
|
experiment_tracker: SerializeAsAny[BaseExperimentTracker]
|
20
|
+
pickler: SerializeAsAny[BasePickler]
|
19
21
|
|
20
22
|
pipeline_file: Optional[str] = ""
|
21
23
|
parameters_file: Optional[str] = ""
|
@@ -24,8 +26,6 @@ class Context(BaseModel):
|
|
24
26
|
tag: str = ""
|
25
27
|
run_id: str = ""
|
26
28
|
variables: Dict[str, str] = {}
|
27
|
-
use_cached: bool = False
|
28
|
-
original_run_id: str = ""
|
29
29
|
dag: Optional[Graph] = None
|
30
30
|
dag_hash: str = ""
|
31
31
|
execution_plan: str = ""
|
@@ -1,10 +1,13 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import logging
|
4
|
+
import os
|
4
5
|
from abc import ABC, abstractmethod
|
5
|
-
from
|
6
|
+
from datetime import datetime
|
7
|
+
from typing import Annotated, Any, Dict, List, Literal, Optional, OrderedDict, Tuple, Union
|
6
8
|
|
7
|
-
from pydantic import BaseModel, Field
|
9
|
+
from pydantic import BaseModel, Field, computed_field
|
10
|
+
from typing_extensions import TypeAliasType
|
8
11
|
|
9
12
|
import runnable.context as context
|
10
13
|
from runnable import defaults, exceptions
|
@@ -14,6 +17,11 @@ logger = logging.getLogger(defaults.LOGGER_NAME)
|
|
14
17
|
# Once defined these classes are sealed to any additions unless a default is provided
|
15
18
|
# Breaking this rule might make runnable backwardly incompatible
|
16
19
|
|
20
|
+
JSONType = TypeAliasType(
|
21
|
+
"JSONType",
|
22
|
+
Union[bool, int, float, str, None, List["JSONType"], Dict[str, "JSONType"]], # type: ignore
|
23
|
+
)
|
24
|
+
|
17
25
|
|
18
26
|
class DataCatalog(BaseModel, extra="allow"):
|
19
27
|
"""
|
@@ -42,19 +50,66 @@ class DataCatalog(BaseModel, extra="allow"):
|
|
42
50
|
return other.name == self.name
|
43
51
|
|
44
52
|
|
53
|
+
class JsonParameter(BaseModel):
|
54
|
+
kind: Literal["json"]
|
55
|
+
value: JSONType # type: ignore
|
56
|
+
|
57
|
+
def get_value(self) -> JSONType: # type: ignore
|
58
|
+
return self.value
|
59
|
+
|
60
|
+
|
61
|
+
class ObjectParameter(BaseModel):
|
62
|
+
kind: Literal["object"]
|
63
|
+
value: str # The name of the pickled object
|
64
|
+
|
65
|
+
@computed_field # type: ignore
|
66
|
+
@property
|
67
|
+
def description(self) -> str:
|
68
|
+
return f"Pickled object stored in catalog as: {self.value}"
|
69
|
+
|
70
|
+
@property
|
71
|
+
def file_name(self) -> str:
|
72
|
+
return f"{self.value}{context.run_context.pickler.extension}"
|
73
|
+
|
74
|
+
def get_value(self) -> Any:
|
75
|
+
# Get the pickled object
|
76
|
+
catalog_handler = context.run_context.catalog_handler
|
77
|
+
|
78
|
+
catalog_handler.get(name=self.file_name, run_id=context.run_context.run_id)
|
79
|
+
obj = context.run_context.pickler.load(path=self.file_name)
|
80
|
+
os.remove(self.file_name) # Remove after loading
|
81
|
+
return obj
|
82
|
+
|
83
|
+
def put_object(self, data: Any) -> None:
|
84
|
+
context.run_context.pickler.dump(data=data, path=self.file_name)
|
85
|
+
|
86
|
+
catalog_handler = context.run_context.catalog_handler
|
87
|
+
catalog_handler.put(name=self.file_name, run_id=context.run_context.run_id)
|
88
|
+
os.remove(self.file_name) # Remove after loading
|
89
|
+
|
90
|
+
|
91
|
+
Parameter = Annotated[Union[JsonParameter, ObjectParameter], Field(discriminator="kind")]
|
92
|
+
|
93
|
+
|
45
94
|
class StepAttempt(BaseModel):
|
46
95
|
"""
|
47
96
|
The captured attributes of an Attempt of a step.
|
48
97
|
"""
|
49
98
|
|
50
|
-
attempt_number: int =
|
99
|
+
attempt_number: int = 1
|
51
100
|
start_time: str = ""
|
52
101
|
end_time: str = ""
|
53
|
-
duration: str = "" # end_time - start_time
|
54
102
|
status: str = "FAIL"
|
55
103
|
message: str = ""
|
56
|
-
input_parameters: Dict[str,
|
57
|
-
output_parameters: Dict[str,
|
104
|
+
input_parameters: Dict[str, Parameter] = Field(default_factory=dict)
|
105
|
+
output_parameters: Dict[str, Parameter] = Field(default_factory=dict)
|
106
|
+
|
107
|
+
@property
|
108
|
+
def duration(self):
|
109
|
+
start = datetime.fromisoformat(self.start_time)
|
110
|
+
end = datetime.fromisoformat(self.end_time)
|
111
|
+
|
112
|
+
return str(end - start)
|
58
113
|
|
59
114
|
|
60
115
|
class CodeIdentity(BaseModel, extra="allow"):
|
@@ -169,12 +224,10 @@ class RunLog(BaseModel):
|
|
169
224
|
|
170
225
|
run_id: str
|
171
226
|
dag_hash: Optional[str] = None
|
172
|
-
use_cached: bool = False
|
173
227
|
tag: Optional[str] = ""
|
174
|
-
original_run_id: Optional[str] = ""
|
175
228
|
status: str = defaults.FAIL
|
176
229
|
steps: OrderedDict[str, StepLog] = Field(default_factory=OrderedDict)
|
177
|
-
parameters: Dict[str,
|
230
|
+
parameters: Dict[str, Parameter] = Field(default_factory=dict)
|
178
231
|
run_config: Dict[str, Any] = Field(default_factory=dict)
|
179
232
|
|
180
233
|
def get_data_catalogs_by_stage(self, stage: str = "put") -> List[DataCatalog]:
|
@@ -374,7 +427,7 @@ class BaseRunLogStore(ABC, BaseModel):
|
|
374
427
|
run_log.status = status
|
375
428
|
self.put_run_log(run_log)
|
376
429
|
|
377
|
-
def get_parameters(self, run_id: str, **kwargs) ->
|
430
|
+
def get_parameters(self, run_id: str, **kwargs) -> Dict[str, Parameter]:
|
378
431
|
"""
|
379
432
|
Get the parameters from the Run log defined by the run_id
|
380
433
|
|
@@ -393,7 +446,7 @@ class BaseRunLogStore(ABC, BaseModel):
|
|
393
446
|
run_log = self.get_run_log_by_id(run_id=run_id)
|
394
447
|
return run_log.parameters
|
395
448
|
|
396
|
-
def set_parameters(self, run_id: str, parameters:
|
449
|
+
def set_parameters(self, run_id: str, parameters: Dict[str, Parameter], **kwargs):
|
397
450
|
"""
|
398
451
|
Update the parameters of the Run log with the new parameters
|
399
452
|
|
@@ -580,16 +633,7 @@ class BaseRunLogStore(ABC, BaseModel):
|
|
580
633
|
step.branches[internal_branch_name] = branch_log # type: ignore
|
581
634
|
self.put_run_log(run_log)
|
582
635
|
|
583
|
-
|
584
|
-
"""
|
585
|
-
Returns an uncommitted step attempt log.
|
586
|
-
|
587
|
-
Returns:
|
588
|
-
StepAttempt: An uncommitted step attempt log
|
589
|
-
"""
|
590
|
-
logger.info(f"{self.service_name} Creating an attempt log")
|
591
|
-
return StepAttempt()
|
592
|
-
|
636
|
+
#
|
593
637
|
def create_code_identity(self, **kwargs) -> CodeIdentity:
|
594
638
|
"""
|
595
639
|
Creates an uncommitted Code identity class
|
@@ -659,9 +703,7 @@ class BufferRunLogstore(BaseRunLogStore):
|
|
659
703
|
self.run_log = RunLog(
|
660
704
|
run_id=run_id,
|
661
705
|
dag_hash=dag_hash,
|
662
|
-
use_cached=use_cached,
|
663
706
|
tag=tag,
|
664
|
-
original_run_id=original_run_id,
|
665
707
|
status=status,
|
666
708
|
)
|
667
709
|
return self.run_log
|
@@ -35,12 +35,13 @@ class ServiceConfig(TypedDict):
|
|
35
35
|
config: Mapping[str, Any]
|
36
36
|
|
37
37
|
|
38
|
-
class
|
38
|
+
class RunnableConfig(TypedDict, total=False):
|
39
39
|
run_log_store: Optional[ServiceConfig]
|
40
40
|
secrets: Optional[ServiceConfig]
|
41
41
|
catalog: Optional[ServiceConfig]
|
42
42
|
executor: Optional[ServiceConfig]
|
43
43
|
experiment_tracker: Optional[ServiceConfig]
|
44
|
+
pickler: Optional[ServiceConfig]
|
44
45
|
|
45
46
|
|
46
47
|
TypeMapVariable: TypeAlias = Optional[Dict[str, Union[str, int, float]]]
|
@@ -81,10 +82,11 @@ DEFAULT_CONTAINER_OUTPUT_PARAMETERS = "parameters.json"
|
|
81
82
|
|
82
83
|
# Default services
|
83
84
|
DEFAULT_EXECUTOR = ServiceConfig(type="local", config={})
|
84
|
-
DEFAULT_RUN_LOG_STORE = ServiceConfig(type="
|
85
|
+
DEFAULT_RUN_LOG_STORE = ServiceConfig(type="file-system", config={})
|
85
86
|
DEFAULT_CATALOG = ServiceConfig(type="file-system", config={})
|
86
87
|
DEFAULT_SECRETS = ServiceConfig(type="do-nothing", config={})
|
87
88
|
DEFAULT_EXPERIMENT_TRACKER = ServiceConfig(type="do-nothing", config={})
|
89
|
+
DEFAULT_PICKLER = ServiceConfig(type="pickle", config={})
|
88
90
|
|
89
91
|
# Map state
|
90
92
|
MAP_PLACEHOLDER = "map_variable_placeholder"
|
@@ -9,12 +9,12 @@ from rich import print
|
|
9
9
|
|
10
10
|
import runnable.context as context
|
11
11
|
from runnable import defaults, graph, utils
|
12
|
-
from runnable.defaults import
|
12
|
+
from runnable.defaults import RunnableConfig, ServiceConfig
|
13
13
|
|
14
14
|
logger = logging.getLogger(defaults.LOGGER_NAME)
|
15
15
|
|
16
16
|
|
17
|
-
def get_default_configs() ->
|
17
|
+
def get_default_configs() -> RunnableConfig:
|
18
18
|
"""
|
19
19
|
User can provide extensions as part of their code base, runnable-config.yaml provides the place to put them.
|
20
20
|
"""
|
@@ -37,7 +37,6 @@ def prepare_configurations(
|
|
37
37
|
configuration_file: str = "",
|
38
38
|
pipeline_file: str = "",
|
39
39
|
tag: str = "",
|
40
|
-
use_cached: str = "",
|
41
40
|
parameters_file: str = "",
|
42
41
|
force_local_executor: bool = False,
|
43
42
|
) -> context.Context:
|
@@ -51,7 +50,6 @@ def prepare_configurations(
|
|
51
50
|
pipeline_file (str): The config/dag file
|
52
51
|
run_id (str): The run id of the run.
|
53
52
|
tag (str): If a tag is provided at the run time
|
54
|
-
use_cached (str): Provide the run_id of the older run
|
55
53
|
|
56
54
|
Returns:
|
57
55
|
executor.BaseExecutor : A prepared executor as per the dag/config
|
@@ -64,7 +62,7 @@ def prepare_configurations(
|
|
64
62
|
if configuration_file:
|
65
63
|
templated_configuration = utils.load_yaml(configuration_file) or {}
|
66
64
|
|
67
|
-
configuration:
|
65
|
+
configuration: RunnableConfig = cast(RunnableConfig, templated_configuration)
|
68
66
|
|
69
67
|
# Run log settings, configuration over-rides everything
|
70
68
|
run_log_config: Optional[ServiceConfig] = configuration.get("run_log_store", None)
|
@@ -84,6 +82,10 @@ def prepare_configurations(
|
|
84
82
|
secrets_config = cast(ServiceConfig, runnable_defaults.get("secrets", defaults.DEFAULT_SECRETS))
|
85
83
|
secrets_handler = utils.get_provider_by_name_and_type("secrets", secrets_config)
|
86
84
|
|
85
|
+
# pickler
|
86
|
+
pickler_config = cast(ServiceConfig, runnable_defaults.get("pickler", defaults.DEFAULT_PICKLER))
|
87
|
+
pickler_handler = utils.get_provider_by_name_and_type("pickler", pickler_config)
|
88
|
+
|
87
89
|
# experiment tracker settings, configuration over-rides everything
|
88
90
|
tracker_config: Optional[ServiceConfig] = configuration.get("experiment_tracker", None)
|
89
91
|
if not tracker_config:
|
@@ -107,6 +109,7 @@ def prepare_configurations(
|
|
107
109
|
run_log_store=run_log_store,
|
108
110
|
catalog_handler=catalog_handler,
|
109
111
|
secrets_handler=secrets_handler,
|
112
|
+
pickler=pickler_handler,
|
110
113
|
experiment_tracker=tracker_handler,
|
111
114
|
variables=variables,
|
112
115
|
tag=tag,
|
@@ -141,11 +144,6 @@ def prepare_configurations(
|
|
141
144
|
run_context.pipeline_file = pipeline_file
|
142
145
|
run_context.dag = dag
|
143
146
|
|
144
|
-
run_context.use_cached = False
|
145
|
-
if use_cached:
|
146
|
-
run_context.use_cached = True
|
147
|
-
run_context.original_run_id = use_cached
|
148
|
-
|
149
147
|
context.run_context = run_context
|
150
148
|
|
151
149
|
return run_context
|
@@ -156,7 +154,6 @@ def execute(
|
|
156
154
|
pipeline_file: str,
|
157
155
|
tag: str = "",
|
158
156
|
run_id: str = "",
|
159
|
-
use_cached: str = "",
|
160
157
|
parameters_file: str = "",
|
161
158
|
):
|
162
159
|
# pylint: disable=R0914,R0913
|
@@ -168,10 +165,8 @@ def execute(
|
|
168
165
|
pipeline_file (str): The config/dag file
|
169
166
|
run_id (str): The run id of the run.
|
170
167
|
tag (str): If a tag is provided at the run time
|
171
|
-
use_cached (str): The previous run_id to use.
|
172
168
|
parameters_file (str): The parameters being sent in to the application
|
173
169
|
"""
|
174
|
-
# Re run settings
|
175
170
|
run_id = utils.generate_run_id(run_id=run_id)
|
176
171
|
|
177
172
|
run_context = prepare_configurations(
|
@@ -179,7 +174,6 @@ def execute(
|
|
179
174
|
pipeline_file=pipeline_file,
|
180
175
|
run_id=run_id,
|
181
176
|
tag=tag,
|
182
|
-
use_cached=use_cached,
|
183
177
|
parameters_file=parameters_file,
|
184
178
|
)
|
185
179
|
print("Working with context:")
|
@@ -231,7 +225,6 @@ def execute_single_node(
|
|
231
225
|
pipeline_file=pipeline_file,
|
232
226
|
run_id=run_id,
|
233
227
|
tag=tag,
|
234
|
-
use_cached="",
|
235
228
|
parameters_file=parameters_file,
|
236
229
|
)
|
237
230
|
print("Working with context:")
|
@@ -416,7 +409,6 @@ def fan(
|
|
416
409
|
pipeline_file=pipeline_file,
|
417
410
|
run_id=run_id,
|
418
411
|
tag=tag,
|
419
|
-
use_cached="",
|
420
412
|
parameters_file=parameters_file,
|
421
413
|
)
|
422
414
|
print("Working with context:")
|