runnable 0.11.1__tar.gz → 0.11.2__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.11.1 → runnable-0.11.2}/PKG-INFO +1 -1
  2. {runnable-0.11.1 → runnable-0.11.2}/pyproject.toml +5 -1
  3. {runnable-0.11.1 → runnable-0.11.2}/runnable/__init__.py +1 -0
  4. {runnable-0.11.1 → runnable-0.11.2}/runnable/datastore.py +4 -2
  5. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/catalog/file_system/implementation.py +1 -1
  6. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/nodes.py +4 -4
  7. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/generic_chunked.py +22 -4
  8. {runnable-0.11.1 → runnable-0.11.2}/runnable/tasks.py +21 -3
  9. {runnable-0.11.1 → runnable-0.11.2}/LICENSE +0 -0
  10. {runnable-0.11.1 → runnable-0.11.2}/README.md +0 -0
  11. {runnable-0.11.1 → runnable-0.11.2}/runnable/catalog.py +0 -0
  12. {runnable-0.11.1 → runnable-0.11.2}/runnable/cli.py +0 -0
  13. {runnable-0.11.1 → runnable-0.11.2}/runnable/context.py +0 -0
  14. {runnable-0.11.1 → runnable-0.11.2}/runnable/defaults.py +0 -0
  15. {runnable-0.11.1 → runnable-0.11.2}/runnable/entrypoints.py +0 -0
  16. {runnable-0.11.1 → runnable-0.11.2}/runnable/exceptions.py +0 -0
  17. {runnable-0.11.1 → runnable-0.11.2}/runnable/executor.py +0 -0
  18. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/__init__.py +0 -0
  19. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/catalog/__init__.py +0 -0
  20. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/catalog/file_system/__init__.py +0 -0
  21. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/catalog/k8s_pvc/__init__.py +0 -0
  22. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/catalog/k8s_pvc/implementation.py +0 -0
  23. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/catalog/k8s_pvc/integration.py +0 -0
  24. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/__init__.py +0 -0
  25. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/argo/__init__.py +0 -0
  26. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/argo/implementation.py +0 -0
  27. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/argo/specification.yaml +0 -0
  28. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/k8s_job/__init__.py +0 -0
  29. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/k8s_job/implementation_FF.py +0 -0
  30. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/k8s_job/integration_FF.py +0 -0
  31. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/local/__init__.py +0 -0
  32. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/local/implementation.py +0 -0
  33. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/local_container/__init__.py +0 -0
  34. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/local_container/implementation.py +0 -0
  35. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/mocked/__init__.py +0 -0
  36. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/mocked/implementation.py +0 -0
  37. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/retry/__init__.py +0 -0
  38. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/executor/retry/implementation.py +0 -0
  39. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/__init__.py +0 -0
  40. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/chunked_file_system/__init__.py +0 -0
  41. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/chunked_file_system/implementation.py +1 -1
  42. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/chunked_k8s_pvc/__init__.py +0 -0
  43. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/chunked_k8s_pvc/implementation.py +0 -0
  44. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/chunked_k8s_pvc/integration.py +0 -0
  45. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/db/implementation_FF.py +0 -0
  46. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/db/integration_FF.py +0 -0
  47. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/file_system/__init__.py +0 -0
  48. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/file_system/implementation.py +0 -0
  49. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/k8s_pvc/__init__.py +0 -0
  50. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/k8s_pvc/implementation.py +0 -0
  51. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/run_log_store/k8s_pvc/integration.py +0 -0
  52. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/secrets/__init__.py +0 -0
  53. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/secrets/dotenv/__init__.py +0 -0
  54. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/secrets/dotenv/implementation.py +0 -0
  55. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/secrets/env_secrets/__init__.py +0 -0
  56. {runnable-0.11.1 → runnable-0.11.2}/runnable/extensions/secrets/env_secrets/implementation.py +0 -0
  57. {runnable-0.11.1 → runnable-0.11.2}/runnable/graph.py +0 -0
  58. {runnable-0.11.1 → runnable-0.11.2}/runnable/integration.py +0 -0
  59. {runnable-0.11.1 → runnable-0.11.2}/runnable/names.py +0 -0
  60. {runnable-0.11.1 → runnable-0.11.2}/runnable/nodes.py +0 -0
  61. {runnable-0.11.1 → runnable-0.11.2}/runnable/parameters.py +0 -0
  62. {runnable-0.11.1 → runnable-0.11.2}/runnable/pickler.py +0 -0
  63. {runnable-0.11.1 → runnable-0.11.2}/runnable/sdk.py +0 -0
  64. {runnable-0.11.1 → runnable-0.11.2}/runnable/secrets.py +0 -0
  65. {runnable-0.11.1 → runnable-0.11.2}/runnable/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: runnable
3
- Version: 0.11.1
3
+ Version: 0.11.2
4
4
  Summary: A Compute agnostic pipelining software
