runnable 0.35.0__py3-none-any.whl → 0.36.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 (42) hide show
  1. extensions/job_executor/__init__.py +3 -4
  2. extensions/job_executor/emulate.py +106 -0
  3. extensions/job_executor/k8s.py +8 -8
  4. extensions/job_executor/local_container.py +13 -14
  5. extensions/nodes/__init__.py +0 -0
  6. extensions/nodes/conditional.py +7 -5
  7. extensions/nodes/fail.py +72 -0
  8. extensions/nodes/map.py +350 -0
  9. extensions/nodes/parallel.py +159 -0
  10. extensions/nodes/stub.py +89 -0
  11. extensions/nodes/success.py +72 -0
  12. extensions/nodes/task.py +92 -0
  13. extensions/pipeline_executor/__init__.py +24 -26
  14. extensions/pipeline_executor/argo.py +18 -15
  15. extensions/pipeline_executor/emulate.py +112 -0
  16. extensions/pipeline_executor/local.py +4 -4
  17. extensions/pipeline_executor/local_container.py +19 -79
  18. extensions/pipeline_executor/mocked.py +4 -4
  19. extensions/pipeline_executor/retry.py +6 -10
  20. extensions/tasks/torch.py +1 -1
  21. runnable/__init__.py +0 -8
  22. runnable/catalog.py +1 -21
  23. runnable/cli.py +0 -59
  24. runnable/context.py +519 -28
  25. runnable/datastore.py +51 -54
  26. runnable/defaults.py +12 -34
  27. runnable/entrypoints.py +82 -440
  28. runnable/exceptions.py +35 -34
  29. runnable/executor.py +13 -20
  30. runnable/names.py +1 -1
  31. runnable/nodes.py +16 -15
  32. runnable/parameters.py +2 -2
  33. runnable/sdk.py +66 -163
  34. runnable/tasks.py +62 -21
  35. runnable/utils.py +6 -268
  36. {runnable-0.35.0.dist-info → runnable-0.36.0.dist-info}/METADATA +1 -1
  37. runnable-0.36.0.dist-info/RECORD +74 -0
  38. {runnable-0.35.0.dist-info → runnable-0.36.0.dist-info}/entry_points.txt +8 -7
  39. extensions/nodes/nodes.py +0 -778
  40. runnable-0.35.0.dist-info/RECORD +0 -66
  41. {runnable-0.35.0.dist-info → runnable-0.36.0.dist-info}/WHEEL +0 -0
  42. {runnable-0.35.0.dist-info → runnable-0.36.0.dist-info}/licenses/LICENSE +0 -0
runnable/utils.py CHANGED
@@ -11,17 +11,16 @@ from collections import OrderedDict
11
11
  from datetime import datetime
12
12
  from pathlib import Path
13
13
  from string import Template as str_template
14
- from typing import TYPE_CHECKING, Any, Dict, Mapping, Tuple, Union
14
+ from typing import TYPE_CHECKING, Any, Dict, Tuple, Union
15
15
 
16
16
  from ruamel.yaml import YAML
17
- from stevedore import driver
18
17
 
19
18
  import runnable.context as context
20
19
  from runnable import console, defaults, names
21
- from runnable.defaults import TypeMapVariable
20
+ from runnable.defaults import MapVariableType
22
21
 
23
22
  if TYPE_CHECKING: # pragma: no cover
24
- from runnable.nodes import BaseNode
23
+ pass
25
24
 
26
25
 
27
26
  logger = logging.getLogger(defaults.LOGGER_NAME)
@@ -66,6 +65,7 @@ def safe_make_dir(directory: Union[str, Path]):
66
65
  Path(directory).mkdir(parents=True, exist_ok=True)
67
66
 
68
67
 
68
+ # TODO: remove this
69
69
  def generate_run_id(run_id: str = "") -> str:
