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/datastore.py CHANGED
@@ -113,7 +113,7 @@ class ObjectParameter(BaseModel):
113
113
  return context.run_context.return_objects[self.value]
114
114
 
115
115
  # If the object was serialised, get it from the catalog
116
- catalog_handler = context.run_context.catalog_handler
116
+ catalog_handler = context.run_context.catalog
117
117
  catalog_handler.get(name=self.file_name)
118
118
  obj = context.run_context.pickler.load(path=self.file_name)
119
119
  os.remove(self.file_name) # Remove after loading
@@ -127,7 +127,7 @@ class ObjectParameter(BaseModel):
127
127
  # If the object was serialised, put it in the catalog
128
128
  context.run_context.pickler.dump(data=data, path=self.file_name)
129
129
 
130
- catalog_handler = context.run_context.catalog_handler
130
+ catalog_handler = context.run_context.catalog
131
131
  catalog_handler.put(name=self.file_name)
132
132
  os.remove(self.file_name) # Remove after loading
133
133
 
@@ -400,7 +400,7 @@ class RunLog(BaseModel):
400
400
  summary["Unique execution id"] = self.run_id
401
401
  summary["status"] = self.status
402
402
 
403
- summary["Catalog Location"] = _context.catalog_handler.get_summary()
403
+ summary["Catalog Location"] = _context.catalog.get_summary()
404
404
  summary["Full Run log present at: "] = _context.run_log_store.get_summary()
405
405
 
406
406
  run_log = _context.run_log_store.get_run_log_by_id(
@@ -467,23 +467,29 @@ class RunLog(BaseModel):
467
467
  current_step = None
468
468
  current_branch = None
469
469
 
470
- for i in range(len(dot_path)):
471
- if i % 2:
472
- # Its odd, so we are in branch
473
- # Get the branch that holds the step
474
- current_branch = current_step.branches[".".join(dot_path[: i + 1])] # type: ignore
475
- current_steps = current_branch.steps
476
- logger.debug(f"Finding branch {i_name} in branch: {current_branch}")
477
- else:
478
- # Its even, so we are in step, we start here!
479
- # Get the step that holds the branch
480
- current_step = current_steps[".".join(dot_path[: i + 1])]
481
- logger.debug(f"Finding branch for {i_name} in step: {current_step}")
482
-
483
- logger.debug(f"current branch : {current_branch}, current step {current_step}")
484
- if current_branch and current_step:
485
- return current_branch, current_step
486
-
470
+ try:
471
+ for i in range(len(dot_path)):
472
+ if i % 2:
473
+ # Its odd, so we are in branch
474
+ # Get the branch that holds the step
475
+ current_branch = current_step.branches[".".join(dot_path[: i + 1])] # type: ignore
476
+ current_steps = current_branch.steps
477
+ logger.debug(f"Finding branch {i_name} in branch: {current_branch}")
478
+ else:
479
+ # Its even, so we are in step, we start here!
480
+ # Get the step that holds the branch
481
+ current_step = current_steps[".".join(dot_path[: i + 1])]
482
+ logger.debug(f"Finding branch for {i_name} in step: {current_step}")
483
+
484
+ logger.debug(
485
+ f"current branch : {current_branch}, current step {current_step}"
486
+ )
487
+ if current_branch and current_step:
488
+ return current_branch, current_step
489
+ except KeyError as _e:
490
+ raise exceptions.BranchLogNotFoundError(self.run_id, i_name) from _e
491
+
492
+ # If we are here, we have not found the branch
487
493
  raise exceptions.BranchLogNotFoundError(self.run_id, i_name)
488
494
 
489
495
  def search_step_by_internal_name(
@@ -513,23 +519,31 @@ class RunLog(BaseModel):
513
519
  current_steps = self.steps
514
520
  current_step = None
515
521
  current_branch = None
516
- for i in range(len(dot_path)):
517
- if i % 2:
518
- # Its odd, so we are in brach name
519
- current_branch = current_step.branches[".".join(dot_path[: i + 1])] # type: ignore
520
- current_steps = current_branch.steps
521
- logger.debug(
522
- f"Finding step log for {i_name} in branch: {current_branch}"
523
- )
524
- else:
525
- # Its even, so we are in step, we start here!
526
- current_step = current_steps[".".join(dot_path[: i + 1])]
527
- logger.debug(f"Finding step log for {i_name} in step: {current_step}")
528
-
529
- logger.debug(f"current branch : {current_branch}, current step {current_step}")
530
- if current_branch and current_step:
531
- return current_step, current_branch
532
-
522
+ try:
523
+ for i in range(len(dot_path)):
524
+ if i % 2:
525
+ # Its odd, so we are in brach name
526
+ current_branch = current_step.branches[".".join(dot_path[: i + 1])] # type: ignore
527
+ current_steps = current_branch.steps
528
+ logger.debug(
529
+ f"Finding step log for {i_name} in branch: {current_branch}"
530
+ )
531
+ else:
532
+ # Its even, so we are in step, we start here!
533
+ current_step = current_steps[".".join(dot_path[: i + 1])]
534
+ logger.debug(
535
+ f"Finding step log for {i_name} in step: {current_step}"
536
+ )
537
+
538
+ logger.debug(
539
+ f"current branch : {current_branch}, current step {current_step}"
540
+ )
541
+ if current_branch and current_step:
542
+ return current_step, current_branch
543
+ except KeyError as _e:
544
+ raise exceptions.StepLogNotFoundError(self.run_id, i_name) from _e
545
+
546
+ # If we are here, we have not found the step
533
547
  raise exceptions.StepLogNotFoundError(self.run_id, i_name)
534
548
 
535
549
 
@@ -548,23 +562,6 @@ class BaseRunLogStore(ABC, BaseModel):
548
562
  def _context(self):
549
563
  return context.run_context
550
564
 
551
- """
552
- Retrieves a Job log from the database using the config and the job_id
553
-
554
- Args:
555
- job_id (str): The job_id of the job
556
-
557
- Returns:
558
- JobLog: The JobLog object identified by the job_id
559
-
560
- Logically the method should:
561
- * Returns the job_log defined by id from the data store defined by the config
562
-
563
- Raises:
564
- NotImplementedError: This is a base class and therefore has no default implementation
565
- JobLogNotFoundError: If the job log for job_id is not found in the datastore
566
- """
567
-
568
565
  @abstractmethod
569
566
  def create_run_log(
570
567
  self,
runnable/defaults.py CHANGED
@@ -1,11 +1,4 @@
1
- from typing import (
2
- Any,
3
- Dict,
4
- Mapping,
5
- Optional,
6
- TypedDict, # type: ignore[unused-ignore]
7
- Union,
8
- )
1
+ from typing import Any, Dict, Optional, Union
9
2
 
10
3
  from rich.style import Style
11
4
  from typing_extensions import TypeAlias
@@ -17,26 +10,12 @@ LOGGER_NAME = "runnable"
17
10
  LOG_LEVEL = "WARNING"
18
11
 
19
12
 
20
- # Type definitions
21
- class ServiceConfig(TypedDict):
22
- type: str
23
- config: Mapping[str, Any]
24
-
25
-
26
- class RunnableConfig(TypedDict, total=False):
27
- run_log_store: Optional[ServiceConfig]
28
- secrets: Optional[ServiceConfig]
29
- catalog: Optional[ServiceConfig]
30
- pipeline_executor: Optional[ServiceConfig]
31
- pickler: Optional[ServiceConfig]
32
-
33
-
34
- TypeMapVariable: TypeAlias = Optional[Dict[str, Union[str, int, float]]]
35
-
13
+ MapVariableType: TypeAlias = Optional[Dict[str, Union[str, int, float]]]
36
14
 
37
15
  # Config file environment variable
38
- RUNNABLE_CONFIG_FILE = "RUNNABLE_CONFIG_FILE"
16
+ RUNNABLE_CONFIGURATION_FILE = "RUNNABLE_CONFIGURATION_FILE"
39
17
  RUNNABLE_RUN_TAG = "RUNNABLE_RUN_TAG"
18
+ RUNNABLE_PARAMETERS_FILE = "RUNNABLE_PARAMETERS_FILE"
40
19
 
41
20
  # Interaction settings
42
21
  TRACK_PREFIX = "RUNNABLE_TRACK_"
@@ -56,19 +35,20 @@ CREATED = "CREATED"
56
35
  PROCESSING = "PROCESSING"
57
36
  SUCCESS = "SUCCESS"
58
37
  FAIL = "FAIL"
59
- TRIGGERED = "TRIGGERED"
60
38
 
61
39
  # Node and Command settings
62
40
  COMMAND_TYPE = "python"
63
41
  COMMAND_FRIENDLY_CHARACTER = "%"
64
42
 
65
43
  # Default services
66
- DEFAULT_PIPELINE_EXECUTOR = ServiceConfig(type="local", config={})
67
- DEFAULT_JOB_EXECUTOR = ServiceConfig(type="local", config={})
68
- DEFAULT_RUN_LOG_STORE = ServiceConfig(type="file-system", config={})
69
- DEFAULT_CATALOG = ServiceConfig(type="file-system", config={})
70
- DEFAULT_SECRETS = ServiceConfig(type="env-secrets", config={})
71
- DEFAULT_PICKLER = ServiceConfig(type="pickle", config={})
44
+ DEFAULT_SERVICES: dict[str, Any] = {
45
+ "pipeline_executor": {"type": "local", "config": {}},
46
+ "job_executor": {"type": "local", "config": {}},
47
+ "run_log_store": {"type": "file-system", "config": {}},
48
+ "catalog": {"type": "file-system", "config": {}},
49
+ "pickler": {"type": "pickle", "config": {}},
50
+ "secrets": {"type": "env-secrets", "config": {}},
51
+ }
72
52
 
73
53
  # Map state
74
54
  MAP_PLACEHOLDER = "map_variable_placeholder"
@@ -83,8 +63,6 @@ MAX_TIME = 86400 # 1 day in seconds
83
63
  # User extensions
84
64
  USER_CONFIG_FILE = "runnable-config.yaml"
85
65
 
86
- # Executor settings
87
- ENABLE_PARALLEL = False
88
66
 
89
67
  # RUN log store settings
90
68
  LOG_LOCATION_FOLDER = ".run_log_store"