5
5
  Home-page: https://github.com/vijayvammi/runnable
6
6
  License: Apache-2.0
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "runnable"
3
- version = "0.11.1"
3
+ version = "0.11.2"
4
4
  description = "A Compute agnostic pipelining software"
5
5
  authors = ["Vijay Vammi <mesanthu@gmail.com>"]
6
6
  license = "Apache-2.0"
@@ -53,6 +53,10 @@ matplotlib = "^3.8.3"
53
53
  [tool.poetry.group.release.dependencies]
54
54
  python-semantic-release = "^9.4.2"
55
55
 
56
+
57
+ [tool.poetry.group.examples.dependencies]
58
+ pandas = "^2.2.2"
59
+
56
60
  [tool.poetry.extras]
57
61
  docker = ['docker']
58
62
  notebook = ['ploomber-engine']
@@ -38,3 +38,4 @@ from runnable.sdk import ( # noqa
38
38
 
39
39
 
40
40
  # TODO: Think of way of generating dag hash without executor configuration
41
+ # TODO: Add examples of map parameters and task types
@@ -312,8 +312,10 @@ class RunLog(BaseModel):
312
312
  summary["Catalog Location"] = _context.catalog_handler.get_summary()
313
313
  summary["Full Run log present at: "] = _context.run_log_store.get_summary()
314
314
 
315
- summary["Final Parameters"] = {p: v.description for p, v in self.parameters.items()}
316
- summary["Collected metrics"] = {p: v.description for p, v in self.parameters.items() if v.kind == "metric"}
315
+ run_log = _context.run_log_store.get_run_log_by_id(run_id=_context.run_id, full=True)
316
+
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"}
317
319
 
318
320
  return summary
319
321
 
@@ -226,7 +226,7 @@ class FileSystemCatalog(BaseCatalog):
226
226
  for cataloged_file in cataloged_files:
227
227
  if str(cataloged_file).endswith("execution.log"):
228
228
  continue
229
- print(cataloged_file.name)
229
+
230
230
  if cataloged_file.is_file():
231
231
  shutil.copy(cataloged_file, run_catalog / cataloged_file.name)
232
232
  else:
@@ -505,7 +505,7 @@ class MapNode(CompositeNode):
505
505
  for _, v in map_variable.items():
506
506
  for branch_return in self.branch_returns:
507
507
  param_name, param_type = branch_return
508
- raw_parameters[f"{param_name}_{v}"] = param_type.copy()
508
+ raw_parameters[f"{v}_{param_name}"] = param_type.copy()
509
509
  else:
510
510
  for branch_return in self.branch_returns:
511
511
  param_name, param_type = branch_return
@@ -606,9 +606,9 @@ class MapNode(CompositeNode):
606
606
  param_name, _ = branch_return
607
607
  to_reduce = []
608
608
  for iter_variable in iterate_on:
609
- to_reduce.append(params[f"{param_name}_{iter_variable}"].get_value())
609
+ to_reduce.append(params[f"{iter_variable}_{param_name}"].get_value())
610
610
 
611
- param_name = f"{param_name}_{v}"
611
+ param_name = f"{v}_{param_name}"
612
612
  params[param_name].value = reducer_f(to_reduce)
613
613
  params[param_name].reduced = True
614
614
  else:
@@ -617,7 +617,7 @@ class MapNode(CompositeNode):
617
617
 
618
618
  to_reduce = []
619
619
  for iter_variable in iterate_on:
620
- to_reduce.append(params[f"{param_name}_{iter_variable}"].get_value())
620
+ to_reduce.append(params[f"{iter_variable}_{param_name}"].get_value())
621
621
 
622
622
  params[param_name].value = reducer_f(*to_reduce)
623
623
  params[param_name].reduced = True
@@ -7,7 +7,16 @@ from string import Template
7
7
  from typing import Any, Dict, Optional, Sequence, Union
8
8
 
9
9
  from runnable import defaults, exceptions
10
- from runnable.datastore import BaseRunLogStore, BranchLog, RunLog, StepLog
10
+ from runnable.datastore import (
11
+ BaseRunLogStore,
12
+ BranchLog,
13
+ JsonParameter,
14
+ MetricParameter,
15
+ ObjectParameter,
16
+ Parameter,
17
+ RunLog,
18
+ StepLog,
19
+ )
11
20
 
12
21
  logger = logging.getLogger(defaults.LOGGER_NAME)
13
22
 
@@ -164,7 +173,9 @@ class ChunkedRunLogStore(BaseRunLogStore):
164
173
  raise Exception(f"Name is required during retrieval for {log_type}")
165
174
 
166
175
  naming_pattern = self.naming_pattern(log_type=log_type, name=name)
176
+
167
177
  matches = self.get_matches(run_id=run_id, name=naming_pattern, multiple_allowed=multiple_allowed)
178
+
168
179
  if matches:
169
180
  if not multiple_allowed:
170
181
  contents = self._retrieve(name=matches) # type: ignore
@@ -370,10 +381,17 @@ class ChunkedRunLogStore(BaseRunLogStore):
370
381
  Raises:
371
382
  RunLogNotFoundError: If the run log for run_id is not found in the datastore
372
383
  """
373
- parameters = {}
384
+ parameters: Dict[str, Parameter] = {}
374
385
  try:
375
386
  parameters_list = self.retrieve(run_id=run_id, log_type=self.LogTypes.PARAMETER, multiple_allowed=True)
376
- parameters = {key: value for param in parameters_list for key, value in param.items()}
387
+ for param in parameters_list:
388
+ for key, value in param.items():
389
+ if value["kind"] == "json":
390
+ parameters[key] = JsonParameter(**value)
391
+ if value["kind"] == "metric":
392
+ parameters[key] = MetricParameter(**value)
393
+ if value["kind"] == "object":
394
+ parameters[key] = ObjectParameter(**value)
377
395
  except EntityNotFoundError:
378
396
  # No parameters are set
379
397
  pass
@@ -401,7 +419,7 @@ class ChunkedRunLogStore(BaseRunLogStore):
401
419
  self.store(
402
420
  run_id=run_id,
403
421
  log_type=self.LogTypes.PARAMETER,
404
- contents={key: value},
422
+ contents={key: value.model_dump(by_alias=True)},
405
423
  name=key,
406
424
  )
407
425
 
@@ -1,4 +1,5 @@
1
1
  import contextlib
2
+ import copy
2
3
  import importlib
3
4
  import io
4
5
  import json
@@ -99,6 +100,20 @@ class BaseTaskType(BaseModel):
99
100
  """
100
101
  raise NotImplementedError()
101
102
 
103
+ def _diff_parameters(
104
+ self, parameters_in: Dict[str, Parameter], context_params: Dict[str, Parameter]
105
+ ) -> Dict[str, Parameter]:
106
+ diff: Dict[str, Parameter] = {}
107
+ for param_name, param in context_params.items():
108
+ if param_name in parameters_in:
109
+ if parameters_in[param_name] != param:
110
+ diff[param_name] = param
111
+ continue
112
+
113
+ diff[param_name] = param
114
+
115
+ return diff
116
+
102
117
  @contextlib.contextmanager
103
118
  def expose_secrets(self):
104
119
  """Context manager to expose secrets to the execution.
@@ -128,7 +143,7 @@ class BaseTaskType(BaseModel):
128
143
  if param.reduced is False:
129
144
  context_param = param_name
130
145
  for _, v in map_variable.items(): # type: ignore
131
- context_param = f"{context_param}_{v}"
146
+ context_param = f"{v}_{context_param}"
132
147
 
133
148
  if context_param in params:
134
149
  params[param_name].value = params[context_param].value
@@ -147,6 +162,8 @@ class BaseTaskType(BaseModel):
147
162
 
148
163
  log_file = open(log_file_name, "w")
149
164
 
165
+ parameters_in = copy.deepcopy(params)
166
+
150
167
  f = io.StringIO()
151
168
  try:
152
169
  with contextlib.redirect_stdout(f):
@@ -168,7 +185,8 @@ class BaseTaskType(BaseModel):
168
185
 
169
186
  # Update parameters
170
187
  # This should only update the parameters that are changed at the root level.
171
- self._context.run_log_store.set_parameters(parameters=params, run_id=self._context.run_id)
188
+ diff_parameters = self._diff_parameters(parameters_in=parameters_in, context_params=params)
189
+ self._context.run_log_store.set_parameters(parameters=diff_parameters, run_id=self._context.run_id)
172
190
 
173
191
 
174
192
  def task_return_to_parameter(task_return: TaskReturns, value: Any) -> Parameter:
@@ -259,7 +277,7 @@ class PythonTaskType(BaseTaskType): # pylint: disable=too-few-public-methods
259
277
  param_name = task_return.name
260
278
  if map_variable:
261
279
  for _, v in map_variable.items():
262
- param_name = f"{param_name}_{v}"
280
+ param_name = f"{v}_{param_name}"
263
281
 
264
282
  output_parameters[param_name] = output_parameter
265
283
 
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -35,10 +35,10 @@ class ChunkedFileSystemRunLogStore(ChunkedRunLogStore):
35
35
  name (str): The suffix of the file name to check in the run log store.
36
36
  """
37
37
  log_folder = self.log_folder_with_run_id(run_id=run_id)
38
-
39
38
  sub_name = Template(name).safe_substitute({"creation_time": ""})
40
39
 
41
40
  matches = list(log_folder.glob(f"{sub_name}*"))
41
+
42
42
  if matches:
43
43
  if not multiple_allowed:
44
44
  if len(matches) > 1:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes