runnable 0.23.0__tar.gz → 0.25.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. {runnable-0.23.0 → runnable-0.25.0}/PKG-INFO +1 -1
  2. {runnable-0.23.0 → runnable-0.25.0}/extensions/nodes/nodes.py +4 -0
  3. {runnable-0.23.0 → runnable-0.25.0}/pyproject.toml +1 -1
  4. {runnable-0.23.0 → runnable-0.25.0}/runnable/cli.py +8 -4
  5. {runnable-0.23.0 → runnable-0.25.0}/runnable/graph.py +0 -1
  6. {runnable-0.23.0 → runnable-0.25.0}/runnable/tasks.py +34 -13
  7. {runnable-0.23.0 → runnable-0.25.0}/runnable/utils.py +5 -1
  8. {runnable-0.23.0 → runnable-0.25.0}/.gitignore +0 -0
  9. {runnable-0.23.0 → runnable-0.25.0}/LICENSE +0 -0
  10. {runnable-0.23.0 → runnable-0.25.0}/README.md +0 -0
  11. {runnable-0.23.0 → runnable-0.25.0}/extensions/README.md +0 -0
  12. {runnable-0.23.0 → runnable-0.25.0}/extensions/__init__.py +0 -0
  13. {runnable-0.23.0 → runnable-0.25.0}/extensions/catalog/README.md +0 -0
  14. {runnable-0.23.0 → runnable-0.25.0}/extensions/catalog/file_system.py +0 -0
  15. {runnable-0.23.0 → runnable-0.25.0}/extensions/catalog/pyproject.toml +0 -0
  16. {runnable-0.23.0 → runnable-0.25.0}/extensions/job_executor/README.md +0 -0
  17. {runnable-0.23.0 → runnable-0.25.0}/extensions/job_executor/__init__.py +0 -0
  18. {runnable-0.23.0 → runnable-0.25.0}/extensions/job_executor/k8s.py +0 -0
  19. {runnable-0.23.0 → runnable-0.25.0}/extensions/job_executor/k8s_job_spec.yaml +0 -0
  20. {runnable-0.23.0 → runnable-0.25.0}/extensions/job_executor/local.py +0 -0
  21. {runnable-0.23.0 → runnable-0.25.0}/extensions/job_executor/local_container.py +0 -0
  22. {runnable-0.23.0 → runnable-0.25.0}/extensions/job_executor/pyproject.toml +0 -0
  23. {runnable-0.23.0 → runnable-0.25.0}/extensions/nodes/README.md +0 -0
  24. {runnable-0.23.0 → runnable-0.25.0}/extensions/nodes/pyproject.toml +0 -0
  25. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/README.md +0 -0
  26. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/__init__.py +0 -0
  27. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/argo.py +0 -0
  28. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/local.py +0 -0
  29. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/local_container.py +0 -0
  30. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/mocked.py +0 -0
  31. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/pyproject.toml +0 -0
  32. {runnable-0.23.0 → runnable-0.25.0}/extensions/pipeline_executor/retry.py +0 -0
  33. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/README.md +0 -0
  34. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/__init__.py +0 -0
  35. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/chunked_fs.py +0 -0
  36. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/db/implementation_FF.py +0 -0
  37. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/db/integration_FF.py +0 -0
  38. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/file_system.py +0 -0
  39. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/generic_chunked.py +0 -0
  40. {runnable-0.23.0 → runnable-0.25.0}/extensions/run_log_store/pyproject.toml +0 -0
  41. {runnable-0.23.0 → runnable-0.25.0}/extensions/secrets/README.md +0 -0
  42. {runnable-0.23.0 → runnable-0.25.0}/extensions/secrets/dotenv.py +0 -0
  43. {runnable-0.23.0 → runnable-0.25.0}/extensions/secrets/pyproject.toml +0 -0
  44. {runnable-0.23.0 → runnable-0.25.0}/runnable/__init__.py +0 -0
  45. {runnable-0.23.0 → runnable-0.25.0}/runnable/catalog.py +0 -0
  46. {runnable-0.23.0 → runnable-0.25.0}/runnable/context.py +0 -0
  47. {runnable-0.23.0 → runnable-0.25.0}/runnable/datastore.py +0 -0
  48. {runnable-0.23.0 → runnable-0.25.0}/runnable/defaults.py +0 -0
  49. {runnable-0.23.0 → runnable-0.25.0}/runnable/entrypoints.py +0 -0
  50. {runnable-0.23.0 → runnable-0.25.0}/runnable/exceptions.py +0 -0
  51. {runnable-0.23.0 → runnable-0.25.0}/runnable/executor.py +0 -0
  52. {runnable-0.23.0 → runnable-0.25.0}/runnable/names.py +0 -0
  53. {runnable-0.23.0 → runnable-0.25.0}/runnable/nodes.py +0 -0
  54. {runnable-0.23.0 → runnable-0.25.0}/runnable/parameters.py +0 -0
  55. {runnable-0.23.0 → runnable-0.25.0}/runnable/pickler.py +0 -0
  56. {runnable-0.23.0 → runnable-0.25.0}/runnable/sdk.py +0 -0
  57. {runnable-0.23.0 → runnable-0.25.0}/runnable/secrets.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runnable
