runnable 0.12.2__tar.gz → 0.12.3__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. runnable-0.12.3/PKG-INFO +270 -0
  2. runnable-0.12.3/README.md +234 -0
  3. {runnable-0.12.2 → runnable-0.12.3}/pyproject.toml +34 -34
  4. {runnable-0.12.2 → runnable-0.12.3}/runnable/sdk.py +150 -101
  5. runnable-0.12.2/PKG-INFO +0 -453
  6. runnable-0.12.2/README.md +0 -417
  7. {runnable-0.12.2 → runnable-0.12.3}/LICENSE +0 -0
  8. {runnable-0.12.2 → runnable-0.12.3}/runnable/__init__.py +0 -0
  9. {runnable-0.12.2 → runnable-0.12.3}/runnable/catalog.py +0 -0
  10. {runnable-0.12.2 → runnable-0.12.3}/runnable/cli.py +0 -0
  11. {runnable-0.12.2 → runnable-0.12.3}/runnable/context.py +0 -0
  12. {runnable-0.12.2 → runnable-0.12.3}/runnable/datastore.py +0 -0
  13. {runnable-0.12.2 → runnable-0.12.3}/runnable/defaults.py +0 -0
  14. {runnable-0.12.2 → runnable-0.12.3}/runnable/entrypoints.py +0 -0
  15. {runnable-0.12.2 → runnable-0.12.3}/runnable/exceptions.py +0 -0
  16. {runnable-0.12.2 → runnable-0.12.3}/runnable/executor.py +0 -0
  17. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/__init__.py +0 -0
  18. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/catalog/__init__.py +0 -0
  19. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/catalog/file_system/__init__.py +0 -0
  20. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/catalog/file_system/implementation.py +0 -0
  21. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/catalog/k8s_pvc/__init__.py +0 -0
  22. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/catalog/k8s_pvc/implementation.py +0 -0
  23. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/catalog/k8s_pvc/integration.py +0 -0
  24. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/__init__.py +0 -0
  25. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/argo/__init__.py +0 -0
  26. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/argo/implementation.py +0 -0
  27. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/argo/specification.yaml +0 -0
  28. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/k8s_job/__init__.py +0 -0
  29. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/k8s_job/implementation_FF.py +0 -0
  30. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/k8s_job/integration_FF.py +0 -0
  31. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/local/__init__.py +0 -0
  32. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/local/implementation.py +0 -0
  33. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/local_container/__init__.py +0 -0
  34. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/local_container/implementation.py +0 -0
  35. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/mocked/__init__.py +0 -0
  36. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/mocked/implementation.py +0 -0
  37. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/retry/__init__.py +0 -0
  38. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/executor/retry/implementation.py +0 -0
  39. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/nodes.py +0 -0
  40. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/__init__.py +0 -0
  41. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/chunked_file_system/__init__.py +0 -0
  42. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/chunked_file_system/implementation.py +0 -0
  43. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/chunked_k8s_pvc/__init__.py +0 -0
  44. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/chunked_k8s_pvc/implementation.py +0 -0
  45. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/chunked_k8s_pvc/integration.py +0 -0
  46. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/db/implementation_FF.py +0 -0
  47. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/db/integration_FF.py +0 -0
  48. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/file_system/__init__.py +0 -0
  49. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/file_system/implementation.py +0 -0
  50. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/generic_chunked.py +0 -0
  51. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/k8s_pvc/__init__.py +0 -0
  52. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/k8s_pvc/implementation.py +0 -0
  53. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/run_log_store/k8s_pvc/integration.py +0 -0
  54. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/secrets/__init__.py +0 -0
  55. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/secrets/dotenv/__init__.py +0 -0
  56. {runnable-0.12.2 → runnable-0.12.3}/runnable/extensions/secrets/dotenv/implementation.py +0 -0
  57. {runnable-0.12.2 → runnable-0.12.3}/runnable/graph.py +0 -0
  58. {runnable-0.12.2 → runnable-0.12.3}/runnable/integration.py +0 -0
  59. {runnable-0.12.2 → runnable-0.12.3}/runnable/names.py +0 -0
  60. {runnable-0.12.2 → runnable-0.12.3}/runnable/nodes.py +0 -0
  61. {runnable-0.12.2 → runnable-0.12.3}/runnable/parameters.py +0 -0
  62. {runnable-0.12.2 → runnable-0.12.3}/runnable/pickler.py +0 -0
  63. {runnable-0.12.2 → runnable-0.12.3}/runnable/secrets.py +0 -0
  64. {runnable-0.12.2 → runnable-0.12.3}/runnable/tasks.py +0 -0
  65. {runnable-0.12.2 → runnable-0.12.3}/runnable/utils.py +0 -0