70
70
  """Generate a new run_id.
71
71
 
@@ -147,19 +147,6 @@ def get_module_and_attr_names(command: str) -> Tuple[str, str]:
147
147
  return module, func
148
148
 
149
149
 
150
- def get_dag_hash(dag: Dict[str, Any]) -> str:
151
- """Generates the hash of the dag definition.
152
-
153
- Args:
154
- dag (dict): The dictionary object containing the dag definition
155
-
156
- Returns:
157
- str: The hash of the dag definition
158
- """
159
- dag_str = json.dumps(dag, sort_keys=True, ensure_ascii=True)
160
- return hashlib.sha1(dag_str.encode("utf-8")).hexdigest()
161
-
162
-
163
150
  def load_yaml(file_path: str, load_type: str = "safe") -> Dict[str, Any]:
164
151
  """Loads an yaml and returns the dictionary.
165
152
 
@@ -314,29 +301,6 @@ def remove_prefix(text: str, prefix: str) -> str:
314
301
  return text # or whatever is given
315
302
 
316
303
 
317
- def get_tracked_data() -> Dict[str, str]:
318
- """Scans the environment variables to find any user tracked variables that have a prefix runnable_TRACK_
319
- Removes the environment variable to prevent any clashes in the future steps.
320
-
321
- Returns:
322
- dict: A dictionary of user tracked data
323
- """
324
- tracked_data = {}
325
- for env_var, value in os.environ.items():
326
- if env_var.startswith(defaults.TRACK_PREFIX):
327
- key = remove_prefix(env_var, defaults.TRACK_PREFIX)
328
- try:
329
- tracked_data[key.lower()] = json.loads(value)
330
- except json.decoder.JSONDecodeError:
331
- logger.warning(
332
- f"Tracker {key} could not be JSON decoded, adding the literal value"
333
- )
334
- tracked_data[key.lower()] = value
335
-
336
- del os.environ[env_var]
337
- return tracked_data
338
-
339
-
340
304
  def diff_dict(d1: Dict[str, Any], d2: Dict[str, Any]) -> Dict[str, Any]:
341
305
  """
342
306
  Given two dicts d1 and d2, return a new dict that has upsert items from d1.
@@ -359,25 +323,6 @@ def diff_dict(d1: Dict[str, Any], d2: Dict[str, Any]) -> Dict[str, Any]:
359
323
  return diff
360
324
 
361
325
 
362
- # def hash_bytestr_iter(bytesiter, hasher, ashexstr=True): # pylint: disable=C0116
363
- # """Hashes the given bytesiter using the given hasher."""
364
- # for block in bytesiter: # pragma: no cover
365
- # hasher.update(block)
366
- # return hasher.hexdigest() if ashexstr else hasher.digest() # pragma: no cover
367
-
368
-
369
- # def file_as_blockiter(afile, blocksize=65536): # pylint: disable=C0116
370
- # """From a StackOverflow answer: that is used to generate a MD5 hash of a large files.
371
- # # https://stackoverflow.com/questions/3431825/generating-an-md5-checksum-of-a-file.
372
-
373
- # """
374
- # with afile: # pragma: no cover
375
- # block = afile.read(blocksize)
376
- # while len(block) > 0:
377
- # yield block
378
- # block = afile.read(blocksize)
379
-
380
-
381
326
  def get_data_hash(file_name: str) -> str:
