runnable 0.12.3__py3-none-any.whl → 0.14.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.
Files changed (64) hide show
  1. runnable/__init__.py +0 -11
  2. runnable/catalog.py +27 -5
  3. runnable/cli.py +122 -26
  4. runnable/datastore.py +71 -35
  5. runnable/defaults.py +0 -1
  6. runnable/entrypoints.py +107 -32
  7. runnable/exceptions.py +6 -2
  8. runnable/executor.py +28 -9
  9. runnable/graph.py +37 -12
  10. runnable/integration.py +7 -2
  11. runnable/nodes.py +15 -17
  12. runnable/parameters.py +27 -8
  13. runnable/pickler.py +1 -1
  14. runnable/sdk.py +101 -33
  15. runnable/secrets.py +3 -1
  16. runnable/tasks.py +246 -34
  17. runnable/utils.py +41 -13
  18. {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info}/METADATA +25 -31
  19. runnable-0.14.0.dist-info/RECORD +24 -0
  20. {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info}/WHEEL +1 -1
  21. runnable-0.14.0.dist-info/entry_points.txt +40 -0
  22. runnable/extensions/__init__.py +0 -0
  23. runnable/extensions/catalog/__init__.py +0 -21
  24. runnable/extensions/catalog/file_system/__init__.py +0 -0
  25. runnable/extensions/catalog/file_system/implementation.py +0 -234
  26. runnable/extensions/catalog/k8s_pvc/__init__.py +0 -0
  27. runnable/extensions/catalog/k8s_pvc/implementation.py +0 -16
  28. runnable/extensions/catalog/k8s_pvc/integration.py +0 -59
  29. runnable/extensions/executor/__init__.py +0 -649
  30. runnable/extensions/executor/argo/__init__.py +0 -0
  31. runnable/extensions/executor/argo/implementation.py +0 -1194
  32. runnable/extensions/executor/argo/specification.yaml +0 -51
  33. runnable/extensions/executor/k8s_job/__init__.py +0 -0
  34. runnable/extensions/executor/k8s_job/implementation_FF.py +0 -259
  35. runnable/extensions/executor/k8s_job/integration_FF.py +0 -69
  36. runnable/extensions/executor/local/__init__.py +0 -0
  37. runnable/extensions/executor/local/implementation.py +0 -71
  38. runnable/extensions/executor/local_container/__init__.py +0 -0
  39. runnable/extensions/executor/local_container/implementation.py +0 -446
  40. runnable/extensions/executor/mocked/__init__.py +0 -0
  41. runnable/extensions/executor/mocked/implementation.py +0 -154
  42. runnable/extensions/executor/retry/__init__.py +0 -0
  43. runnable/extensions/executor/retry/implementation.py +0 -168
  44. runnable/extensions/nodes.py +0 -855
  45. runnable/extensions/run_log_store/__init__.py +0 -0
  46. runnable/extensions/run_log_store/chunked_file_system/__init__.py +0 -0
  47. runnable/extensions/run_log_store/chunked_file_system/implementation.py +0 -111
  48. runnable/extensions/run_log_store/chunked_k8s_pvc/__init__.py +0 -0
  49. runnable/extensions/run_log_store/chunked_k8s_pvc/implementation.py +0 -21
  50. runnable/extensions/run_log_store/chunked_k8s_pvc/integration.py +0 -61
  51. runnable/extensions/run_log_store/db/implementation_FF.py +0 -157
  52. runnable/extensions/run_log_store/db/integration_FF.py +0 -0
  53. runnable/extensions/run_log_store/file_system/__init__.py +0 -0
  54. runnable/extensions/run_log_store/file_system/implementation.py +0 -140
  55. runnable/extensions/run_log_store/generic_chunked.py +0 -557
  56. runnable/extensions/run_log_store/k8s_pvc/__init__.py +0 -0
  57. runnable/extensions/run_log_store/k8s_pvc/implementation.py +0 -21
  58. runnable/extensions/run_log_store/k8s_pvc/integration.py +0 -56
  59. runnable/extensions/secrets/__init__.py +0 -0
  60. runnable/extensions/secrets/dotenv/__init__.py +0 -0
  61. runnable/extensions/secrets/dotenv/implementation.py +0 -100
  62. runnable-0.12.3.dist-info/RECORD +0 -64
  63. runnable-0.12.3.dist-info/entry_points.txt +0 -41
  64. {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info/licenses}/LICENSE +0 -0
