runnable 0.11.0__py3-none-any.whl → 0.11.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- runnable/__init__.py +4 -0
- runnable/cli.py +1 -0
- runnable/entrypoints.py +5 -0
- runnable/extensions/executor/__init__.py +2 -0
- runnable/sdk.py +37 -13
- runnable/tasks.py +95 -43
- {runnable-0.11.0.dist-info → runnable-0.11.1.dist-info}/METADATA +2 -3
- {runnable-0.11.0.dist-info → runnable-0.11.1.dist-info}/RECORD +11 -11
- {runnable-0.11.0.dist-info → runnable-0.11.1.dist-info}/LICENSE +0 -0
- {runnable-0.11.0.dist-info → runnable-0.11.1.dist-info}/WHEEL +0 -0
- {runnable-0.11.0.dist-info → runnable-0.11.1.dist-info}/entry_points.txt +0 -0
runnable/__init__.py
CHANGED
@@ -29,6 +29,10 @@ from runnable.sdk import ( # noqa
|
|
29
29
|
pickled,
|
30
30
|
)
|
31
31
|
|
32
|
+
## TODO: Summary should be a bit better for catalog.
|
33
|
+
## If the execution fails, hint them about the retry executor.
|
34
|
+
# Make the retry executor loose!
|
35
|
+
|
32
36
|
# TODO: Think of model registry as a central place to store models.
|
33
37
|
# TODO: Implement Sagemaker pipelines as a executor.
|
34
38
|
|
runnable/cli.py
CHANGED
runnable/entrypoints.py
CHANGED
@@ -172,6 +172,7 @@ def execute(
|
|
172
172
|
)
|
173
173
|
console.print("Working with context:")
|
174
174
|
console.print(run_context)
|
175
|
+
console.rule(style="[dark orange]")
|
175
176
|
|
176
177
|
executor = run_context.executor
|
177
178
|
|
@@ -243,6 +244,7 @@ def execute_single_node(
|
|
243
244
|
)
|
244
245
|
console.print("Working with context:")
|
245
246
|
console.print(run_context)
|
247
|
+
console.rule(style="[dark orange]")
|
246
248
|
|
247
249
|
executor = run_context.executor
|
248
250
|
run_context.execution_plan = defaults.EXECUTION_PLAN.CHAINED.value
|
@@ -296,6 +298,7 @@ def execute_notebook(
|
|
296
298
|
|
297
299
|
console.print("Working with context:")
|
298
300
|
console.print(run_context)
|
301
|
+
console.rule(style="[dark orange]")
|
299
302
|
|
300
303
|
step_config = {
|
301
304
|
"command": notebook_file,
|
@@ -358,6 +361,7 @@ def execute_function(
|
|
358
361
|
|
359
362
|
console.print("Working with context:")
|
360
363
|
console.print(run_context)
|
364
|
+
console.rule(style="[dark orange]")
|
361
365
|
|
362
366
|
# Prepare the graph with a single node
|
363
367
|
step_config = {
|
@@ -427,6 +431,7 @@ def fan(
|
|
427
431
|
)
|
428
432
|
console.print("Working with context:")
|
429
433
|
console.print(run_context)
|
434
|
+
console.rule(style="[dark orange]")
|
430
435
|
|
431
436
|
executor = run_context.executor
|
432
437
|
run_context.execution_plan = defaults.EXECUTION_PLAN.CHAINED.value
|
runnable/sdk.py
CHANGED
@@ -15,8 +15,13 @@ from pydantic import (
|
|
15
15
|
field_validator,
|
16
16
|
model_validator,
|
17
17
|
)
|
18
|
-
from rich import
|
19
|
-
|
18
|
+
from rich.progress import (
|
19
|
+
BarColumn,
|
20
|
+
Progress,
|
21
|
+
SpinnerColumn,
|
22
|
+
TextColumn,
|
23
|
+
TimeElapsedColumn,
|
24
|
+
)
|
20
25
|
from rich.table import Column
|
21
26
|
from typing_extensions import Self
|
22
27
|
|
@@ -71,7 +76,7 @@ class Catalog(BaseModel):
|
|
71
76
|
|
72
77
|
class BaseTraversal(ABC, BaseModel):
|
73
78
|
name: str
|
74
|
-
next_node: str = Field(default="",
|
79
|
+
next_node: str = Field(default="", serialization_alias="next_node")
|
75
80
|
terminate_with_success: bool = Field(default=False, exclude=True)
|
76
81
|
terminate_with_failure: bool = Field(default=False, exclude=True)
|
77
82
|
on_failure: str = Field(default="", alias="on_failure")
|
@@ -83,6 +88,12 @@ class BaseTraversal(ABC, BaseModel):
|
|
83
88
|
def internal_name(self) -> str:
|
84
89
|
return self.name
|
85
90
|
|
91
|
+
def __hash__(self):
|
92
|
+
"""
|
93
|
+
Needed to Uniqueize DataCatalog objects.
|
94
|
+
"""
|
95
|
+
return hash(self.name)
|
96
|
+
|
86
97
|
def __rshift__(self, other: StepType) -> StepType:
|
87
98
|
if self.next_node:
|
88
99
|
raise Exception(f"The node {self} already has a next node: {self.next_node}")
|
@@ -180,6 +191,7 @@ class BaseTask(BaseTraversal):
|
|
180
191
|
catalog: Optional[Catalog] = Field(default=None, alias="catalog")
|
181
192
|
overrides: Dict[str, Any] = Field(default_factory=dict, alias="overrides")
|
182
193
|
returns: List[Union[str, TaskReturns]] = Field(default_factory=list, alias="returns")
|
194
|
+
secrets: List[str] = Field(default_factory=list)
|
183
195
|
|
184
196
|
@field_validator("returns", mode="before")
|
185
197
|
@classmethod
|
@@ -201,7 +213,7 @@ class BaseTask(BaseTraversal):
|
|
201
213
|
if not (self.terminate_with_failure or self.terminate_with_success):
|
202
214
|
raise AssertionError("A node not being terminated must have a user defined next node")
|
203
215
|
|
204
|
-
return TaskNode.parse_from_config(self.model_dump(exclude_none=True))
|
216
|
+
return TaskNode.parse_from_config(self.model_dump(exclude_none=True, by_alias=True))
|
205
217
|
|
206
218
|
|
207
219
|
class PythonTask(BaseTask):
|
@@ -297,9 +309,9 @@ class NotebookTask(BaseTask):
|
|
297
309
|
|
298
310
|
"""
|
299
311
|
|
300
|
-
notebook: str = Field(
|
312
|
+
notebook: str = Field(serialization_alias="command")
|
301
313
|
|
302
|
-
notebook_output_path: Optional[str] = Field(default=None, alias="notebook_output_path")
|
314
|
+
notebook_output_path: Optional[str] = Field(default=None, alias="notebook_output_path", validate_default=True)
|
303
315
|
optional_ploomber_args: Optional[Dict[str, Any]] = Field(default=None, alias="optional_ploomber_args")
|
304
316
|
|
305
317
|
@computed_field
|
@@ -526,7 +538,7 @@ class Pipeline(BaseModel):
|
|
526
538
|
_dag: graph.Graph = PrivateAttr()
|
527
539
|
model_config = ConfigDict(extra="forbid")
|
528
540
|
|
529
|
-
def _validate_path(self, path: List[StepType]) -> None:
|
541
|
+
def _validate_path(self, path: List[StepType], failure_path: bool = False) -> None:
|
530
542
|
# Check if one and only one step terminates with success
|
531
543
|
# Check no more than one step terminates with failure
|
532
544
|
|
@@ -544,7 +556,7 @@ class Pipeline(BaseModel):
|
|
544
556
|
raise Exception("A pipeline cannot have more than one step that terminates with failure")
|
545
557
|
reached_failure = True
|
546
558
|
|
547
|
-
if not reached_success:
|
559
|
+
if not reached_success and not reached_failure:
|
548
560
|
raise Exception("A pipeline must have at least one step that terminates with success")
|
549
561
|
|
550
562
|
def _construct_path(self, path: List[StepType]) -> None:
|
@@ -594,11 +606,21 @@ class Pipeline(BaseModel):
|
|
594
606
|
|
595
607
|
# Check all paths are valid and construct the path
|
596
608
|
paths = [success_path] + on_failure_paths
|
609
|
+
failure_path = False
|
597
610
|
for path in paths:
|
598
|
-
self._validate_path(path)
|
611
|
+
self._validate_path(path, failure_path)
|
599
612
|
self._construct_path(path)
|
600
613
|
|
601
|
-
|
614
|
+
failure_path = True
|
615
|
+
|
616
|
+
all_steps: List[StepType] = []
|
617
|
+
|
618
|
+
for path in paths:
|
619
|
+
for step in path:
|
620
|
+
all_steps.append(step)
|
621
|
+
|
622
|
+
seen = set()
|
623
|
+
unique = [x for x in all_steps if not (x in seen or seen.add(x))] # type: ignore
|
602
624
|
|
603
625
|
self._dag = graph.Graph(
|
604
626
|
start_at=all_steps[0].name,
|
@@ -606,7 +628,7 @@ class Pipeline(BaseModel):
|
|
606
628
|
internal_branch_name=self.internal_branch_name,
|
607
629
|
)
|
608
630
|
|
609
|
-
for step in
|
631
|
+
for step in unique:
|
610
632
|
self._dag.add_node(step.create_node())
|
611
633
|
|
612
634
|
if self.add_terminal_nodes:
|
@@ -675,8 +697,9 @@ class Pipeline(BaseModel):
|
|
675
697
|
|
676
698
|
run_context.dag = graph.create_graph(dag_definition)
|
677
699
|
|
678
|
-
print("Working with context:")
|
679
|
-
print(run_context)
|
700
|
+
console.print("Working with context:")
|
701
|
+
console.print(run_context)
|
702
|
+
console.rule(style="[dark orange]")
|
680
703
|
|
681
704
|
if not run_context.executor._local:
|
682
705
|
# We are not working with non local executor
|
@@ -693,6 +716,7 @@ class Pipeline(BaseModel):
|
|
693
716
|
run_context.executor.prepare_for_graph_execution()
|
694
717
|
|
695
718
|
with Progress(
|
719
|
+
SpinnerColumn(spinner_name="runner"),
|
696
720
|
TextColumn("[progress.description]{task.description}", table_column=Column(ratio=2)),
|
697
721
|
BarColumn(table_column=Column(ratio=1), style="dark_orange"),
|
698
722
|
TimeElapsedColumn(table_column=Column(ratio=1)),
|
runnable/tasks.py
CHANGED
@@ -9,13 +9,14 @@ import sys
|
|
9
9
|
from datetime import datetime
|
10
10
|
from pickle import PicklingError
|
11
11
|
from string import Template
|
12
|
-
from typing import Any, Dict, List, Literal, Tuple
|
12
|
+
from typing import Any, Dict, List, Literal, Optional, Tuple
|
13
13
|
|
14
14
|
from pydantic import BaseModel, ConfigDict, Field, ValidationInfo, field_validator
|
15
|
+
from rich.console import Console
|
15
16
|
from stevedore import driver
|
16
17
|
|
17
18
|
import runnable.context as context
|
18
|
-
from runnable import
|
19
|
+
from runnable import defaults, exceptions, parameters, utils
|
19
20
|
from runnable.datastore import (
|
20
21
|
JsonParameter,
|
21
22
|
MetricParameter,
|
@@ -32,6 +33,9 @@ logging.getLogger("stevedore").setLevel(logging.CRITICAL)
|
|
32
33
|
# TODO: Can we add memory peak, cpu usage, etc. to the metrics?
|
33
34
|
|
34
35
|
|
36
|
+
console = Console(file=io.StringIO())
|
37
|
+
|
38
|
+
|
35
39
|
class TaskReturns(BaseModel):
|
36
40
|
name: str
|
37
41
|
kind: Literal["json", "object", "metric"] = Field(default="json")
|
@@ -42,7 +46,7 @@ class BaseTaskType(BaseModel):
|
|
42
46
|
|
43
47
|
task_type: str = Field(serialization_alias="command_type")
|
44
48
|
node_name: str = Field(exclude=True)
|
45
|
-
secrets:
|
49
|
+
secrets: List[str] = Field(default_factory=list)
|
46
50
|
returns: List[TaskReturns] = Field(default_factory=list, alias="returns")
|
47
51
|
|
48
52
|
model_config = ConfigDict(extra="forbid")
|
@@ -69,15 +73,14 @@ class BaseTaskType(BaseModel):
|
|
69
73
|
raise NotImplementedError()
|
70
74
|
|
71
75
|
def set_secrets_as_env_variables(self):
|
72
|
-
for key
|
76
|
+
for key in self.secrets:
|
73
77
|
secret_value = context.run_context.secrets_handler.get(key)
|
74
|
-
|
75
|
-
os.environ[value] = secret_value
|
78
|
+
os.environ[key] = secret_value
|
76
79
|
|
77
80
|
def delete_secrets_from_env_variables(self):
|
78
|
-
for
|
79
|
-
if
|
80
|
-
del os.environ[
|
81
|
+
for key in self.secrets:
|
82
|
+
if key in os.environ:
|
83
|
+
del os.environ[key]
|
81
84
|
|
82
85
|
def execute_command(
|
83
86
|
self,
|
@@ -135,17 +138,21 @@ class BaseTaskType(BaseModel):
|
|
135
138
|
if not allow_complex:
|
136
139
|
params = {key: value for key, value in params.items() if isinstance(value, JsonParameter)}
|
137
140
|
|
138
|
-
log_file_name = self.node_name
|
141
|
+
log_file_name = self.node_name # + ".execution.log"
|
139
142
|
if map_variable:
|
140
143
|
for _, value in map_variable.items():
|
141
144
|
log_file_name += "_" + str(value)
|
142
145
|
|
146
|
+
log_file_name = "".join(x for x in log_file_name if x.isalnum()) + ".execution.log"
|
147
|
+
|
143
148
|
log_file = open(log_file_name, "w")
|
144
149
|
|
145
150
|
f = io.StringIO()
|
146
151
|
try:
|
147
152
|
with contextlib.redirect_stdout(f):
|
153
|
+
# with contextlib.nullcontext():
|
148
154
|
yield params
|
155
|
+
print(console.file.getvalue()) # type: ignore
|
149
156
|
except Exception as e: # pylint: disable=broad-except
|
150
157
|
logger.exception(e)
|
151
158
|
finally:
|
@@ -156,10 +163,11 @@ class BaseTaskType(BaseModel):
|
|
156
163
|
log_file.close()
|
157
164
|
|
158
165
|
# Put the log file in the catalog
|
159
|
-
|
166
|
+
self._context.catalog_handler.put(name=log_file.name, run_id=context.run_context.run_id)
|
160
167
|
os.remove(log_file.name)
|
161
168
|
|
162
169
|
# Update parameters
|
170
|
+
# This should only update the parameters that are changed at the root level.
|
163
171
|
self._context.run_log_store.set_parameters(parameters=params, run_id=self._context.run_id)
|
164
172
|
|
165
173
|
|
@@ -219,8 +227,7 @@ class PythonTaskType(BaseTaskType): # pylint: disable=too-few-public-methods
|
|
219
227
|
logger.info(f"Calling {func} from {module} with {filtered_parameters}")
|
220
228
|
user_set_parameters = f(**filtered_parameters) # This is a tuple or single value
|
221
229
|
except Exception as e:
|
222
|
-
|
223
|
-
console.print(e, style=defaults.error_style)
|
230
|
+
console.log(e, style=defaults.error_style, markup=False)
|
224
231
|
raise exceptions.CommandCallError(f"Function call: {self.command} did not succeed.\n") from e
|
225
232
|
|
226
233
|
attempt_log.input_parameters = params.copy()
|
@@ -263,9 +270,9 @@ class PythonTaskType(BaseTaskType): # pylint: disable=too-few-public-methods
|
|
263
270
|
attempt_log.status = defaults.SUCCESS
|
264
271
|
except Exception as _e:
|
265
272
|
msg = f"Call to the function {self.command} did not succeed.\n"
|
266
|
-
logger.exception(_e)
|
267
273
|
attempt_log.message = msg
|
268
|
-
console.
|
274
|
+
console.print_exception(show_locals=False)
|
275
|
+
console.log(_e, style=defaults.error_style)
|
269
276
|
|
270
277
|
attempt_log.end_time = str(datetime.now())
|
271
278
|
|
@@ -277,7 +284,7 @@ class NotebookTaskType(BaseTaskType):
|
|
277
284
|
|
278
285
|
task_type: str = Field(default="notebook", serialization_alias="command_type")
|
279
286
|
command: str
|
280
|
-
notebook_output_path: str = Field(default=
|
287
|
+
notebook_output_path: Optional[str] = Field(default=None, validate_default=True)
|
281
288
|
optional_ploomber_args: dict = {}
|
282
289
|
|
283
290
|
@field_validator("command")
|
@@ -319,7 +326,7 @@ class NotebookTaskType(BaseTaskType):
|
|
319
326
|
import ploomber_engine as pm
|
320
327
|
from ploomber_engine.ipython import PloomberClient
|
321
328
|
|
322
|
-
notebook_output_path = self.notebook_output_path
|
329
|
+
notebook_output_path = self.notebook_output_path or ""
|
323
330
|
|
324
331
|
with self.execution_context(
|
325
332
|
map_variable=map_variable, allow_complex=False
|
@@ -424,15 +431,17 @@ class ShellTaskType(BaseTaskType):
|
|
424
431
|
|
425
432
|
# Expose secrets as environment variables
|
426
433
|
if self.secrets:
|
427
|
-
for key
|
434
|
+
for key in self.secrets:
|
428
435
|
secret_value = context.run_context.secrets_handler.get(key)
|
429
|
-
subprocess_env[
|
436
|
+
subprocess_env[key] = secret_value
|
430
437
|
|
431
438
|
with self.execution_context(map_variable=map_variable, allow_complex=False) as params:
|
432
439
|
subprocess_env.update({k: v.get_value() for k, v in params.items()})
|
433
440
|
|
434
441
|
# Json dumps all runnable environment variables
|
435
442
|
for key, value in subprocess_env.items():
|
443
|
+
if isinstance(value, str):
|
444
|
+
continue
|
436
445
|
subprocess_env[key] = json.dumps(value)
|
437
446
|
|
438
447
|
collect_delimiter = "=== COLLECT ==="
|
@@ -441,37 +450,80 @@ class ShellTaskType(BaseTaskType):
|
|
441
450
|
logger.info(f"Executing shell command: {command}")
|
442
451
|
|
443
452
|
capture = False
|
444
|
-
return_keys =
|
453
|
+
return_keys = {x.name: x for x in self.returns}
|
445
454
|
|
446
|
-
|
455
|
+
proc = subprocess.Popen(
|
447
456
|
command,
|
448
457
|
shell=True,
|
449
458
|
env=subprocess_env,
|
450
459
|
stdout=subprocess.PIPE,
|
451
460
|
stderr=subprocess.PIPE,
|
452
461
|
text=True,
|
453
|
-
)
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
462
|
+
)
|
463
|
+
result = proc.communicate()
|
464
|
+
logger.debug(result)
|
465
|
+
logger.info(proc.returncode)
|
466
|
+
|
467
|
+
if proc.returncode != 0:
|
468
|
+
msg = ",".join(result[1].split("\n"))
|
469
|
+
attempt_log.status = defaults.FAIL
|
470
|
+
attempt_log.end_time = str(datetime.now())
|
471
|
+
attempt_log.message = msg
|
472
|
+
console.print(msg, style=defaults.error_style)
|
473
|
+
return attempt_log
|
474
|
+
|
475
|
+
# for stderr
|
476
|
+
for line in result[1].split("\n"):
|
477
|
+
if line.strip() == "":
|
478
|
+
continue
|
479
|
+
console.print(line, style=defaults.warning_style)
|
480
|
+
|
481
|
+
output_parameters: Dict[str, Parameter] = {}
|
482
|
+
metrics: Dict[str, Parameter] = {}
|
483
|
+
|
484
|
+
# only from stdout
|
485
|
+
for line in result[0].split("\n"):
|
486
|
+
if line.strip() == "":
|
487
|
+
continue
|
488
|
+
|
489
|
+
logger.info(line)
|
490
|
+
console.print(line)
|
491
|
+
|
492
|
+
if line.strip() == collect_delimiter:
|
493
|
+
# The lines from now on should be captured
|
494
|
+
capture = True
|
495
|
+
continue
|
496
|
+
|
497
|
+
if capture:
|
498
|
+
key, value = line.strip().split("=", 1)
|
499
|
+
if key in return_keys:
|
500
|
+
task_return = return_keys[key]
|
501
|
+
|
502
|
+
try:
|
503
|
+
value = json.loads(value)
|
504
|
+
except json.JSONDecodeError:
|
505
|
+
value = value
|
506
|
+
|
507
|
+
output_parameter = task_return_to_parameter(
|
508
|
+
task_return=task_return,
|
509
|
+
value=value,
|
510
|
+
)
|
511
|
+
|
512
|
+
if task_return.kind == "metric":
|
513
|
+
metrics[task_return.name] = output_parameter
|
514
|
+
|
515
|
+
param_name = task_return.name
|
516
|
+
if map_variable:
|
517
|
+
for _, v in map_variable.items():
|
518
|
+
param_name = f"{param_name}_{v}"
|
519
|
+
|
520
|
+
output_parameters[param_name] = output_parameter
|
521
|
+
|
522
|
+
attempt_log.output_parameters = output_parameters
|
523
|
+
attempt_log.user_defined_metrics = metrics
|
524
|
+
params.update(output_parameters)
|
525
|
+
|
526
|
+
attempt_log.status = defaults.SUCCESS
|
475
527
|
|
476
528
|
attempt_log.end_time = str(datetime.now())
|
477
529
|
return attempt_log
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: runnable
|
3
|
-
Version: 0.11.
|
3
|
+
Version: 0.11.1
|
4
4
|
Summary: A Compute agnostic pipelining software
|
5
5
|
Home-page: https://github.com/vijayvammi/runnable
|
6
6
|
License: Apache-2.0
|
@@ -15,13 +15,12 @@ Classifier: Programming Language :: Python :: 3.11
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.12
|
16
16
|
Provides-Extra: database
|
17
17
|
Provides-Extra: docker
|
18
|
-
Provides-Extra: mlflow
|
19
18
|
Provides-Extra: notebook
|
20
19
|
Requires-Dist: click
|
21
20
|
Requires-Dist: click-plugins (>=1.1.1,<2.0.0)
|
22
21
|
Requires-Dist: dill (>=0.3.8,<0.4.0)
|
23
22
|
Requires-Dist: docker ; extra == "docker"
|
24
|
-
Requires-Dist: mlflow-skinny
|
23
|
+
Requires-Dist: mlflow-skinny
|
25
24
|
Requires-Dist: ploomber-engine (>=0.0.31,<0.0.32) ; extra == "notebook"
|
26
25
|
Requires-Dist: pydantic (>=2.5,<3.0)
|
27
26
|
Requires-Dist: rich (>=13.5.2,<14.0.0)
|
@@ -1,10 +1,10 @@
|
|
1
|
-
runnable/__init__.py,sha256=
|
1
|
+
runnable/__init__.py,sha256=C5ySSfN_vHWFTscnxLx3tfMjKT3Bs9jfUjXnDvun33Y,870
|
2
2
|
runnable/catalog.py,sha256=22OECi5TrpHErxYIhfx-lJ2vgBUi4-5V9CaYEVm98hE,4138
|
3
|
-
runnable/cli.py,sha256=
|
3
|
+
runnable/cli.py,sha256=RILUrEfzernuKD3dNdXPBkqN_1OgE5GosYRuInj0FVs,9618
|
4
4
|
runnable/context.py,sha256=QhiXJHRcEBfSKB1ijvL5yB9w44x0HCe7VEiwK1cUJ9U,1124
|
5
5
|
runnable/datastore.py,sha256=EgKi4_b5g6KbInpjMyw8Xwr-EgcSGi1Lx2u5vp4amSQ,27672
|
6
6
|
runnable/defaults.py,sha256=MOX7I2S6yO4FphZaZREFQca94a20oO8uvzXLd6GLKQs,4703
|
7
|
-
runnable/entrypoints.py,sha256
|
7
|
+
runnable/entrypoints.py,sha256=a8M7vb954as_ni7lM0t65czXQj2AHjB-KrQJ3zt3sWo,16397
|
8
8
|
runnable/exceptions.py,sha256=6NIYoTAzdKyGQ9PvW1Hu7b80OS746395KiGDhM7ThH8,2526
|
9
9
|
runnable/executor.py,sha256=xfBighQ5t_vejohip000XfxLwsgechUE1ZMIJWrZbUA,14484
|
10
10
|
runnable/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -14,7 +14,7 @@ runnable/extensions/catalog/file_system/implementation.py,sha256=9j920o9SULdcVp1
|
|
14
14
|
runnable/extensions/catalog/k8s_pvc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
15
|
runnable/extensions/catalog/k8s_pvc/implementation.py,sha256=oJDDI0APT7lrtjWmzYJRDHLGn3Vhbn2MdFSRYvFBUpY,436
|
16
16
|
runnable/extensions/catalog/k8s_pvc/integration.py,sha256=OfrHbNFN8sR-wsVa4os3ajmWJFSd5H4KOHGVAmjRZTQ,1850
|
17
|
-
runnable/extensions/executor/__init__.py,sha256=
|
17
|
+
runnable/extensions/executor/__init__.py,sha256=eV3q_dL2cRqYaJ8RWV6Xk1__KMWMM2hUnQFT7Z5pRso,26698
|
18
18
|
runnable/extensions/executor/argo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
19
|
runnable/extensions/executor/argo/implementation.py,sha256=_BfxCe742S6uV-7PuQ53KjzwY-8Rq-5y9txOXMYf20U,43670
|
20
20
|
runnable/extensions/executor/argo/specification.yaml,sha256=wXQcm2gOQYqy-IOQIhucohS32ZrHKCfGA5zZ0RraPYc,1276
|
@@ -55,12 +55,12 @@ runnable/names.py,sha256=vn92Kv9ANROYSZX6Z4z1v_WA3WiEdIYmG6KEStBFZug,8134
|
|
55
55
|
runnable/nodes.py,sha256=UqR-bJx0Hi7uLSUw_saB7VsNdFh3POKtdgsEPsasHfE,16576
|
56
56
|
runnable/parameters.py,sha256=KGGW8_uoIK2hd3EwzzBmoHBOrai3fh-SESNPpJRTfj4,5161
|
57
57
|
runnable/pickler.py,sha256=5SDNf0miMUJ3ZauhQdzwk8_t-9jeOqaTjP5bvRnu9sU,2685
|
58
|
-
runnable/sdk.py,sha256=
|
58
|
+
runnable/sdk.py,sha256=JsM27GUc3c57ZepK996FHtfzXP6FGs8MP-s96RC-_fo,27648
|
59
59
|
runnable/secrets.py,sha256=dakb7WRloWVo-KpQp6Vy4rwFdGi58BTlT4OifQY106I,2324
|
60
|
-
runnable/tasks.py,sha256=
|
60
|
+
runnable/tasks.py,sha256=CH0W7evAZK5hco0medJS6DwHRr06bng7oB7xk0Xh6zQ,20618
|
61
61
|
runnable/utils.py,sha256=okZFGbJWqStl5Rq5vLhNUQZDv_vhcT58bq9MDrTVxhc,19449
|
62
|
-
runnable-0.11.
|
63
|
-
runnable-0.11.
|
64
|
-
runnable-0.11.
|
65
|
-
runnable-0.11.
|
66
|
-
runnable-0.11.
|
62
|
+
runnable-0.11.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
63
|
+
runnable-0.11.1.dist-info/METADATA,sha256=IKuld8eA9gcb6y7YZaO-3Dpmw2x4U2wnPg0eag1fewU,17020
|
64
|
+
runnable-0.11.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
65
|
+
runnable-0.11.1.dist-info/entry_points.txt,sha256=Wy-dimdD2REO2a36Ri84fqGqA5iwGy2RIbdgRNtCNdM,1540
|
66
|
+
runnable-0.11.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|