382
327
  """Returns the hash of the data file.
383
328
 
@@ -397,193 +342,7 @@ def get_data_hash(file_name: str) -> str:
397
342
  return file_hash.hexdigest()
398
343
 
399
344
 
400
- # TODO: This is not the right place for this.
401
- def get_node_execution_command(
402
- node: BaseNode,
403
- map_variable: TypeMapVariable = None,
404
- over_write_run_id: str = "",
405
- log_level: str = "",
406
- ) -> str:
407
- """A utility function to standardize execution call to a node via command line.
408
-
409
- Args:
410
- executor (object): The executor class.
411
- node (object): The Node to execute
412
- map_variable (str, optional): If the node belongs to a map step. Defaults to None.
413
-
414
- Returns:
415
- str: The execution command to run a node via command line.
416
- """
417
- run_id = context.run_context.run_id
418
-
419
- if over_write_run_id:
420
- run_id = over_write_run_id
421
-
422
- log_level = log_level or logging.getLevelName(logger.getEffectiveLevel())
423
-
424
- action = (
425
- f"runnable execute-single-node {run_id} "
426
- f"{context.run_context.pipeline_file} "
427
- f"{node._command_friendly_name()} "
428
- f"--log-level {log_level} "
429
- )
430
-
431
- if context.run_context.from_sdk:
432
- action = action + "--mode python "
433
-
434
- if map_variable:
435
- action = action + f"--map-variable '{json.dumps(map_variable)}' "
436
-
437
- if context.run_context.configuration_file:
438
- action = action + f"--config {context.run_context.configuration_file} "
439
-
440
- if context.run_context.parameters_file:
441
- action = action + f"--parameters-file {context.run_context.parameters_file} "
442
-
443
- if context.run_context.tag:
444
- action = action + f"--tag {context.run_context.tag}"
445
-
446
- return action
447
-
448
-
449
- # TODO: This is not the right place for this.
450
- def get_fan_command(
451
- mode: str,
452
- node: BaseNode,
453
- run_id: str,
454
- map_variable: TypeMapVariable = None,
455
- log_level: str = "",
456
- ) -> str:
457
- """
458
- An utility function to return the fan "in or out" command
459
-
460
- Args:
461
- executor (BaseExecutor): The executor class
462
- mode (str): in or out
463
- node (BaseNode): The composite node that we are fanning in or out
464
- run_id (str): The run id.
465
- map_variable (dict, optional): If the node is a map, we have the map variable. Defaults to None.
466
-
467
- Returns:
468
- str: The fan in or out command
469
- """
470
- log_level = log_level or logging.getLevelName(logger.getEffectiveLevel())
471
- action = (
472
- f"runnable fan {run_id} "
473
- f"{node._command_friendly_name()} " # step name
474
- f"{context.run_context.pipeline_file} " # yaml or python
475
- f"{mode} " # in or out
476
- f"--log-level {log_level} "
477
- )
478
- if context.run_context.configuration_file:
479
- action = action + f" --config-file {context.run_context.configuration_file} "
480
-
481
- if context.run_context.parameters_file:
482
- action = action + f" --parameters-file {context.run_context.parameters_file}"
483
-
484
- if map_variable:
485
- action = action + f" --map-variable '{json.dumps(map_variable)}'"
486
-
487
- if context.run_context.from_sdk: # execution mode
488
- action = action + " --mode python "
489
-
490
- return action
491
-
492
-
493
- # TODO: This is not the right place for this.
494
- def get_job_execution_command(over_write_run_id: str = "") -> str:
495
- """Get the execution command to run a job via command line.
496
-
497
- This function should be used by all executors to submit jobs in remote environment
498
- """
499
-
500
- run_id = context.run_context.run_id
501
-
502
- if over_write_run_id:
503
- run_id = over_write_run_id
504
-
505
- log_level = logging.getLevelName(logger.getEffectiveLevel())
506
-
507
- action = (
508
- f"runnable execute-job {context.run_context.job_definition_file} {run_id} "
509
- f" --log-level {log_level}"
510
- )
511
-
512
- if context.run_context.configuration_file:
513
- action = action + f" --config {context.run_context.configuration_file}"
514
-
515
- if context.run_context.parameters_file:
516
- action = action + f" --parameters {context.run_context.parameters_file}"
517
-
518
- if context.run_context.from_sdk:
519
- action = action + " --mode python "
520
-
521
- if context.run_context.tag:
522
- action = action + f" --tag {context.run_context.tag}"
523
-
524
- return action
525
-
526
-
527
- def get_provider_by_name_and_type(
528
- service_type: str, service_details: defaults.ServiceConfig
529
- ):
530
- """Given a service type, one of executor, run_log_store, catalog, secrets and the config
531
- return the exact child class implementing the service.
532
- We use stevedore to do the work for us.
533
-
534
- Args:
535
- service_type (str): One of executor, run_log_store, catalog, secrets
536
- service_details (dict): The config used to instantiate the service.
537
-
538
- Raises:
539
- Exception: If the service by that name does not exist
540
-
541
- Returns:
542
- object: A service object
543
- """
544
-
545
- namespace = service_type
546
-
547
- service_name = service_details["type"]
548
- service_config: Mapping[str, Any] = {}
549
- if "config" in service_details:
550
- service_config = service_details.get("config", {})
551
-
552
- logger.debug(
553
- f"Trying to get a service of {service_type} of the name {service_name} with config: {service_config}"
554
- )
555
- try:
556
- mgr = driver.DriverManager(
557
- namespace=namespace,
558
- name=service_name,
559
- invoke_on_load=True,
560
- invoke_kwds={**service_config},
561
- )
562
- return mgr.driver
563
- except Exception as _e:
564
- logger.exception(
565
- f"Could not find the service of type: {service_type} with config: {service_details}"
566
- )
567
- raise Exception(
568
- f"Could not find the service of type: {service_type} with config: {service_details}"
569
- ) from _e
570
-
571
-
572
- def get_run_config() -> dict:
573
- """Given an executor with assigned services, return the run_config.
574
-
575
- Args:
576
- executor (object): The executor with all the services assigned.
577
-
578
- Returns:
579
- dict: The run_config.
580
- """
581
-
582
- run_config = context.run_context.model_dump(by_alias=True)
583
- return run_config
584
-
585
-
586
- def json_to_ordered_dict(json_str: str) -> TypeMapVariable:
345
+ def json_to_ordered_dict(json_str: str) -> MapVariableType:
587
346
  """Decode a JSON str into OrderedDict.