runnable/__init__.py CHANGED
@@ -34,14 +34,3 @@ from runnable.sdk import ( # noqa
34
34
 
35
35
  # Needed to disable ploomber telemetry
36
36
  os.environ["PLOOMBER_STATS_ENABLED"] = "false"
37
-
38
- ## TODO: Summary should be a bit better for catalog.
39
- ## If the execution fails, hint them about the retry executor.
40
- # Make the retry executor loose!
41
-
42
- # TODO: Think of model registry as a central place to store models.
43
- # TODO: Implement Sagemaker pipelines as a executor.
44
-
45
-
46
- # TODO: Think of way of generating dag hash without executor configuration
47
- # Try to get a release
runnable/catalog.py CHANGED
@@ -11,6 +11,26 @@ from runnable.datastore import DataCatalog
11
11
  logger = logging.getLogger(defaults.LOGGER_NAME)
12
12
 
13
13
 
14
+ def is_catalog_out_of_sync(
15
+ catalog, synced_catalogs=Optional[List[DataCatalog]]
16
+ ) -> bool:
17
+ """
18
+ Check if the catalog items are out of sync from already cataloged objects.
19
+ If they are, return False.
20
+ If the object does not exist or synced catalog does not exist, return True
21
+ """
22
+ if not synced_catalogs:
23
+ return True # If nothing has been synced in the past
24
+
25
+ for synced_catalog in synced_catalogs:
26
+ if synced_catalog.catalog_relative_path == catalog.catalog_relative_path:
27
+ if synced_catalog.data_hash == catalog.data_hash:
28
+ return False
29
+ return True
30
+
31
+ return True # The object does not exist, sync it
32
+
33
+
14
34
  # --8<-- [start:docs]
15
35
 
16
36
 
@@ -26,8 +46,7 @@ class BaseCatalog(ABC, BaseModel):
26
46
  model_config = ConfigDict(extra="forbid")
27
47
 
28
48
  @abstractmethod
29
- def get_summary(self) -> Dict[str, Any]:
30
- ...
49
+ def get_summary(self) -> Dict[str, Any]: ...
31
50
 
32
51
  @property
33
52
  def _context(self):
@@ -38,7 +57,9 @@ class BaseCatalog(ABC, BaseModel):
38
57
  return defaults.COMPUTE_DATA_FOLDER
39
58
 
40
59
  @abstractmethod
41
- def get(self, name: str, run_id: str, compute_data_folder: str = "", **kwargs) -> List[DataCatalog]:
60
+ def get(
61
+ self, name: str, run_id: str, compute_data_folder: str = "", **kwargs
62
+ ) -> List[DataCatalog]:
42
63
  """
43
64
  Get the catalog item by 'name' for the 'run id' and store it in compute data folder.
44
65
 
@@ -119,7 +140,9 @@ class DoNothingCatalog(BaseCatalog):
119
140
  def get_summary(self) -> Dict[str, Any]:
120
141
  return {}
121
142
 
122
- def get(self, name: str, run_id: str, compute_data_folder: str = "", **kwargs) -> List[DataCatalog]:
143
+ def get(
144
+ self, name: str, run_id: str, compute_data_folder: str = "", **kwargs
145
+ ) -> List[DataCatalog]:
123
146
  """
124
147
  Does nothing
125
148
  """
@@ -145,4 +168,3 @@ class DoNothingCatalog(BaseCatalog):
145
168
  Does nothing
146
169
  """
147
170
  logger.info("Using a do-nothing catalog, doing nothing while sync between runs")
148
- ...
runnable/cli.py CHANGED
@@ -22,9 +22,13 @@ def cli():
22
22
 
23
23
 
24
24
  @cli.command("execute", short_help="Execute/translate a pipeline")
25
- @click.option("-f", "--file", default="pipeline.yaml", help="The pipeline definition file", show_default=True)
25
+ @click.argument("filename")
26
26
  @click.option(
27
- "-c", "--config-file", default=None, help="config file, in yaml, to be used for the run", show_default=True
27
+ "-c",
28
+ "--config-file",
29
+ default=None,
30
+ help="config file, in yaml, to be used for the run",
31
+ show_default=True,
28
32
  )
29
33
  @click.option(
30
34
  "-p",
@@ -41,8 +45,12 @@ def cli():
41
45
  type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
42
46
  )
43
47
  @click.option("--tag", default="", help="A tag attached to the run")
44
- @click.option("--run-id", help="An optional run_id, one would be generated if not provided")
45
- def execute(file, config_file, parameters_file, log_level, tag, run_id): # pragma: no cover
48
+ @click.option(
49
+ "--run-id", help="An optional run_id, one would be generated if not provided"
50
+ )
51
+ def execute(
52
+ filename, config_file, parameters_file, log_level, tag, run_id
53
+ ): # pragma: no cover
46
54
  """
47
55
  Execute a pipeline
48
56
 
@@ -64,20 +72,35 @@ def execute(file, config_file, parameters_file, log_level, tag, run_id): # prag
64
72
 
65
73
  entrypoints.execute(
66
74
  configuration_file=config_file,
67
- pipeline_file=file,
75
+ pipeline_file=filename,
68
76
  tag=tag,
69
77
  run_id=run_id,
70
78
  parameters_file=parameters_file,
71
79
  )
72
80
 
73
81
 
74
- @cli.command("execute_single_node", short_help="Internal entry point to execute a single node", hidden=True)
82
+ @cli.command(
83
+ "execute_single_node",
84
+ short_help="Internal entry point to execute a single node",
85
+ hidden=True,
86
+ )
75
87
  @click.argument("run_id")
76
88
  @click.argument("step_name")
77
- @click.option("--map-variable", default="", help="The map variable dictionary in str", show_default=True)
78
- @click.option("-f", "--file", default="", help="The pipeline definition file", show_default=True)
79
89
  @click.option(
80
- "-c", "--config-file", default=None, help="config file, in yaml, to be used for the run", show_default=True
90
+ "--map-variable",
91
+ default="",
92
+ help="The map variable dictionary in str",
93
+ show_default=True,
94
+ )
95
+ @click.option(
96
+ "-f", "--file", default="", help="The pipeline definition file", show_default=True
97
+ )
98
+ @click.option(
99
+ "-c",
100
+ "--config-file",
101
+ default=None,
102
+ help="config file, in yaml, to be used for the run",
103
+ show_default=True,
81
104
  )
82
105
  @click.option(
83
106
  "-p",
@@ -94,7 +117,9 @@ def execute(file, config_file, parameters_file, log_level, tag, run_id): # prag
94
117
  type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
95
118
  )
96
119
  @click.option("--tag", default="", help="A tag attached to the run")
97
- def execute_single_node(run_id, step_name, map_variable, file, config_file, parameters_file, log_level, tag):
120
+ def execute_single_node(
121
+ run_id, step_name, map_variable, file, config_file, parameters_file, log_level, tag
122
+ ):
98
123
  """
99
124
  Internal entrypoint for runnable to execute a single node.
100
125
 
@@ -119,7 +144,11 @@ def execute_single_node(run_id, step_name, map_variable, file, config_file, para
119
144
  @click.argument("filename")
120
145
  @click.option("--entrypoint", default=defaults.ENTRYPOINT.USER.value, hidden=True)
121
146
  @click.option(
122
- "-c", "--config-file", default=None, help="config file, in yaml, to be used for the run", show_default=True
147
+ "-c",
148
+ "--config-file",
149
+ default=None,
150
+ help="config file, in yaml, to be used for the run",
151
+ show_default=True,
123
152
  )
124
153
  @click.option(
125
154
  "-p",
@@ -136,10 +165,20 @@ def execute_single_node(run_id, step_name, map_variable, file, config_file, para
136
165
  type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
137
166
  )
138
167
  @click.option("--data-folder", "-d", default="data/", help="The catalog data folder")
139
- @click.option("--put-in-catalog", "-put", default=None, multiple=True, help="The data to put from the catalog")
140
- @click.option("--notebook-output-path", default="", help="The output path for the notebook")
168
+ @click.option(
169
+ "--put-in-catalog",
170
+ "-put",
171
+ default=None,
172
+ multiple=True,
173
+ help="The data to put from the catalog",
174
+ )
175
+ @click.option(
176
+ "--notebook-output-path", default="", help="The output path for the notebook"
177
+ )
141
178
  @click.option("--tag", help="A tag attached to the run")
142
- @click.option("--run-id", help="An optional run_id, one would be generated if not provided")
179
+ @click.option(
180
+ "--run-id", help="An optional run_id, one would be generated if not provided"
181
+ )
143
182
  def execute_notebook(
144
183
  filename,
145
184
  entrypoint,
@@ -159,7 +198,10 @@ def execute_notebook(
159
198
  The execution plan is unchained.
160
199
  """
161
200
  logger.setLevel(log_level)
162
- catalog_config = {"compute_data_folder": data_folder, "put": list(put_in_catalog) if put_in_catalog else None}
201
+ catalog_config = {
202
+ "compute_data_folder": data_folder,
203
+ "put": list(put_in_catalog) if put_in_catalog else None,
204
+ }
163
205
  if not filename.endswith(".ipynb"):
164
206
  raise Exception("A notebook should always have ipynb as the extension")
165
207
 
@@ -179,7 +221,11 @@ def execute_notebook(
179
221
  @click.argument("command")
180
222
  @click.option("--entrypoint", default=defaults.ENTRYPOINT.USER.value, hidden=True)
181
223
  @click.option(
182
- "-c", "--config-file", default=None, help="config file, in yaml, to be used for the run", show_default=True
224
+ "-c",
225
+ "--config-file",
226
+ default=None,
227
+ help="config file, in yaml, to be used for the run",
228
+ show_default=True,
183
229
  )
184
230
  @click.option(
185
231
  "-p",
@@ -196,11 +242,27 @@ def execute_notebook(
196
242
  type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
197
243
  )
198
244
  @click.option("--data-folder", "-d", default="data/", help="The catalog data folder")
199
- @click.option("--put-in-catalog", "-put", default=None, multiple=True, help="The data to put from the catalog")
245
+ @click.option(
246
+ "--put-in-catalog",
247
+ "-put",
248
+ default=None,
249
+ multiple=True,
250
+ help="The data to put from the catalog",
251
+ )
200
252
  @click.option("--tag", help="A tag attached to the run")
201
- @click.option("--run-id", help="An optional run_id, one would be generated if not provided")
253
+ @click.option(
254
+ "--run-id", help="An optional run_id, one would be generated if not provided"
255
+ )
202
256
  def execute_function(
203
- command, entrypoint, config_file, parameters_file, log_level, data_folder, put_in_catalog, tag, run_id
257
+ command,
258
+ entrypoint,
259
+ config_file,
260
+ parameters_file,
261
+ log_level,
262
+ data_folder,
263
+ put_in_catalog,
264
+ tag,
265
+ run_id,
204
266
  ):
205
267
  """
206
268
  External entry point to execute a python function in isolation.
@@ -209,7 +271,10 @@ def execute_function(
209
271
  The execution plan is unchained.
210
272
  """
211
273
  logger.setLevel(log_level)
212
- catalog_config = {"compute_data_folder": data_folder, "put": list(put_in_catalog) if put_in_catalog else None}
274
+ catalog_config = {
275
+ "compute_data_folder": data_folder,
276
+ "put": list(put_in_catalog) if put_in_catalog else None,
277
+ }
213
278
  entrypoints.execute_function(
214
279
  entrypoint=entrypoint,
215
280
  command=command,
@@ -221,14 +286,35 @@ def execute_function(
221
286
  )
222
287
 
223
288
 
224
- @cli.command("fan", short_help="Internal entry point to fan in or out a composite node", hidden=True)
289
+ @cli.command(
290
+ "fan",
291
+ short_help="Internal entry point to fan in or out a composite node",
292
+ hidden=True,
293
+ )
225
294
  @click.argument("run_id")
226
295
  @click.argument("step_name")
227
- @click.option("-m", "--mode", help="fan in or fan out", required=True, type=click.Choice(["in", "out"]))
228
- @click.option("--map-variable", default="", help="The map variable dictionary in str", show_default=True)
229
- @click.option("-f", "--file", default="", help="The pipeline definition file", show_default=True)
230
296
  @click.option(
231
- "-c", "--config-file", default=None, help="config file, in yaml, to be used for the run", show_default=True
297
+ "-m",
298
+ "--mode",
299
+ help="fan in or fan out",
300
+ required=True,
301
+ type=click.Choice(["in", "out"]),
302
+ )
303
+ @click.option(
304
+ "--map-variable",
305
+ default="",
306
+ help="The map variable dictionary in str",
307
+ show_default=True,
308
+ )
309
+ @click.option(
310
+ "-f", "--file", default="", help="The pipeline definition file", show_default=True
311
+ )
312
+ @click.option(
313
+ "-c",
314
+ "--config-file",
315
+ default=None,
316
+ help="config file, in yaml, to be used for the run",
317
+ show_default=True,
232
318
  )
233
319
  @click.option(
234
320
  "-p",
@@ -245,7 +331,17 @@ def execute_function(
245
331
  type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
246
332
  )
247
333
  @click.option("--tag", default="", help="A tag attached to the run")
248
- def fan(run_id, step_name, mode, map_variable, file, config_file, parameters_file, log_level, tag):
334
+ def fan(
335
+ run_id,
336
+ step_name,
337
+ mode,
338
+ map_variable,
339
+ file,
340
+ config_file,
341
+ parameters_file,
342
+ log_level,
343
+ tag,
344
+ ):
249
345
  """
250
346
  Internal entrypoint for runnable to fan in or out a composite node.
251
347
 
runnable/datastore.py CHANGED
@@ -18,7 +18,6 @@ from typing import (
18
18
 
19
19
  from pydantic import BaseModel, Field, computed_field
20
20
 
21
- import runnable.context as context
22
21
  from runnable import defaults, exceptions
23
22
 
24
23
  logger = logging.getLogger(defaults.LOGGER_NAME)
@@ -56,14 +55,11 @@ class DataCatalog(BaseModel, extra="allow"):
56
55
  return other.name == self.name
57
56
 
58
57
 
59
- """
60
- The theory behind reduced:
61
- parameters returned by steps in map node are only reduced by the end of the map step, fan-in.
62
- If they are accessed within the map step, the value should be the value returned by the step in the map step.
63
-
64
- Once the map state is complete, we can set the reduce to true and have the value as
65
- the reduced value. Its either a list or a custom function return.
66
- """
58
+ # The theory behind reduced:
59
+ # parameters returned by steps in map node are only reduced by the end of the map step, fan-in.
60
+ # If they are accessed within the map step, the value should be the value returned by the step in the map step.
61
+ # Once the map state is complete, we can set the reduce to true and have the value as
62
+ # the reduced value. Its either a list or a custom function return.
67
63
 
68
64
 
69
65
  class JsonParameter(BaseModel):
@@ -125,7 +121,9 @@ class ObjectParameter(BaseModel):
125
121
  os.remove(self.file_name) # Remove after loading
126
122
 
127
123
 
128
- Parameter = Annotated[Union[JsonParameter, ObjectParameter, MetricParameter], Field(discriminator="kind")]
124
+ Parameter = Annotated[
125
+ Union[JsonParameter, ObjectParameter, MetricParameter], Field(discriminator="kind")
126
+ ]
129
127
 
130
128
 
131
129
  class StepAttempt(BaseModel):
@@ -157,8 +155,12 @@ class CodeIdentity(BaseModel, extra="allow"):
157
155
 
158
156
  code_identifier: Optional[str] = "" # GIT sha code or docker image id
159
157
  code_identifier_type: Optional[str] = "" # git or docker
160
- code_identifier_dependable: Optional[bool] = False # If git, checks if the tree is clean.
161
- code_identifier_url: Optional[str] = "" # The git remote url or docker repository url
158
+ code_identifier_dependable: Optional[bool] = (
159
+ False # If git, checks if the tree is clean.
160
+ )
161
+ code_identifier_url: Optional[str] = (
162
+ "" # The git remote url or docker repository url
163
+ )
162
164
  code_identifier_message: Optional[str] = "" # Any optional message
163
165
 
164
166
 
@@ -185,18 +187,28 @@ class StepLog(BaseModel):
185
187
  summary: Dict[str, Any] = {}
186
188
 
187
189
  summary["Name"] = self.internal_name
188
- summary["Input catalog content"] = [dc.name for dc in self.data_catalog if dc.stage == "get"]
190
+ summary["Input catalog content"] = [
191
+ dc.name for dc in self.data_catalog if dc.stage == "get"
192
+ ]
189
193
  summary["Available parameters"] = [
190
- (p, v.description) for attempt in self.attempts for p, v in attempt.input_parameters.items()
194
+ (p, v.description)
195
+ for attempt in self.attempts
196
+ for p, v in attempt.input_parameters.items()
191
197
  ]
192
198
 
193
- summary["Output catalog content"] = [dc.name for dc in self.data_catalog if dc.stage == "put"]
199
+ summary["Output catalog content"] = [
200
+ dc.name for dc in self.data_catalog if dc.stage == "put"
201
+ ]
194
202
  summary["Output parameters"] = [
195
- (p, v.description) for attempt in self.attempts for p, v in attempt.output_parameters.items()
203
+ (p, v.description)
204
+ for attempt in self.attempts
205
+ for p, v in attempt.output_parameters.items()
196
206
  ]
197
207
 
198
208
  summary["Metrics"] = [
199
- (p, v.description) for attempt in self.attempts for p, v in attempt.user_defined_metrics.items()
209
+ (p, v.description)
210
+ for attempt in self.attempts
211
+ for p, v in attempt.user_defined_metrics.items()
200
212
  ]
201
213
 
202
214
  cis = []
@@ -312,10 +324,18 @@ class RunLog(BaseModel):
312
324
  summary["Catalog Location"] = _context.catalog_handler.get_summary()
313
325
  summary["Full Run log present at: "] = _context.run_log_store.get_summary()
314
326
 
315
- run_log = _context.run_log_store.get_run_log_by_id(run_id=_context.run_id, full=True)
327
+ run_log = _context.run_log_store.get_run_log_by_id(
328
+ run_id=_context.run_id, full=True
329
+ )
316
330
 
317
- summary["Final Parameters"] = {p: v.description for p, v in run_log.parameters.items()}
318
- summary["Collected metrics"] = {p: v.description for p, v in run_log.parameters.items() if v.kind == "metric"}
331
+ summary["Final Parameters"] = {
332
+ p: v.description for p, v in run_log.parameters.items()
333
+ }
334
+ summary["Collected metrics"] = {
335
+ p: v.description
336
+ for p, v in run_log.parameters.items()
337
+ if v.kind == "metric"
338
+ }
319
339
 
320
340
  return summary
321
341
 
@@ -338,7 +358,9 @@ class RunLog(BaseModel):
338
358
 
339
359
  return list(set(data_catalogs))
340
360
 
341
- def search_branch_by_internal_name(self, i_name: str) -> Tuple[Union[BranchLog, RunLog], Union[StepLog, None]]:
361
+ def search_branch_by_internal_name(
362
+ self, i_name: str
363
+ ) -> Tuple[Union[BranchLog, RunLog], Union[StepLog, None]]:
342
364
  """
343
365
  Given a branch internal name, search for it in the run log.
344
366
 
@@ -385,7 +407,9 @@ class RunLog(BaseModel):
385
407
 
386
408
  raise exceptions.BranchLogNotFoundError(self.run_id, i_name)
387
409
 
388
- def search_step_by_internal_name(self, i_name: str) -> Tuple[StepLog, Union[BranchLog, None]]:
410
+ def search_step_by_internal_name(
411
+ self, i_name: str
412
+ ) -> Tuple[StepLog, Union[BranchLog, None]]:
389
413
  """
390
414
  Given a steps internal name, search for the step name.
391
415
 
@@ -415,7 +439,9 @@ class RunLog(BaseModel):
415
439
  # Its odd, so we are in brach name
416
440
  current_branch = current_step.branches[".".join(dot_path[: i + 1])] # type: ignore
417
441
  current_steps = current_branch.steps
418
- logger.debug(f"Finding step log for {i_name} in branch: {current_branch}")
442
+ logger.debug(
443
+ f"Finding step log for {i_name} in branch: {current_branch}"
444
+ )
419
445
  else:
420
446
  # Its even, so we are in step, we start here!
421
447
  current_step = current_steps[".".join(dot_path[: i + 1])]
@@ -428,10 +454,6 @@ class RunLog(BaseModel):
428
454
  raise exceptions.StepLogNotFoundError(self.run_id, i_name)
429
455
 
430
456
 
431
- # All outside modules should interact with dataclasses using the RunLogStore to promote extensibility
432
- # If you want to customize dataclass, extend BaseRunLogStore and implement the methods as per the specification
433
-
434
-
435
457
  class BaseRunLogStore(ABC, BaseModel):
436
458
  """
437
459
  The base class of a Run Log Store with many common methods implemented.
@@ -441,8 +463,7 @@ class BaseRunLogStore(ABC, BaseModel):
441
463
  service_type: str = "run_log_store"
442
464
 
443
465
  @abstractmethod
444
- def get_summary(self) -> Dict[str, Any]:
445
- ...
466
+ def get_summary(self) -> Dict[str, Any]: ...
446
467
 
447
468
  @property
448
469
  def _context(self):
@@ -629,7 +650,9 @@ class BaseRunLogStore(ABC, BaseModel):
629
650
  RunLogNotFoundError: If the run log for run_id is not found in the datastore
630
651
  StepLogNotFoundError: If the step log for internal_name is not found in the datastore for run_id
631
652
  """
632
- logger.info(f"{self.service_name} Getting the step log: {internal_name} of {run_id}")
653
+ logger.info(
654
+ f"{self.service_name} Getting the step log: {internal_name} of {run_id}"
655
+ )
633
656
  run_log = self.get_run_log_by_id(run_id=run_id)
634
657
  step_log, _ = run_log.search_step_by_internal_name(internal_name)
635
658
  return step_log
@@ -675,10 +698,14 @@ class BaseRunLogStore(ABC, BaseModel):
675
698
  BranchLog: Uncommitted and initialized with defaults BranchLog object
676
699
  """
677
700
  # Create a new BranchLog
678
- logger.info(f"{self.service_name} Creating a Branch Log : {internal_branch_name}")
701
+ logger.info(
702
+ f"{self.service_name} Creating a Branch Log : {internal_branch_name}"
703
+ )
679
704
  return BranchLog(internal_name=internal_branch_name, status=defaults.CREATED)
680
705
 
681
- def get_branch_log(self, internal_branch_name: str, run_id: str, **kwargs) -> Union[BranchLog, RunLog]:
706
+ def get_branch_log(
707
+ self, internal_branch_name: str, run_id: str, **kwargs
708
+ ) -> Union[BranchLog, RunLog]:
682
709
  """
683
710
  Returns the branch log by the internal branch name for the run id
684
711
 
@@ -697,7 +724,9 @@ class BaseRunLogStore(ABC, BaseModel):
697
724
  branch, _ = run_log.search_branch_by_internal_name(internal_branch_name)
698
725
  return branch
699
726
 
700
- def add_branch_log(self, branch_log: Union[BranchLog, RunLog], run_id: str, **kwargs):
727
+ def add_branch_log(
728
+ self, branch_log: Union[BranchLog, RunLog], run_id: str, **kwargs
729
+ ):
701
730
  """
702
731
  The method should:
703
732
  # Get the run log
@@ -775,7 +804,9 @@ class BufferRunLogstore(BaseRunLogStore):
775
804
  """
776
805
 
777
806
  service_name: str = "buffered"
778
- run_log: Optional[RunLog] = Field(default=None, exclude=True) # For a buffered Run Log, this is the database
807
+ run_log: Optional[RunLog] = Field(
808
+ default=None, exclude=True
809
+ ) # For a buffered Run Log, this is the database
779
810
 
780
811
  def get_summary(self) -> Dict[str, Any]:
781
812
  summary = {"Type": self.service_name, "Location": "Not persisted"}
@@ -826,5 +857,10 @@ class BufferRunLogstore(BaseRunLogStore):
826
857
  # Puts the run log in the db
827
858
  # Raises Exception if not found
828
859
  """
829
- logger.info(f"{self.service_name} Putting the run log in the DB: {run_log.run_id}")
860
+ logger.info(
861
+ f"{self.service_name} Putting the run log in the DB: {run_log.run_id}"
862
+ )
830
863
  self.run_log = run_log
864
+
865
+
866
+ import runnable.context as context # noqa: F401, E402
runnable/defaults.py CHANGED
@@ -33,7 +33,6 @@ class RunnableConfig(TypedDict, total=False):
33
33
  secrets: Optional[ServiceConfig]
34
34
  catalog: Optional[ServiceConfig]
35
35
  executor: Optional[ServiceConfig]
36
- experiment_tracker: Optional[ServiceConfig]
37
36
  pickler: Optional[ServiceConfig]
38
37
 
39
38