@@ -0,0 +1,270 @@
1
+ Metadata-Version: 2.1
2
+ Name: runnable
3
+ Version: 0.12.3
4
+ Summary: A Compute agnostic pipelining software
5
+ Home-page: https://github.com/vijayvammi/runnable
6
+ License: Apache-2.0
7
+ Author: Vijay Vammi
8
+ Author-email: mesanthu@gmail.com
9
+ Requires-Python: >=3.9,<3.13
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.9
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Provides-Extra: database
17
+ Provides-Extra: docker
18
+ Provides-Extra: notebook
19
+ Requires-Dist: click
20
+ Requires-Dist: click-plugins (>=1.1.1,<2.0.0)
21
+ Requires-Dist: dill (>=0.3.8,<0.4.0)
22
+ Requires-Dist: docker ; extra == "docker"
23
+ Requires-Dist: mlflow-skinny
24
+ Requires-Dist: ploomber-engine (>=0.0.31,<0.0.32) ; extra == "notebook"
25
+ Requires-Dist: pydantic (>=2.5,<3.0)
26
+ Requires-Dist: rich (>=13.5.2,<14.0.0)
27
+ Requires-Dist: ruamel.yaml
28
+ Requires-Dist: ruamel.yaml.clib
29
+ Requires-Dist: sqlalchemy ; extra == "database"
30
+ Requires-Dist: stevedore (>=3.5.0,<4.0.0)
31
+ Requires-Dist: typing-extensions ; python_version < "3.8"
32
+ Project-URL: Documentation, https://github.com/vijayvammi/runnable
33
+ Project-URL: Repository, https://github.com/vijayvammi/runnable
34
+ Description-Content-Type: text/markdown
35
+
36
+
37
+
38
+
39
+
40
+
41
+ </p>
42
+ <hr style="border:2px dotted orange">
43
+
44
+ <p align="center">
45
+ <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>
46
+ <a href="https://pypi.org/project/runnable/"><img alt="Pypi" src="https://badge.fury.io/py/runnable.svg"></a>
47
+ <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>
48
+ <a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
49
+ <a href="https://github.com/python/mypy"><img alt="MyPy Checked" src="https://www.mypy-lang.org/static/mypy_badge.svg"></a>
50
+ <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">
51
+ </p>
52
+ <hr style="border:2px dotted orange">
53
+
54
+
55
+ [Please check here for complete documentation](https://astrazeneca.github.io/runnable/)
56
+
57
+ ## Example
58
+
59
+ The below data science flavored code is a well-known
60
+ [iris example from scikit-learn](https://scikit-learn.org/stable/auto_examples/linear_model/plot_iris_logistic.html).
61
+
62
+
63
+ ```python
64
+ """
65
+ Example of Logistic regression using scikit-learn
66
+ https://scikit-learn.org/stable/auto_examples/linear_model/plot_iris_logistic.html
67
+ """
68
+
69
+ import matplotlib.pyplot as plt
70
+ import numpy as np
71
+ from sklearn import datasets
72
+ from sklearn.inspection import DecisionBoundaryDisplay
73
+ from sklearn.linear_model import LogisticRegression
74
+
75
+
76
+ def load_data():
77
+ # import some data to play with
78
+ iris = datasets.load_iris()
79
+ X = iris.data[:, :2] # we only take the first two features.
80
+ Y = iris.target
81
+
82
+ return X, Y
83
+
84
+
85
+ def model_fit(X: np.ndarray, Y: np.ndarray, C: float = 1e5):
86
+ logreg = LogisticRegression(C=C)
87
+ logreg.fit(X, Y)
88
+
89
+ return logreg
90
+
91
+
92
+ def generate_plots(X: np.ndarray, Y: np.ndarray, logreg: LogisticRegression):
93
+ _, ax = plt.subplots(figsize=(4, 3))
94
+ DecisionBoundaryDisplay.from_estimator(
95
+ logreg,
96
+ X,
97
+ cmap=plt.cm.Paired,
98
+ ax=ax,
99
+ response_method="predict",
100
+ plot_method="pcolormesh",
101
+ shading="auto",
102
+ xlabel="Sepal length",
103
+ ylabel="Sepal width",
104
+ eps=0.5,
105
+ )
106
+
107
+ # Plot also the training points
108
+ plt.scatter(X[:, 0], X[:, 1], c=Y, edgecolors="k", cmap=plt.cm.Paired)
109
+
110
+ plt.xticks(())
111
+ plt.yticks(())
112
+
113
+ plt.savefig("iris_logistic.png")
114
+
115
+ # TODO: What is the right value?
116
+ return 0.6
117
+
118
+
119
+ ## Without any orchestration
120
+ def main():
121
+ X, Y = load_data()
122
+ logreg = model_fit(X, Y, C=1.0)
123
+ generate_plots(X, Y, logreg)
124
+
125
+
126
+ ## With runnable orchestration
127
+ def runnable_pipeline():
128
+ # The below code can be anywhere
129
+ from runnable import Catalog, Pipeline, PythonTask, metric, pickled
130
+
131
+ # X, Y = load_data()
132
+ load_data_task = PythonTask(
133
+ function=load_data,
134
+ name="load_data",
135
+ returns=[pickled("X"), pickled("Y")], # (1)
136
+ )
137
+
138
+ # logreg = model_fit(X, Y, C=1.0)
139
+ model_fit_task = PythonTask(
140
+ function=model_fit,
141
+ name="model_fit",
142
+ returns=[pickled("logreg")],
143
+ )
144
+
145
+ # generate_plots(X, Y, logreg)
146
+ generate_plots_task = PythonTask(
147
+ function=generate_plots,
148
+ name="generate_plots",
149
+ terminate_with_success=True,
150
+ catalog=Catalog(put=["iris_logistic.png"]), # (2)
151
+ returns=[metric("score")],
152
+ )
153
+
154
+ pipeline = Pipeline(
155
+ steps=[load_data_task, model_fit_task, generate_plots_task],
156
+ ) # (4)
157
+
158
+ pipeline.execute()
159
+
160
+ return pipeline
161
+
162
+
163
+ if __name__ == "__main__":
164
+ # main()
165
+ runnable_pipeline()
166
+
167
+ ```
168
+
169
+
170
+ 1. Return two serialized objects X and Y.
171
+ 2. Store the file `iris_logistic.png` for future reference.
172
+ 3. Define the sequence of tasks.
173
+ 4. Define a pipeline with the tasks
174
+
175
+ The difference between native driver and runnable orchestration:
176
+
177
+ !!! tip inline end "Notebooks and Shell scripts"
178
+
179
+ You can execute notebooks and shell scripts too!!
180
+
181
+ They can be written just as you would want them, *plain old notebooks and scripts*.
182
+
183
+
184
+
185
+
186
+ <div class="annotate" markdown>
187
+
188
+ ```diff
189
+
190
+ - X, Y = load_data()
191
+ +load_data_task = PythonTask(
192
+ + function=load_data,
193
+ + name="load_data",
194
+ + returns=[pickled("X"), pickled("Y")], (1)
195
+ + )
196
+
197
+ -logreg = model_fit(X, Y, C=1.0)
198
+ +model_fit_task = PythonTask(
199
+ + function=model_fit,
200
+ + name="model_fit",
201
+ + returns=[pickled("logreg")],
202
+ + )
203
+
204
+ -generate_plots(X, Y, logreg)
205
+ +generate_plots_task = PythonTask(
206
+ + function=generate_plots,
207
+ + name="generate_plots",
208
+ + terminate_with_success=True,
209
+ + catalog=Catalog(put=["iris_logistic.png"]), (2)
210
+ + )
211
+
212
+
213
+ +pipeline = Pipeline(
214
+ + steps=[load_data_task, model_fit_task, generate_plots_task], (3)
215
+
216
+ ```
217
+ </div>
218
+
219
+
220
+ ---
221
+
222
+ - [x] ```Domain``` code remains completely independent of ```driver``` code.
223
+ - [x] The ```driver``` function has an equivalent and intuitive runnable expression
224
+ - [x] Reproducible by default, runnable stores metadata about code/data/config for every execution.
225
+ - [x] The pipeline is `runnable` in any environment.
226
+
227
+
228
+ ## Documentation
229
+
230
+ [More details about the project and how to use it available here](https://astrazeneca.github.io/runnable/).
231
+
232
+ <hr style="border:2px dotted orange">
233
+
234
+ ## Installation
235
+
236
+ The minimum python version that runnable supports is 3.8
237
+
238
+ ```shell
239
+ pip install runnable
240
+ ```
241
+
242
+ Please look at the [installation guide](https://astrazeneca.github.io/runnable-core/usage)
243
+ for more information.
244
+
245
+
246
+ ## Pipelines can be:
247
+
248
+ ### Linear
249
+
250
+ A simple linear pipeline with tasks either
251
+ [python functions](https://astrazeneca.github.io/runnable-core/concepts/task/#python_functions),
252
+ [notebooks](https://astrazeneca.github.io/runnable-core/concepts/task/#notebooks), or [shell scripts](https://astrazeneca.github.io/runnable-core/concepts/task/#shell)
253
+
254
+ [![](https://mermaid.ink/img/pako:eNpl0bFuwyAQBuBXQVdZTqTESpxMDJ0ytkszhgwnOCcoNo4OaFVZfvcSx20tGSQ4fn0wHB3o1hBIyLJOWGeDFJ3Iq7r90lfkkA9HHfmTUpnX1hFyLvrHzDLl_qB4-1BOOZGGD3TfSikvTDSNFqdj2sT2vBTr9euQlXNWjqycsN2c7UZWFMUE7udwP0L3y6JenNKiyfvz8t8_b-gavT9QJYY0PcDtjeTLptrAChriBq1JzeoeWkG4UkMKZCoN8k2Bcn1yGEN7_HYaZOBIK4h3g4EOFi-MDcgKa59SMja0_P7s_vAJ_Q_YOH6o?type=png)](https://mermaid.live/edit#pako:eNpl0bFuwyAQBuBXQVdZTqTESpxMDJ0ytkszhgwnOCcoNo4OaFVZfvcSx20tGSQ4fn0wHB3o1hBIyLJOWGeDFJ3Iq7r90lfkkA9HHfmTUpnX1hFyLvrHzDLl_qB4-1BOOZGGD3TfSikvTDSNFqdj2sT2vBTr9euQlXNWjqycsN2c7UZWFMUE7udwP0L3y6JenNKiyfvz8t8_b-gavT9QJYY0PcDtjeTLptrAChriBq1JzeoeWkG4UkMKZCoN8k2Bcn1yGEN7_HYaZOBIK4h3g4EOFi-MDcgKa59SMja0_P7s_vAJ_Q_YOH6o)
255
+
256
+ ### [Parallel branches](https://astrazeneca.github.io/runnable-core/concepts/parallel)
257
+
258
+ Execute branches in parallel
259
+
260
+ [![](https://mermaid.ink/img/pako:eNp9k01rwzAMhv-K8S4ZtJCzDzuMLmWwwkh2KMQ7eImShiZ2sB1KKf3vs52PpsWNT7LySHqlyBeciRwwwUUtTtmBSY2-YsopR8MpQUfAdCdBBekWNBpvv6-EkFICzGAtWcUTDW3wYy20M7lr5QGBK2j-anBAkH4M1z6grnjpy17xAiTwDII07jj6HK8-VnVZBspITnpjztyoVkLLJOy3Qfrdm6gQEu2370Io7WLORo84PbRoA_oOl9BBg4UHbHR58UkMWq_fxjrOnhLRx1nH0SgkjlBjh7ekxNKGc0NelDLknhePI8qf7MVNr_31nm1wwNTeM2Ao6pmf-3y3Mp7WlqA7twOnXfKs17zt-6azmim1gQL1A0NKS3EE8hKZE4Yezm3chIVFiFe4AdmwKjdv7mIjKNYHaIBiYsycySPFlF8NxzotkjPPMNGygxXu2pxp2FSslKzBpGC1Ml7IKy3krn_E7i1f_wEayTcn?type=png)](https://mermaid.live/edit#pako:eNp9k01rwzAMhv-K8S4ZtJCzDzuMLmWwwkh2KMQ7eImShiZ2sB1KKf3vs52PpsWNT7LySHqlyBeciRwwwUUtTtmBSY2-YsopR8MpQUfAdCdBBekWNBpvv6-EkFICzGAtWcUTDW3wYy20M7lr5QGBK2j-anBAkH4M1z6grnjpy17xAiTwDII07jj6HK8-VnVZBspITnpjztyoVkLLJOy3Qfrdm6gQEu2370Io7WLORo84PbRoA_oOl9BBg4UHbHR58UkMWq_fxjrOnhLRx1nH0SgkjlBjh7ekxNKGc0NelDLknhePI8qf7MVNr_31nm1wwNTeM2Ao6pmf-3y3Mp7WlqA7twOnXfKs17zt-6azmim1gQL1A0NKS3EE8hKZE4Yezm3chIVFiFe4AdmwKjdv7mIjKNYHaIBiYsycySPFlF8NxzotkjPPMNGygxXu2pxp2FSslKzBpGC1Ml7IKy3krn_E7i1f_wEayTcn)
261
+
262
+ ### [loops or map](https://astrazeneca.github.io/runnable-core/concepts/map)
263
+
264
+ Execute a pipeline over an iterable parameter.
265
+
266
+ [![](https://mermaid.ink/img/pako:eNqVlF1rwjAUhv9KyG4qKNR-3AS2m8nuBgN3Z0Sy5tQG20SSdE7E_76kVVEr2CY3Ied9Tx6Sk3PAmeKACc5LtcsKpi36nlGZFbXciHwfLN79CuWiBLMcEULWGkBSaeosA2OCxbxdXMd89Get2bZASsLiSyuvQE2mJZXIjW27t2rOmQZ3Gp9rD6UjatWnwy7q6zPPukd50WTydmemEiS_QbQ79RwxGoQY9UaMuojRA8TCXexzyHgQZNwbMu5Cxl3IXNX6OWMyiDHpzZh0GZMHjOK3xz2mgxjT3oxplzG9MPp5_nVOhwJjteDwOg3HyFj3L1dCcvh7DUc-iftX18n6Waet1xX8cG908vpKHO6OW7cvkeHm5GR2b3drdvaSGTODHLW37mxabYC8fLgRhlfxpjNdwmEets-Dx7gCXTHBXQc8-D2KbQEVUEzckjO9oZjKo9Ox2qr5XmaYWF3DGNdbzizMBHOVVWGSs9K4XeDCKv3ZttSmsx7_AYa341E?type=png)](https://mermaid.live/edit#pako:eNqVlF1rwjAUhv9KyG4qKNR-3AS2m8nuBgN3Z0Sy5tQG20SSdE7E_76kVVEr2CY3Ied9Tx6Sk3PAmeKACc5LtcsKpi36nlGZFbXciHwfLN79CuWiBLMcEULWGkBSaeosA2OCxbxdXMd89Get2bZASsLiSyuvQE2mJZXIjW27t2rOmQZ3Gp9rD6UjatWnwy7q6zPPukd50WTydmemEiS_QbQ79RwxGoQY9UaMuojRA8TCXexzyHgQZNwbMu5Cxl3IXNX6OWMyiDHpzZh0GZMHjOK3xz2mgxjT3oxplzG9MPp5_nVOhwJjteDwOg3HyFj3L1dCcvh7DUc-iftX18n6Waet1xX8cG908vpKHO6OW7cvkeHm5GR2b3drdvaSGTODHLW37mxabYC8fLgRhlfxpjNdwmEets-Dx7gCXTHBXQc8-D2KbQEVUEzckjO9oZjKo9Ox2qr5XmaYWF3DGNdbzizMBHOVVWGSs9K4XeDCKv3ZttSmsx7_AYa341E)
267
+
268
+ ### [Arbitrary nesting](https://astrazeneca.github.io/runnable-core/concepts/nesting/)
269
+ Any nesting of parallel within map and so on.
270
+
@@ -0,0 +1,234 @@
1
+
2
+
3
+
4
+
5
+
6
+ </p>
7
+ <hr style="border:2px dotted orange">
8
+
9
+ <p align="center">
10
+ <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>
11
+ <a href="https://pypi.org/project/runnable/"><img alt="Pypi" src="https://badge.fury.io/py/runnable.svg"></a>
12
+ <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>
13
+ <a href="https://github.com/psf/black"><img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
14
+ <a href="https://github.com/python/mypy"><img alt="MyPy Checked" src="https://www.mypy-lang.org/static/mypy_badge.svg"></a>
15
+ <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">
16
+ </p>
17
+ <hr style="border:2px dotted orange">
18
+
19
+
20
+ [Please check here for complete documentation](https://astrazeneca.github.io/runnable/)
21
+
22
+ ## Example
23
+
24
+ The below data science flavored code is a well-known
25
+ [iris example from scikit-learn](https://scikit-learn.org/stable/auto_examples/linear_model/plot_iris_logistic.html).
26
+
27
+
28
+ ```python
29
+ """
30
+ Example of Logistic regression using scikit-learn
31
+ https://scikit-learn.org/stable/auto_examples/linear_model/plot_iris_logistic.html
32
+ """
33
+
34
+ import matplotlib.pyplot as plt
35
+ import numpy as np
36
+ from sklearn import datasets
37
+ from sklearn.inspection import DecisionBoundaryDisplay
38
+ from sklearn.linear_model import LogisticRegression
39
+
40
+
41
+ def load_data():
42
+ # import some data to play with
43
+ iris = datasets.load_iris()
44
+ X = iris.data[:, :2] # we only take the first two features.
45
+ Y = iris.target
46
+
47
+ return X, Y
48
+
49
+
50
+ def model_fit(X: np.ndarray, Y: np.ndarray, C: float = 1e5):
51
+ logreg = LogisticRegression(C=C)
52
+ logreg.fit(X, Y)
53
+
54
+ return logreg
55
+
56
+
57
+ def generate_plots(X: np.ndarray, Y: np.ndarray, logreg: LogisticRegression):
58
+ _, ax = plt.subplots(figsize=(4, 3))
59
+ DecisionBoundaryDisplay.from_estimator(
60
+ logreg,
61
+ X,
62
+ cmap=plt.cm.Paired,
63
+ ax=ax,
64
+ response_method="predict",
65
+ plot_method="pcolormesh",
66
+ shading="auto",
67
+ xlabel="Sepal length",
68
+ ylabel="Sepal width",
69
+ eps=0.5,
70
+ )
71
+
72
+ # Plot also the training points
73
+ plt.scatter(X[:, 0], X[:, 1], c=Y, edgecolors="k", cmap=plt.cm.Paired)
74
+
75
+ plt.xticks(())
76
+ plt.yticks(())
77
+
78
+ plt.savefig("iris_logistic.png")
79
+
80
+ # TODO: What is the right value?
81
+ return 0.6
82
+
83
+
84
+ ## Without any orchestration
85
+ def main():
86
+ X, Y = load_data()
87
+ logreg = model_fit(X, Y, C=1.0)
88
+ generate_plots(X, Y, logreg)
89
+
90
+
91
+ ## With runnable orchestration
92
+ def runnable_pipeline():
93
+ # The below code can be anywhere
94
+ from runnable import Catalog, Pipeline, PythonTask, metric, pickled
95
+
96
+ # X, Y = load_data()
97
+ load_data_task = PythonTask(
98
+ function=load_data,
99
+ name="load_data",
100
+ returns=[pickled("X"), pickled("Y")], # (1)
101
+ )
102
+
103
+ # logreg = model_fit(X, Y, C=1.0)
104
+ model_fit_task = PythonTask(
105
+ function=model_fit,
106
+ name="model_fit",
107
+ returns=[pickled("logreg")],
108
+ )
109
+
110
+ # generate_plots(X, Y, logreg)
111
+ generate_plots_task = PythonTask(
112
+ function=generate_plots,
113
+ name="generate_plots",
114
+ terminate_with_success=True,
115
+ catalog=Catalog(put=["iris_logistic.png"]), # (2)
116
+ returns=[metric("score")],
117
+ )
118
+
119
+ pipeline = Pipeline(
120
+ steps=[load_data_task, model_fit_task, generate_plots_task],
121
+ ) # (4)
122
+
123
+ pipeline.execute()
124
+
125
+ return pipeline
126
+
127
+
128
+ if __name__ == "__main__":
129
+ # main()
130
+ runnable_pipeline()
131
+
132
+ ```
133
+
134
+
135
+ 1. Return two serialized objects X and Y.
136
+ 2. Store the file `iris_logistic.png` for future reference.
137
+ 3. Define the sequence of tasks.
138
+ 4. Define a pipeline with the tasks
139
+
140
+ The difference between native driver and runnable orchestration:
141
+
142
+ !!! tip inline end "Notebooks and Shell scripts"
143
+
144
+ You can execute notebooks and shell scripts too!!
145
+
146
+ They can be written just as you would want them, *plain old notebooks and scripts*.
147
+
148
+
149
+
150
+
151
+ <div class="annotate" markdown>
152
+
153
+ ```diff
154
+
155
+ - X, Y = load_data()
156
+ +load_data_task = PythonTask(
157
+ + function=load_data,
158
+ + name="load_data",
159
+ + returns=[pickled("X"), pickled("Y")], (1)
160
+ + )
161
+
162
+ -logreg = model_fit(X, Y, C=1.0)
163
+ +model_fit_task = PythonTask(
164
+ + function=model_fit,
165
+ + name="model_fit",
166
+ + returns=[pickled("logreg")],
167
+ + )
168
+
169
+ -generate_plots(X, Y, logreg)
170
+ +generate_plots_task = PythonTask(
171
+ + function=generate_plots,
172
+ + name="generate_plots",
173
+ + terminate_with_success=True,
174
+ + catalog=Catalog(put=["iris_logistic.png"]), (2)
175
+ + )
176
+
177
+
178
+ +pipeline = Pipeline(
179
+ + steps=[load_data_task, model_fit_task, generate_plots_task], (3)
180
+
181
+ ```
182
+ </div>
183
+
184
+
185
+ ---
186
+
187
+ - [x] ```Domain``` code remains completely independent of ```driver``` code.
188
+ - [x] The ```driver``` function has an equivalent and intuitive runnable expression
189
+ - [x] Reproducible by default, runnable stores metadata about code/data/config for every execution.
190
+ - [x] The pipeline is `runnable` in any environment.
191
+
192
+
193
+ ## Documentation
194
+
195
+ [More details about the project and how to use it available here](https://astrazeneca.github.io/runnable/).
196
+
197
+ <hr style="border:2px dotted orange">
198
+
199
+ ## Installation
200
+
201
+ The minimum python version that runnable supports is 3.8
202
+
203
+ ```shell
204
+ pip install runnable
205
+ ```
206
+
207
+ Please look at the [installation guide](https://astrazeneca.github.io/runnable-core/usage)
208
+ for more information.
209
+
210
+
211
+ ## Pipelines can be:
212
+
213
+ ### Linear
214
+
215
+ A simple linear pipeline with tasks either
216
+ [python functions](https://astrazeneca.github.io/runnable-core/concepts/task/#python_functions),
217
+ [notebooks](https://astrazeneca.github.io/runnable-core/concepts/task/#notebooks), or [shell scripts](https://astrazeneca.github.io/runnable-core/concepts/task/#shell)
218
+
219
+ [![](https://mermaid.ink/img/pako:eNpl0bFuwyAQBuBXQVdZTqTESpxMDJ0ytkszhgwnOCcoNo4OaFVZfvcSx20tGSQ4fn0wHB3o1hBIyLJOWGeDFJ3Iq7r90lfkkA9HHfmTUpnX1hFyLvrHzDLl_qB4-1BOOZGGD3TfSikvTDSNFqdj2sT2vBTr9euQlXNWjqycsN2c7UZWFMUE7udwP0L3y6JenNKiyfvz8t8_b-gavT9QJYY0PcDtjeTLptrAChriBq1JzeoeWkG4UkMKZCoN8k2Bcn1yGEN7_HYaZOBIK4h3g4EOFi-MDcgKa59SMja0_P7s_vAJ_Q_YOH6o?type=png)](https://mermaid.live/edit#pako:eNpl0bFuwyAQBuBXQVdZTqTESpxMDJ0ytkszhgwnOCcoNo4OaFVZfvcSx20tGSQ4fn0wHB3o1hBIyLJOWGeDFJ3Iq7r90lfkkA9HHfmTUpnX1hFyLvrHzDLl_qB4-1BOOZGGD3TfSikvTDSNFqdj2sT2vBTr9euQlXNWjqycsN2c7UZWFMUE7udwP0L3y6JenNKiyfvz8t8_b-gavT9QJYY0PcDtjeTLptrAChriBq1JzeoeWkG4UkMKZCoN8k2Bcn1yGEN7_HYaZOBIK4h3g4EOFi-MDcgKa59SMja0_P7s_vAJ_Q_YOH6o)
220
+
221
+ ### [Parallel branches](https://astrazeneca.github.io/runnable-core/concepts/parallel)
222
+
223
+ Execute branches in parallel
224
+
225
+ [![](https://mermaid.ink/img/pako:eNp9k01rwzAMhv-K8S4ZtJCzDzuMLmWwwkh2KMQ7eImShiZ2sB1KKf3vs52PpsWNT7LySHqlyBeciRwwwUUtTtmBSY2-YsopR8MpQUfAdCdBBekWNBpvv6-EkFICzGAtWcUTDW3wYy20M7lr5QGBK2j-anBAkH4M1z6grnjpy17xAiTwDII07jj6HK8-VnVZBspITnpjztyoVkLLJOy3Qfrdm6gQEu2370Io7WLORo84PbRoA_oOl9BBg4UHbHR58UkMWq_fxjrOnhLRx1nH0SgkjlBjh7ekxNKGc0NelDLknhePI8qf7MVNr_31nm1wwNTeM2Ao6pmf-3y3Mp7WlqA7twOnXfKs17zt-6azmim1gQL1A0NKS3EE8hKZE4Yezm3chIVFiFe4AdmwKjdv7mIjKNYHaIBiYsycySPFlF8NxzotkjPPMNGygxXu2pxp2FSslKzBpGC1Ml7IKy3krn_E7i1f_wEayTcn?type=png)](https://mermaid.live/edit#pako:eNp9k01rwzAMhv-K8S4ZtJCzDzuMLmWwwkh2KMQ7eImShiZ2sB1KKf3vs52PpsWNT7LySHqlyBeciRwwwUUtTtmBSY2-YsopR8MpQUfAdCdBBekWNBpvv6-EkFICzGAtWcUTDW3wYy20M7lr5QGBK2j-anBAkH4M1z6grnjpy17xAiTwDII07jj6HK8-VnVZBspITnpjztyoVkLLJOy3Qfrdm6gQEu2370Io7WLORo84PbRoA_oOl9BBg4UHbHR58UkMWq_fxjrOnhLRx1nH0SgkjlBjh7ekxNKGc0NelDLknhePI8qf7MVNr_31nm1wwNTeM2Ao6pmf-3y3Mp7WlqA7twOnXfKs17zt-6azmim1gQL1A0NKS3EE8hKZE4Yezm3chIVFiFe4AdmwKjdv7mIjKNYHaIBiYsycySPFlF8NxzotkjPPMNGygxXu2pxp2FSslKzBpGC1Ml7IKy3krn_E7i1f_wEayTcn)
226
+
227
+ ### [loops or map](https://astrazeneca.github.io/runnable-core/concepts/map)
228
+
229
+ Execute a pipeline over an iterable parameter.
230
+
231
+ [![](https://mermaid.ink/img/pako:eNqVlF1rwjAUhv9KyG4qKNR-3AS2m8nuBgN3Z0Sy5tQG20SSdE7E_76kVVEr2CY3Ied9Tx6Sk3PAmeKACc5LtcsKpi36nlGZFbXciHwfLN79CuWiBLMcEULWGkBSaeosA2OCxbxdXMd89Get2bZASsLiSyuvQE2mJZXIjW27t2rOmQZ3Gp9rD6UjatWnwy7q6zPPukd50WTydmemEiS_QbQ79RwxGoQY9UaMuojRA8TCXexzyHgQZNwbMu5Cxl3IXNX6OWMyiDHpzZh0GZMHjOK3xz2mgxjT3oxplzG9MPp5_nVOhwJjteDwOg3HyFj3L1dCcvh7DUc-iftX18n6Waet1xX8cG908vpKHO6OW7cvkeHm5GR2b3drdvaSGTODHLW37mxabYC8fLgRhlfxpjNdwmEets-Dx7gCXTHBXQc8-D2KbQEVUEzckjO9oZjKo9Ox2qr5XmaYWF3DGNdbzizMBHOVVWGSs9K4XeDCKv3ZttSmsx7_AYa341E?type=png)](https://mermaid.live/edit#pako:eNqVlF1rwjAUhv9KyG4qKNR-3AS2m8nuBgN3Z0Sy5tQG20SSdE7E_76kVVEr2CY3Ied9Tx6Sk3PAmeKACc5LtcsKpi36nlGZFbXciHwfLN79CuWiBLMcEULWGkBSaeosA2OCxbxdXMd89Get2bZASsLiSyuvQE2mJZXIjW27t2rOmQZ3Gp9rD6UjatWnwy7q6zPPukd50WTydmemEiS_QbQ79RwxGoQY9UaMuojRA8TCXexzyHgQZNwbMu5Cxl3IXNX6OWMyiDHpzZh0GZMHjOK3xz2mgxjT3oxplzG9MPp5_nVOhwJjteDwOg3HyFj3L1dCcvh7DUc-iftX18n6Waet1xX8cG908vpKHO6OW7cvkeHm5GR2b3drdvaSGTODHLW37mxabYC8fLgRhlfxpjNdwmEets-Dx7gCXTHBXQc8-D2KbQEVUEzckjO9oZjKo9Ox2qr5XmaYWF3DGNdbzizMBHOVVWGSs9K4XeDCKv3ZttSmsx7_AYa341E)
232
+
233
+ ### [Arbitrary nesting](https://astrazeneca.github.io/runnable-core/concepts/nesting/)
234
+ Any nesting of parallel within map and so on.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "runnable"
3
- version = "0.12.2"
3
+ version = "0.12.3"
4
4
  description = "A Compute agnostic pipelining software"
5
5
  authors = ["Vijay Vammi <mesanthu@gmail.com>"]
6
6
  license = "Apache-2.0"
@@ -25,43 +25,12 @@ mlflow-skinny = { version = "*", optional = true }
25
25
  ploomber-engine = "^0.0.31"
26
26
  dill = "^0.3.8"
27
27
 
28
- [tool.poetry.group.docs.dependencies]
29
- mkdocs = "*"
30
- mkdocs-material = "*"
31
- mkdocs-section-index = "^0.3.5"
32
- mkdocstrings = { extras = ["python"], version = "^0.24.0" }
33
- nbconvert = "^7.13.1"
34
- mkdocs-click = "^0.8.1"
35
- tensorflow = "^2.16.1"
36
-
37
- [tool.poetry.group.binary.dependencies]
38
- pyinstaller = "^5.13.2"
39
-
40
- [tool.poetry.group.perf.dependencies]
41
- # Run the performace tests poetry run python -m pyflame -p ./flamegraph.pl runnable/entrypoints.py
42
- pyflame = "^0.3.1"
43
-
44
-
45
- [tool.poetry.group.tutorial.dependencies]
46
- pandas = "^2.2.1"
47
- numpy = "^1.26.4"
48
- scikit-learn = "^1.4.1.post1"
49
- 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" }
50
- matplotlib = "^3.8.3"
51
-
52
-
53
- [tool.poetry.group.release.dependencies]
54
- python-semantic-release = "^9.4.2"
55
-
56
-
57
- [tool.poetry.group.examples.dependencies]
58
- pandas = "^2.2.2"
59
-
60
28
  [tool.poetry.extras]
61
29
  docker = ['docker']
62
30
  notebook = ['ploomber-engine']
63
31
  database = ["sqlalchemy"]
64
32
 
33
+
65
34
  [tool.poetry.group.dev.dependencies]
66
35
  pytest = "*"
67
36
  pytest-cov = "*"
@@ -73,13 +42,44 @@ ruff = "^0.0.259"
73
42
  commit-linter = "^1.0.2"
74
43
  black = "^23.3.0"
75
44
  gitlint = "^0.19.1"
76
- pandas = "^2.2.2"
45
+ pandas = "^2.2.2" # for testing examples
77
46
 
47
+ [tool.poetry.group.release.dependencies]
48
+ python-semantic-release = "^9.4.2"
49
+
50
+ [tool.poetry.group.docs.dependencies]
51
+ mkdocs = "*"
52
+ mkdocs-material = "*"
53
+ mkdocs-section-index = "^0.3.5"
54
+ mkdocstrings = { extras = ["python"], version = "^0.24.0" }
55
+ nbconvert = "^7.13.1"
56
+ mkdocs-click = "^0.8.1"
57
+
58
+ [tool.poetry.group.tutorial.dependencies]
59
+ pandas = "^2.2.1"
60
+ numpy = "^1.26.4"
61
+ scikit-learn = "^1.4.1.post1"
62
+ 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" }
63
+ matplotlib = "^3.8.3"
64
+
65
+
66
+ [tool.poetry.group.compare.dependencies]
67
+ torch = "^2.3.0"
68
+ torchvision = "^0.18.0"
69
+ tensorflow = "^2.16.1"
78
70
 
79
71
  [tool.poetry.scripts]
80
72
  runnable = 'runnable.cli:cli'
81
73
 
82
74
 
75
+ [tool.poetry.group.binary.dependencies]
76
+ pyinstaller = "^5.13.2"
77
+
78
+ [tool.poetry.group.perf.dependencies]
79
+ # Run the performace tests poetry run python -m pyflame -p ./flamegraph.pl runnable/entrypoints.py
80
+ pyflame = "^0.3.1"
81
+
82
+
83
83
  # Plugins for Executors
84
84
  [tool.poetry.plugins."executor"]
85
85
  "local" = "runnable.extensions.executor.local.implementation:LocalExecutor"