588
347
 
589
348
  Args:
@@ -598,27 +357,6 @@ def json_to_ordered_dict(json_str: str) -> TypeMapVariable:
598
357
  return OrderedDict()
599
358
 
600
359
 
601
- def set_runnable_environment_variables(
602
- run_id: str = "", configuration_file: str = "", tag: str = ""
603
- ) -> None:
604
- """Set the environment variables used by runnable. This function should be called during the prepare configurations
605
- by all executors.
606
-
607
- Args:
608
- run_id (str, optional): The run id of the execution. Defaults to None.
609
- configuration_file (str, optional): The configuration file if used. Defaults to None.
610
- tag (str, optional): The tag associated with a run. Defaults to None.
611
- """
612
- if run_id:
613
- os.environ[defaults.ENV_RUN_ID] = run_id
614
-
615
- if configuration_file:
616
- os.environ[defaults.RUNNABLE_CONFIG_FILE] = configuration_file
617
-
618
- if tag:
619
- os.environ[defaults.RUNNABLE_RUN_TAG] = tag
620
-
621
-
622
360
  def gather_variables() -> Dict[str, str]:
623
361
  """Gather all the environment variables used by runnable. All the variables start with runnable_VAR_.
624
362
 
@@ -635,7 +373,7 @@ def gather_variables() -> Dict[str, str]:
635
373
  return variables
636
374
 
637
375
 
638
- def make_log_file_name(name: str, map_variable: TypeMapVariable) -> str:
376
+ def make_log_file_name(name: str, map_variable: MapVariableType) -> str:
639
377
  random_tag = "".join(random.choices(string.ascii_uppercase + string.digits, k=3))
640
378
  log_file_name = name
641
379
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: runnable
3
- Version: 0.35.0
3
+ Version: 0.36.0
4
4
  Summary: Add your description here
5
5
  Author-email: "Vammi, Vijay" <vijay.vammi@astrazeneca.com>
6
6
  License-File: LICENSE
@@ -0,0 +1,74 @@
1
+ extensions/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ extensions/catalog/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ extensions/catalog/any_path.py,sha256=atB5gWPRX6ptW6zwYeCVb_fh0qhs7WAFO9HIsnMZl98,7350
5
+ extensions/catalog/file_system.py,sha256=T_qFPFfrmykoAMc1rjNi_DBb437me8WPRcFglwAK744,1767
6
+ extensions/catalog/minio.py,sha256=R3GvfCxN1GTcs4bQIAWh79_GHDTVd14gnpKlzwFeKUI,2363
7
+ extensions/catalog/pyproject.toml,sha256=lLNxY6v04c8I5QK_zKw_E6sJTArSJRA_V-79ktaA3Hk,279
8
+ extensions/catalog/s3.py,sha256=Sw5t8_kVRprn3uGGJCiHn7M9zw1CLaCOFj6YErtfG0o,287
9
+ extensions/job_executor/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ extensions/job_executor/__init__.py,sha256=5_pKw7GJbwmXL-QPdZwtfRKVHuKiPqLheK3rGU5G7-M,5813
11
+ extensions/job_executor/emulate.py,sha256=d9KI4If0DeRkKv9iCSKyZCziK_3ARsJvs5RUFo9yigc,3220
12
+ extensions/job_executor/k8s.py,sha256=W14u1xwJDtb-gyGdNl62IwWIs49AUO2oTAAxQCm6YT0,16456
13
+ extensions/job_executor/k8s_job_spec.yaml,sha256=7aFpxHdO_p6Hkc3YxusUOuAQTD1Myu0yTPX9DrhxbOg,1158
14
+ extensions/job_executor/local.py,sha256=3ZbCFXBvbLlMp10JTmQJJrjBKG2keHI6SH8hEvmHDkA,2230
15
+ extensions/job_executor/local_container.py,sha256=uoRbsyR5QiVytWJQtF7nXUA1h8wHAaQezedWFKl3btM,6914
16
+ extensions/job_executor/pyproject.toml,sha256=UIEgiCYHTXcRWSByNMFuKJFKgxTBpQqTqyUecIsb_Vc,286
17
+ extensions/nodes/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ extensions/nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ extensions/nodes/conditional.py,sha256=lsXLerIDWJk0fHo4EEngl8rYw6dN40EgKIgdBuvt8ro,8641
20
+ extensions/nodes/fail.py,sha256=P_wryruE2INiAmu4Vf7q4fTEkfbIMnhT71Y9IrOqRkM,2170
21
+ extensions/nodes/map.py,sha256=s0l07uAc6j8MO7Fqch0DzOE3_CsV6pBNHj5E3nf1S60,13659
22
+ extensions/nodes/parallel.py,sha256=cuxpR1e0KwuxvoZaSwiiEn9YmYskplbjLBWBzzU-Ti8,5952
23
+ extensions/nodes/pyproject.toml,sha256=YTu-ETN3JNFSkMzzWeOwn4m-O2nbRH-PmiPBALDCUw4,278
24
+ extensions/nodes/stub.py,sha256=o9DjBekNa9O4b0VQOiNOA9eNjJ3C2a9Sn9d2fX7KaWg,2715
25
+ extensions/nodes/success.py,sha256=yT4WkUI-1YN6qy4Ji6zSoZFXI9jOl6Ond4WxZRq-33k,2179
26
+ extensions/nodes/task.py,sha256=m5_s5u7lQDoTmeO6CG94btrG5If9AKm2-RvOzvm0fDc,3147
27
+ extensions/pipeline_executor/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ extensions/pipeline_executor/__init__.py,sha256=u1wLhQfDB1WotCoLIg1mwGlJTupfV312xACwjUxsbJw,24521
29
+ extensions/pipeline_executor/argo.py,sha256=Jz0sA3rNiG_JrCEMCA4b7aGjpWo8erQFLgymgCXrGWU,38349
30
+ extensions/pipeline_executor/emulate.py,sha256=ziaIzEpYgVOm2PPCY8bnRdoevMwS8OY9aEUXpwCFQR0,3547
31
+ extensions/pipeline_executor/local.py,sha256=_8dtj88mI3xeZT4UPwtHNtbyi_VVzz_lpIxvC0UZS-g,1887
32
+ extensions/pipeline_executor/local_container.py,sha256=oJsd7Pcxur2ZzaBqTN6IUk_ZnMqYkxrK65BVKo_2P2k,10262
33
+ extensions/pipeline_executor/mocked.py,sha256=myaU5Jy4LRRwe2-fBiX5Ts-1xc1a6nqXHxQlmur5H-M,5679
34
+ extensions/pipeline_executor/pyproject.toml,sha256=ykTX7srR10PBYb8LsIwEj8vIPPIEZQ5V_R7VYbZ-ido,291
35
+ extensions/pipeline_executor/retry.py,sha256=sBfZiS9ryw_hNCMAza82mXyV1wPjOJb20EEF9f5FUng,6790
36
+ extensions/run_log_store/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ extensions/run_log_store/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ extensions/run_log_store/any_path.py,sha256=0nN_LHbm2W6AHkerQmsVHq3EoybFQF8lxpCicacHo8Y,2861
39
+ extensions/run_log_store/chunked_fs.py,sha256=wHMKcAx6uFI4OOTp7QWCdGq9WvEFesbLp9VxHZU28l0,3341
40
+ extensions/run_log_store/chunked_minio.py,sha256=Itfkw4Ycf0uLCqxH3Uk_itmVgT7ipJp05yKfD22WBiY,4007
41
+ extensions/run_log_store/file_system.py,sha256=hhrbhSnuzv8yzBr6DAu45NT8-sawPP86WA2-LY70vjw,2781
42
+ extensions/run_log_store/generic_chunked.py,sha256=EnhRxlqm1jG-Tdxul4sY8OeCX5fK9FY2v8DZanX9-5o,20455
43
+ extensions/run_log_store/minio.py,sha256=omrKDSdRzmnVBg9xXkkdQb-icBIgBDRdpmwGRlMyCGk,3453
44
+ extensions/run_log_store/pyproject.toml,sha256=YnmXsFvFG9uv_c0spLYBsNI_1sbktqxtHsOuClyvZ3g,288
45
+ extensions/run_log_store/db/implementation_FF.py,sha256=euTnh0xzNF0e_DyfHQ4W-kG1AwTr8u7OuO3_cZkR5bM,5237
46
+ extensions/run_log_store/db/integration_FF.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ extensions/secrets/README.md,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ extensions/secrets/dotenv.py,sha256=nADHXI6KJ_LUYOIe5EbtYH-21OBebSNVr0Pjb1GlZ7w,1573
49
+ extensions/secrets/pyproject.toml,sha256=mLJNImNcBlbLKHh-0ugVWT9V83R4RibyyYDtBCSqVF4,282
50
+ extensions/tasks/torch.py,sha256=H1b84vV1j8a8U0ddabPEOcCVUWZHXx7FUbJDJ0PxzuI,10283
51
+ extensions/tasks/torch_config.py,sha256=UjfMitT-TXASRDGR30I2vDRnyk7JQnR-5CsOVidjpSY,2833
52
+ runnable/__init__.py,sha256=LUruVUZaLLZC4Xz-6_w_0qQ-OtxMZR5VVIPJeOxLRUY,538
53
+ runnable/catalog.py,sha256=A03iMLW8S6_AZjucBoFhl7fPKx-khTLQeICVAUjd9WU,3767
54
+ runnable/cli.py,sha256=CziCKBoL-dklSEo_x-YO1AysrG2eaf2LMQZbcNTeCbM,7283
55
+ runnable/context.py,sha256=yEJodj6hbBAcvpQdoAUAwoYXsqiJTQtxmGTJWIaexHs,17515
56
+ runnable/datastore.py,sha256=2pYg4i1JRMzw_CUUIsPOWt7wYPiGBamfo-CPVAkEH54,32375
57
+ runnable/defaults.py,sha256=4UYuShnjEyWP529UlFnubvkBpOcczKIdE4jEOhPBwl4,3076
58
+ runnable/entrypoints.py,sha256=46prgr3_FYtBMlRbUXIDSpgZUBgaxcdJAekXhgEIj7M,6578
59
+ runnable/exceptions.py,sha256=t5tSlYqe_EjU5liXu32yLLh_yrnXeFL93BuXfmQzV98,3268
60
+ runnable/executor.py,sha256=CwzHkeGVpocACZLzfFS94TzKeiaPLv4NtXtvT3eoocY,15222
61
+ runnable/graph.py,sha256=poQz5zcvq89ju_u5sYlunQLPbHnXTaUmjcvstPwvT4U,16536
62
+ runnable/names.py,sha256=A9ldUyULXuWjJ1MoXihHqlg-xeTVX-oWYTO5Ah0trmo,8128
63
+ runnable/nodes.py,sha256=JXB7TLA5zrFFk1cJXLrSBfunp4aVRFw_Y5uIjIGOpHg,16805
64
+ runnable/parameters.py,sha256=zEehAliVvCOLOnNZ4ExJvSDJM_2PWY0URZ0bmZUgCQA,5289
65
+ runnable/pickler.py,sha256=ydJ_eti_U1F4l-YacFp7BWm6g5vTn04UXye25S1HVok,2684
66
+ runnable/sdk.py,sha256=reP1TEy05PAjQdHHVobAbt1bqVkSDSqPENGp173Ak7s,33434
67
+ runnable/secrets.py,sha256=4L_dBFxTgr8r_hHUD6RlZEtqaOHDRsFG5PXO5wlvMI0,2324
68
+ runnable/tasks.py,sha256=TUNcFCuu3B0E223EC9z1nx4J2K_P1vkLg7wHIxEuepo,33720
69
+ runnable/utils.py,sha256=amHW3KR_NGTDysGHcSafhh5WJUX7GPBSxqdPyzAIhao,11350
70
+ runnable-0.36.0.dist-info/METADATA,sha256=c4n_9b8IfivaF8SzYELhRFEjRqcE257EYDZNdOSOioY,10166
71
+ runnable-0.36.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
72
+ runnable-0.36.0.dist-info/entry_points.txt,sha256=KkxihZ0LLEiwvFl7RquyqZ0tp2fJDIs7DgzHYDlmc3U,2018
73
+ runnable-0.36.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
74
+ runnable-0.36.0.dist-info/RECORD,,
@@ -8,6 +8,7 @@ minio = extensions.catalog.minio:MinioCatalog
8
8
  s3 = extensions.catalog.s3:S3Catalog
9
9
 
10
10
  [job_executor]
11
+ emulator = extensions.job_executor.emulate:EmulatorJobExecutor
11
12
  k8s-job = extensions.job_executor.k8s:K8sJobExecutor
12
13
  local = extensions.job_executor.local:LocalJobExecutor
13
14
  local-container = extensions.job_executor.local_container:LocalContainerJobExecutor
@@ -15,19 +16,19 @@ mini-k8s-job = extensions.job_executor.k8s:MiniK8sJobExecutor
15
16
 
16
17
  [nodes]
17
18
  conditional = extensions.nodes.conditional:ConditionalNode
18
- dag = extensions.nodes.nodes:DagNode
19
- fail = extensions.nodes.nodes:FailNode
20
- map = extensions.nodes.nodes:MapNode
21
- parallel = extensions.nodes.nodes:ParallelNode
22
- stub = extensions.nodes.nodes:StubNode
23
- success = extensions.nodes.nodes:SuccessNode
24
- task = extensions.nodes.nodes:TaskNode
19
+ fail = extensions.nodes.fail:FailNode
20
+ map = extensions.nodes.map:MapNode
21
+ parallel = extensions.nodes.parallel:ParallelNode
22
+ stub = extensions.nodes.stub:StubNode
23
+ success = extensions.nodes.success:SuccessNode
24
+ task = extensions.nodes.task:TaskNode
25
25
 
26
26
  [pickler]
27
27
  pickle = runnable.pickler:NativePickler
28
28
 
29
29
  [pipeline_executor]
30
30
  argo = extensions.pipeline_executor.argo:ArgoExecutor
31
+ emulator = extensions.pipeline_executor.emulate:Emulator
31
32
  local = extensions.pipeline_executor.local:LocalExecutor
32
33
  local-container = extensions.pipeline_executor.local_container:LocalContainerExecutor
33
34
  mocked = extensions.pipeline_executor.mocked:MockedExecutor