3
- Version: 0.23.0
3
+ Version: 0.25.0
4
4
  Summary: Add your description here
5
5
  Author-email: "Vammi, Vijay" <vijay.vammi@astrazeneca.com>
6
6
  License-File: LICENSE
@@ -661,6 +661,10 @@ class MapNode(CompositeNode):
661
661
 
662
662
  self._context.run_log_store.add_step_log(step_log, self._context.run_id)
663
663
 
664
+ # If we failed, we return without any collection
665
+ if not step_log.status == defaults.SUCCESS:
666
+ return
667
+
664
668
  # Apply the reduce function and reduce the returns of the task nodes.
665
669
  # The final value of the parameter is the result of the reduce function.
666
670
  reducer_f = self.get_reducer_function()
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "runnable"
3
- version = "0.23.0"
3
+ version = "0.25.0"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -64,8 +64,9 @@ def execute(
64
64
  tag: Annotated[str, typer.Option(help="A tag attached to the run")] = "",
65
65
  run_id: Annotated[
66
66
  str,
67
- typer.Option(
68
- help="An optional run_id, one would be generated if its not provided"
67
+ typer.Argument(
68
+ envvar=defaults.ENV_RUN_ID,
69
+ help="An optional run_id, one would be generated if its not provided",
69
70
  ),
70
71
  ] = "",
71
72
  ):
@@ -282,8 +283,11 @@ def execute_job(
282
283
  ],
283
284
  run_id: Annotated[
284
285
  str,
285
- typer.Argument(help="An run_id, one would be generated if its not provided"),
286
- ],
286
+ typer.Argument(
287
+ envvar="RUNNABLE_RUN_ID",
288
+ help="An optional run_id, one would be generated if its not provided",
289
+ ),
290
+ ] = "",
287
291
  config_file: Annotated[
288
292
  str,
289
293
  typer.Option(
@@ -76,7 +76,6 @@ class Graph(BaseModel):
76
76
  for _, value in self.nodes.items():
77
77
  if value.internal_name == internal_name:
78
78
  return value
79
- print("graph", internal_name)
80
79
  raise exceptions.NodeNotFoundError(internal_name)
81
80
 
82
81
  def __str__(self): # pragma: no cover
@@ -31,7 +31,26 @@ logger = logging.getLogger(defaults.LOGGER_NAME)
31
31
  logging.getLogger("stevedore").setLevel(logging.CRITICAL)
32
32
 
33
33
 
34
- # TODO: This has to be an extension
34
+ class TeeIO(io.StringIO):
35
+ """
36
+ A custom class to write to the buffer and the output stream at the same time.
37
+ """
38
+
39
+ def __init__(self, output_stream=sys.stdout):
40
+ super().__init__()
41
+ self.output_stream = output_stream
42
+
43
+ def write(self, s):
44
+ super().write(s) # Write to the buffer
45
+ self.output_stream.write(s) # Write to the output stream
46
+
47
+ def flush(self):
48
+ super().flush()
49
+ self.output_stream.flush()
50
+
51
+
52
+ buffer = TeeIO()
53
+ sys.stdout = buffer
35
54
 
36
55
 
37
56
  class TaskReturns(BaseModel):
@@ -152,6 +171,7 @@ class BaseTaskType(BaseModel):
152
171
  key: value
153
172
  for key, value in params.items()
154
173
  if isinstance(value, JsonParameter)
174
+ or isinstance(value, MetricParameter)
155
175
  }
156
176
 
157
177
  parameters_in = copy.deepcopy(params)
@@ -274,7 +294,7 @@ class PythonTaskType(BaseTaskType): # pylint: disable=too-few-public-methods
274
294
  f"Calling {func} from {module} with {filtered_parameters}"
275
295
  )
276
296
 
277
- out_file = io.StringIO()
297
+ out_file = TeeIO()
278
298
  with contextlib.redirect_stdout(out_file):
279
299
  user_set_parameters = f(
280
300
  **filtered_parameters
@@ -284,16 +304,15 @@ class PythonTaskType(BaseTaskType): # pylint: disable=too-few-public-methods
284
304
  raise exceptions.CommandCallError(
285
305
  f"Function call: {self.command} did not succeed.\n"
286
306
  ) from e
287
-
288
- attempt_log.input_parameters = params.copy()
289
-
290
- if map_variable:
291
- attempt_log.input_parameters.update(
292
- {
293
- k: JsonParameter(value=v, kind="json")
294
- for k, v in map_variable.items()
295
- }
296
- )
307
+ finally:
308
+ attempt_log.input_parameters = params.copy()
309
+ if map_variable:
310
+ attempt_log.input_parameters.update(
311
+ {
312
+ k: JsonParameter(value=v, kind="json")
313
+ for k, v in map_variable.items()
314
+ }
315
+ )
297
316
 
298
317
  if self.returns:
299
318
  if not isinstance(user_set_parameters, tuple): # make it a tuple
@@ -448,6 +467,7 @@ class NotebookTaskType(BaseTaskType):
448
467
  ) as params,
449
468
  self.expose_secrets() as _,
450
469
  ):
470
+ attempt_log.input_parameters = params.copy()
451
471
  copy_params = copy.deepcopy(params)
452
472
 
453
473
  if map_variable:
@@ -476,7 +496,7 @@ class NotebookTaskType(BaseTaskType):
476
496
  }
477
497
  kwds.update(ploomber_optional_args)
478
498
 
479
- out_file = io.StringIO()
499
+ out_file = TeeIO()
480
500
  with contextlib.redirect_stdout(out_file):
481
501
  pm.execute_notebook(**kwds)
482
502
  task_console.print(out_file.getvalue())
@@ -635,6 +655,7 @@ class ShellTaskType(BaseTaskType):
635
655
  ) as params:
636
656
  subprocess_env.update({k: v.get_value() for k, v in params.items()})
637
657
 
658
+ attempt_log.input_parameters = params.copy()
638
659
  # Json dumps all runnable environment variables
639
660
  for key, value in subprocess_env.items():
640
661
  if isinstance(value, str):
@@ -77,7 +77,11 @@ def generate_run_id(run_id: str = "") -> str:
77
77
  Returns:
78
78
  str: A generated run_id
79
79
  """
80
- # If we are not provided with a run_id, generate one
80
+ # If we are not provided with a run_id, check env var
81
+ if not run_id:
82
+ run_id = os.environ.get(defaults.ENV_RUN_ID, "")
83
+
84
+ # If both are not given, generate one
81
85
  if not run_id:
82
86
  now = datetime.now()
83
87
  run_id = f"{names.get_random_name()}-{now.hour:02}{now.minute:02}"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes