runnable 0.12.3__py3-none-any.whl → 0.14.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.
- runnable/__init__.py +0 -11
 - runnable/catalog.py +27 -5
 - runnable/cli.py +122 -26
 - runnable/datastore.py +71 -35
 - runnable/defaults.py +0 -1
 - runnable/entrypoints.py +107 -32
 - runnable/exceptions.py +6 -2
 - runnable/executor.py +28 -9
 - runnable/graph.py +37 -12
 - runnable/integration.py +7 -2
 - runnable/nodes.py +15 -17
 - runnable/parameters.py +27 -8
 - runnable/pickler.py +1 -1
 - runnable/sdk.py +101 -33
 - runnable/secrets.py +3 -1
 - runnable/tasks.py +246 -34
 - runnable/utils.py +41 -13
 - {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info}/METADATA +25 -31
 - runnable-0.14.0.dist-info/RECORD +24 -0
 - {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info}/WHEEL +1 -1
 - runnable-0.14.0.dist-info/entry_points.txt +40 -0
 - runnable/extensions/__init__.py +0 -0
 - runnable/extensions/catalog/__init__.py +0 -21
 - runnable/extensions/catalog/file_system/__init__.py +0 -0
 - runnable/extensions/catalog/file_system/implementation.py +0 -234
 - runnable/extensions/catalog/k8s_pvc/__init__.py +0 -0
 - runnable/extensions/catalog/k8s_pvc/implementation.py +0 -16
 - runnable/extensions/catalog/k8s_pvc/integration.py +0 -59
 - runnable/extensions/executor/__init__.py +0 -649
 - runnable/extensions/executor/argo/__init__.py +0 -0
 - runnable/extensions/executor/argo/implementation.py +0 -1194
 - runnable/extensions/executor/argo/specification.yaml +0 -51
 - runnable/extensions/executor/k8s_job/__init__.py +0 -0
 - runnable/extensions/executor/k8s_job/implementation_FF.py +0 -259
 - runnable/extensions/executor/k8s_job/integration_FF.py +0 -69
 - runnable/extensions/executor/local/__init__.py +0 -0
 - runnable/extensions/executor/local/implementation.py +0 -71
 - runnable/extensions/executor/local_container/__init__.py +0 -0
 - runnable/extensions/executor/local_container/implementation.py +0 -446
 - runnable/extensions/executor/mocked/__init__.py +0 -0
 - runnable/extensions/executor/mocked/implementation.py +0 -154
 - runnable/extensions/executor/retry/__init__.py +0 -0
 - runnable/extensions/executor/retry/implementation.py +0 -168
 - runnable/extensions/nodes.py +0 -855
 - runnable/extensions/run_log_store/__init__.py +0 -0
 - runnable/extensions/run_log_store/chunked_file_system/__init__.py +0 -0
 - runnable/extensions/run_log_store/chunked_file_system/implementation.py +0 -111
 - runnable/extensions/run_log_store/chunked_k8s_pvc/__init__.py +0 -0
 - runnable/extensions/run_log_store/chunked_k8s_pvc/implementation.py +0 -21
 - runnable/extensions/run_log_store/chunked_k8s_pvc/integration.py +0 -61
 - runnable/extensions/run_log_store/db/implementation_FF.py +0 -157
 - runnable/extensions/run_log_store/db/integration_FF.py +0 -0
 - runnable/extensions/run_log_store/file_system/__init__.py +0 -0
 - runnable/extensions/run_log_store/file_system/implementation.py +0 -140
 - runnable/extensions/run_log_store/generic_chunked.py +0 -557
 - runnable/extensions/run_log_store/k8s_pvc/__init__.py +0 -0
 - runnable/extensions/run_log_store/k8s_pvc/implementation.py +0 -21
 - runnable/extensions/run_log_store/k8s_pvc/integration.py +0 -56
 - runnable/extensions/secrets/__init__.py +0 -0
 - runnable/extensions/secrets/dotenv/__init__.py +0 -0
 - runnable/extensions/secrets/dotenv/implementation.py +0 -100
 - runnable-0.12.3.dist-info/RECORD +0 -64
 - runnable-0.12.3.dist-info/entry_points.txt +0 -41
 - {runnable-0.12.3.dist-info → runnable-0.14.0.dist-info/licenses}/LICENSE +0 -0
 
    
        runnable/__init__.py
    CHANGED
    
    | 
         @@ -34,14 +34,3 @@ from runnable.sdk import (  # noqa 
     | 
|
| 
       34 
34 
     | 
    
         | 
| 
       35 
35 
     | 
    
         
             
            # Needed to disable ploomber telemetry
         
     | 
| 
       36 
36 
     | 
    
         
             
            os.environ["PLOOMBER_STATS_ENABLED"] = "false"
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
            ## TODO: Summary should be a bit better for catalog.
         
     | 
| 
       39 
     | 
    
         
            -
            ## If the execution fails, hint them about the retry executor.
         
     | 
| 
       40 
     | 
    
         
            -
            # Make the retry executor loose!
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
            # TODO: Think of model registry as a central place to store models.
         
     | 
| 
       43 
     | 
    
         
            -
            # TODO: Implement Sagemaker pipelines as a executor.
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
            # TODO: Think of way of generating dag hash without executor configuration
         
     | 
| 
       47 
     | 
    
         
            -
            # Try to get a release
         
     | 
    
        runnable/catalog.py
    CHANGED
    
    | 
         @@ -11,6 +11,26 @@ from runnable.datastore import DataCatalog 
     | 
|
| 
       11 
11 
     | 
    
         
             
            logger = logging.getLogger(defaults.LOGGER_NAME)
         
     | 
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         | 
| 
      
 14 
     | 
    
         
            +
            def is_catalog_out_of_sync(
         
     | 
| 
      
 15 
     | 
    
         
            +
                catalog, synced_catalogs=Optional[List[DataCatalog]]
         
     | 
| 
      
 16 
     | 
    
         
            +
            ) -> bool:
         
     | 
| 
      
 17 
     | 
    
         
            +
                """
         
     | 
| 
      
 18 
     | 
    
         
            +
                Check if the catalog items are out of sync from already cataloged objects.
         
     | 
| 
      
 19 
     | 
    
         
            +
                If they are, return False.
         
     | 
| 
      
 20 
     | 
    
         
            +
                If the object does not exist or synced catalog does not exist, return True
         
     | 
| 
      
 21 
     | 
    
         
            +
                """
         
     | 
| 
      
 22 
     | 
    
         
            +
                if not synced_catalogs:
         
     | 
| 
      
 23 
     | 
    
         
            +
                    return True  # If nothing has been synced in the past
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                for synced_catalog in synced_catalogs:
         
     | 
| 
      
 26 
     | 
    
         
            +
                    if synced_catalog.catalog_relative_path == catalog.catalog_relative_path:
         
     | 
| 
      
 27 
     | 
    
         
            +
                        if synced_catalog.data_hash == catalog.data_hash:
         
     | 
| 
      
 28 
     | 
    
         
            +
                            return False
         
     | 
| 
      
 29 
     | 
    
         
            +
                        return True
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                return True  # The object does not exist, sync it
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
       14 
34 
     | 
    
         
             
            # --8<-- [start:docs]
         
     | 
| 
       15 
35 
     | 
    
         | 
| 
       16 
36 
     | 
    
         | 
| 
         @@ -26,8 +46,7 @@ class BaseCatalog(ABC, BaseModel): 
     | 
|
| 
       26 
46 
     | 
    
         
             
                model_config = ConfigDict(extra="forbid")
         
     | 
| 
       27 
47 
     | 
    
         | 
| 
       28 
48 
     | 
    
         
             
                @abstractmethod
         
     | 
| 
       29 
     | 
    
         
            -
                def get_summary(self) -> Dict[str, Any]:
         
     | 
| 
       30 
     | 
    
         
            -
                    ...
         
     | 
| 
      
 49 
     | 
    
         
            +
                def get_summary(self) -> Dict[str, Any]: ...
         
     | 
| 
       31 
50 
     | 
    
         | 
| 
       32 
51 
     | 
    
         
             
                @property
         
     | 
| 
       33 
52 
     | 
    
         
             
                def _context(self):
         
     | 
| 
         @@ -38,7 +57,9 @@ class BaseCatalog(ABC, BaseModel): 
     | 
|
| 
       38 
57 
     | 
    
         
             
                    return defaults.COMPUTE_DATA_FOLDER
         
     | 
| 
       39 
58 
     | 
    
         | 
| 
       40 
59 
     | 
    
         
             
                @abstractmethod
         
     | 
| 
       41 
     | 
    
         
            -
                def get( 
     | 
| 
      
 60 
     | 
    
         
            +
                def get(
         
     | 
| 
      
 61 
     | 
    
         
            +
                    self, name: str, run_id: str, compute_data_folder: str = "", **kwargs
         
     | 
| 
      
 62 
     | 
    
         
            +
                ) -> List[DataCatalog]:
         
     | 
| 
       42 
63 
     | 
    
         
             
                    """
         
     | 
| 
       43 
64 
     | 
    
         
             
                    Get the catalog item by 'name' for the 'run id' and store it in compute data folder.
         
     | 
| 
       44 
65 
     | 
    
         | 
| 
         @@ -119,7 +140,9 @@ class DoNothingCatalog(BaseCatalog): 
     | 
|
| 
       119 
140 
     | 
    
         
             
                def get_summary(self) -> Dict[str, Any]:
         
     | 
| 
       120 
141 
     | 
    
         
             
                    return {}
         
     | 
| 
       121 
142 
     | 
    
         | 
| 
       122 
     | 
    
         
            -
                def get( 
     | 
| 
      
 143 
     | 
    
         
            +
                def get(
         
     | 
| 
      
 144 
     | 
    
         
            +
                    self, name: str, run_id: str, compute_data_folder: str = "", **kwargs
         
     | 
| 
      
 145 
     | 
    
         
            +
                ) -> List[DataCatalog]:
         
     | 
| 
       123 
146 
     | 
    
         
             
                    """
         
     | 
| 
       124 
147 
     | 
    
         
             
                    Does nothing
         
     | 
| 
       125 
148 
     | 
    
         
             
                    """
         
     | 
| 
         @@ -145,4 +168,3 @@ class DoNothingCatalog(BaseCatalog): 
     | 
|
| 
       145 
168 
     | 
    
         
             
                    Does nothing
         
     | 
| 
       146 
169 
     | 
    
         
             
                    """
         
     | 
| 
       147 
170 
     | 
    
         
             
                    logger.info("Using a do-nothing catalog, doing nothing while sync between runs")
         
     | 
| 
       148 
     | 
    
         
            -
                    ...
         
     | 
    
        runnable/cli.py
    CHANGED
    
    | 
         @@ -22,9 +22,13 @@ def cli(): 
     | 
|
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
24 
     | 
    
         
             
            @cli.command("execute", short_help="Execute/translate a pipeline")
         
     | 
| 
       25 
     | 
    
         
            -
            @click. 
     | 
| 
      
 25 
     | 
    
         
            +
            @click.argument("filename")
         
     | 
| 
       26 
26 
     | 
    
         
             
            @click.option(
         
     | 
| 
       27 
     | 
    
         
            -
                "-c", 
     | 
| 
      
 27 
     | 
    
         
            +
                "-c",
         
     | 
| 
      
 28 
     | 
    
         
            +
                "--config-file",
         
     | 
| 
      
 29 
     | 
    
         
            +
                default=None,
         
     | 
| 
      
 30 
     | 
    
         
            +
                help="config file, in yaml, to be used for the run",
         
     | 
| 
      
 31 
     | 
    
         
            +
                show_default=True,
         
     | 
| 
       28 
32 
     | 
    
         
             
            )
         
     | 
| 
       29 
33 
     | 
    
         
             
            @click.option(
         
     | 
| 
       30 
34 
     | 
    
         
             
                "-p",
         
     | 
| 
         @@ -41,8 +45,12 @@ def cli(): 
     | 
|
| 
       41 
45 
     | 
    
         
             
                type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
         
     | 
| 
       42 
46 
     | 
    
         
             
            )
         
     | 
| 
       43 
47 
     | 
    
         
             
            @click.option("--tag", default="", help="A tag attached to the run")
         
     | 
| 
       44 
     | 
    
         
            -
            @click.option( 
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
      
 48 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 49 
     | 
    
         
            +
                "--run-id", help="An optional run_id, one would be generated if not provided"
         
     | 
| 
      
 50 
     | 
    
         
            +
            )
         
     | 
| 
      
 51 
     | 
    
         
            +
            def execute(
         
     | 
| 
      
 52 
     | 
    
         
            +
                filename, config_file, parameters_file, log_level, tag, run_id
         
     | 
| 
      
 53 
     | 
    
         
            +
            ):  # pragma: no cover
         
     | 
| 
       46 
54 
     | 
    
         
             
                """
         
     | 
| 
       47 
55 
     | 
    
         
             
                Execute a pipeline
         
     | 
| 
       48 
56 
     | 
    
         | 
| 
         @@ -64,20 +72,35 @@ def execute(file, config_file, parameters_file, log_level, tag, run_id):  # prag 
     | 
|
| 
       64 
72 
     | 
    
         | 
| 
       65 
73 
     | 
    
         
             
                entrypoints.execute(
         
     | 
| 
       66 
74 
     | 
    
         
             
                    configuration_file=config_file,
         
     | 
| 
       67 
     | 
    
         
            -
                    pipeline_file= 
     | 
| 
      
 75 
     | 
    
         
            +
                    pipeline_file=filename,
         
     | 
| 
       68 
76 
     | 
    
         
             
                    tag=tag,
         
     | 
| 
       69 
77 
     | 
    
         
             
                    run_id=run_id,
         
     | 
| 
       70 
78 
     | 
    
         
             
                    parameters_file=parameters_file,
         
     | 
| 
       71 
79 
     | 
    
         
             
                )
         
     | 
| 
       72 
80 
     | 
    
         | 
| 
       73 
81 
     | 
    
         | 
| 
       74 
     | 
    
         
            -
            @cli.command( 
     | 
| 
      
 82 
     | 
    
         
            +
            @cli.command(
         
     | 
| 
      
 83 
     | 
    
         
            +
                "execute_single_node",
         
     | 
| 
      
 84 
     | 
    
         
            +
                short_help="Internal entry point to execute a single node",
         
     | 
| 
      
 85 
     | 
    
         
            +
                hidden=True,
         
     | 
| 
      
 86 
     | 
    
         
            +
            )
         
     | 
| 
       75 
87 
     | 
    
         
             
            @click.argument("run_id")
         
     | 
| 
       76 
88 
     | 
    
         
             
            @click.argument("step_name")
         
     | 
| 
       77 
     | 
    
         
            -
            @click.option("--map-variable", default="", help="The map variable dictionary in str", show_default=True)
         
     | 
| 
       78 
     | 
    
         
            -
            @click.option("-f", "--file", default="", help="The pipeline definition file", show_default=True)
         
     | 
| 
       79 
89 
     | 
    
         
             
            @click.option(
         
     | 
| 
       80 
     | 
    
         
            -
                " 
     | 
| 
      
 90 
     | 
    
         
            +
                "--map-variable",
         
     | 
| 
      
 91 
     | 
    
         
            +
                default="",
         
     | 
| 
      
 92 
     | 
    
         
            +
                help="The map variable dictionary in str",
         
     | 
| 
      
 93 
     | 
    
         
            +
                show_default=True,
         
     | 
| 
      
 94 
     | 
    
         
            +
            )
         
     | 
| 
      
 95 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 96 
     | 
    
         
            +
                "-f", "--file", default="", help="The pipeline definition file", show_default=True
         
     | 
| 
      
 97 
     | 
    
         
            +
            )
         
     | 
| 
      
 98 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 99 
     | 
    
         
            +
                "-c",
         
     | 
| 
      
 100 
     | 
    
         
            +
                "--config-file",
         
     | 
| 
      
 101 
     | 
    
         
            +
                default=None,
         
     | 
| 
      
 102 
     | 
    
         
            +
                help="config file, in yaml, to be used for the run",
         
     | 
| 
      
 103 
     | 
    
         
            +
                show_default=True,
         
     | 
| 
       81 
104 
     | 
    
         
             
            )
         
     | 
| 
       82 
105 
     | 
    
         
             
            @click.option(
         
     | 
| 
       83 
106 
     | 
    
         
             
                "-p",
         
     | 
| 
         @@ -94,7 +117,9 @@ def execute(file, config_file, parameters_file, log_level, tag, run_id):  # prag 
     | 
|
| 
       94 
117 
     | 
    
         
             
                type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
         
     | 
| 
       95 
118 
     | 
    
         
             
            )
         
     | 
| 
       96 
119 
     | 
    
         
             
            @click.option("--tag", default="", help="A tag attached to the run")
         
     | 
| 
       97 
     | 
    
         
            -
            def execute_single_node( 
     | 
| 
      
 120 
     | 
    
         
            +
            def execute_single_node(
         
     | 
| 
      
 121 
     | 
    
         
            +
                run_id, step_name, map_variable, file, config_file, parameters_file, log_level, tag
         
     | 
| 
      
 122 
     | 
    
         
            +
            ):
         
     | 
| 
       98 
123 
     | 
    
         
             
                """
         
     | 
| 
       99 
124 
     | 
    
         
             
                Internal entrypoint for runnable to execute a single node.
         
     | 
| 
       100 
125 
     | 
    
         | 
| 
         @@ -119,7 +144,11 @@ def execute_single_node(run_id, step_name, map_variable, file, config_file, para 
     | 
|
| 
       119 
144 
     | 
    
         
             
            @click.argument("filename")
         
     | 
| 
       120 
145 
     | 
    
         
             
            @click.option("--entrypoint", default=defaults.ENTRYPOINT.USER.value, hidden=True)
         
     | 
| 
       121 
146 
     | 
    
         
             
            @click.option(
         
     | 
| 
       122 
     | 
    
         
            -
                "-c", 
     | 
| 
      
 147 
     | 
    
         
            +
                "-c",
         
     | 
| 
      
 148 
     | 
    
         
            +
                "--config-file",
         
     | 
| 
      
 149 
     | 
    
         
            +
                default=None,
         
     | 
| 
      
 150 
     | 
    
         
            +
                help="config file, in yaml, to be used for the run",
         
     | 
| 
      
 151 
     | 
    
         
            +
                show_default=True,
         
     | 
| 
       123 
152 
     | 
    
         
             
            )
         
     | 
| 
       124 
153 
     | 
    
         
             
            @click.option(
         
     | 
| 
       125 
154 
     | 
    
         
             
                "-p",
         
     | 
| 
         @@ -136,10 +165,20 @@ def execute_single_node(run_id, step_name, map_variable, file, config_file, para 
     | 
|
| 
       136 
165 
     | 
    
         
             
                type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
         
     | 
| 
       137 
166 
     | 
    
         
             
            )
         
     | 
| 
       138 
167 
     | 
    
         
             
            @click.option("--data-folder", "-d", default="data/", help="The catalog data folder")
         
     | 
| 
       139 
     | 
    
         
            -
            @click.option( 
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
      
 168 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 169 
     | 
    
         
            +
                "--put-in-catalog",
         
     | 
| 
      
 170 
     | 
    
         
            +
                "-put",
         
     | 
| 
      
 171 
     | 
    
         
            +
                default=None,
         
     | 
| 
      
 172 
     | 
    
         
            +
                multiple=True,
         
     | 
| 
      
 173 
     | 
    
         
            +
                help="The data to put from the catalog",
         
     | 
| 
      
 174 
     | 
    
         
            +
            )
         
     | 
| 
      
 175 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 176 
     | 
    
         
            +
                "--notebook-output-path", default="", help="The output path for the notebook"
         
     | 
| 
      
 177 
     | 
    
         
            +
            )
         
     | 
| 
       141 
178 
     | 
    
         
             
            @click.option("--tag", help="A tag attached to the run")
         
     | 
| 
       142 
     | 
    
         
            -
            @click.option( 
     | 
| 
      
 179 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 180 
     | 
    
         
            +
                "--run-id", help="An optional run_id, one would be generated if not provided"
         
     | 
| 
      
 181 
     | 
    
         
            +
            )
         
     | 
| 
       143 
182 
     | 
    
         
             
            def execute_notebook(
         
     | 
| 
       144 
183 
     | 
    
         
             
                filename,
         
     | 
| 
       145 
184 
     | 
    
         
             
                entrypoint,
         
     | 
| 
         @@ -159,7 +198,10 @@ def execute_notebook( 
     | 
|
| 
       159 
198 
     | 
    
         
             
                The execution plan is unchained.
         
     | 
| 
       160 
199 
     | 
    
         
             
                """
         
     | 
| 
       161 
200 
     | 
    
         
             
                logger.setLevel(log_level)
         
     | 
| 
       162 
     | 
    
         
            -
                catalog_config = { 
     | 
| 
      
 201 
     | 
    
         
            +
                catalog_config = {
         
     | 
| 
      
 202 
     | 
    
         
            +
                    "compute_data_folder": data_folder,
         
     | 
| 
      
 203 
     | 
    
         
            +
                    "put": list(put_in_catalog) if put_in_catalog else None,
         
     | 
| 
      
 204 
     | 
    
         
            +
                }
         
     | 
| 
       163 
205 
     | 
    
         
             
                if not filename.endswith(".ipynb"):
         
     | 
| 
       164 
206 
     | 
    
         
             
                    raise Exception("A notebook should always have ipynb as the extension")
         
     | 
| 
       165 
207 
     | 
    
         | 
| 
         @@ -179,7 +221,11 @@ def execute_notebook( 
     | 
|
| 
       179 
221 
     | 
    
         
             
            @click.argument("command")
         
     | 
| 
       180 
222 
     | 
    
         
             
            @click.option("--entrypoint", default=defaults.ENTRYPOINT.USER.value, hidden=True)
         
     | 
| 
       181 
223 
     | 
    
         
             
            @click.option(
         
     | 
| 
       182 
     | 
    
         
            -
                "-c", 
     | 
| 
      
 224 
     | 
    
         
            +
                "-c",
         
     | 
| 
      
 225 
     | 
    
         
            +
                "--config-file",
         
     | 
| 
      
 226 
     | 
    
         
            +
                default=None,
         
     | 
| 
      
 227 
     | 
    
         
            +
                help="config file, in yaml, to be used for the run",
         
     | 
| 
      
 228 
     | 
    
         
            +
                show_default=True,
         
     | 
| 
       183 
229 
     | 
    
         
             
            )
         
     | 
| 
       184 
230 
     | 
    
         
             
            @click.option(
         
     | 
| 
       185 
231 
     | 
    
         
             
                "-p",
         
     | 
| 
         @@ -196,11 +242,27 @@ def execute_notebook( 
     | 
|
| 
       196 
242 
     | 
    
         
             
                type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
         
     | 
| 
       197 
243 
     | 
    
         
             
            )
         
     | 
| 
       198 
244 
     | 
    
         
             
            @click.option("--data-folder", "-d", default="data/", help="The catalog data folder")
         
     | 
| 
       199 
     | 
    
         
            -
            @click.option( 
     | 
| 
      
 245 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 246 
     | 
    
         
            +
                "--put-in-catalog",
         
     | 
| 
      
 247 
     | 
    
         
            +
                "-put",
         
     | 
| 
      
 248 
     | 
    
         
            +
                default=None,
         
     | 
| 
      
 249 
     | 
    
         
            +
                multiple=True,
         
     | 
| 
      
 250 
     | 
    
         
            +
                help="The data to put from the catalog",
         
     | 
| 
      
 251 
     | 
    
         
            +
            )
         
     | 
| 
       200 
252 
     | 
    
         
             
            @click.option("--tag", help="A tag attached to the run")
         
     | 
| 
       201 
     | 
    
         
            -
            @click.option( 
     | 
| 
      
 253 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 254 
     | 
    
         
            +
                "--run-id", help="An optional run_id, one would be generated if not provided"
         
     | 
| 
      
 255 
     | 
    
         
            +
            )
         
     | 
| 
       202 
256 
     | 
    
         
             
            def execute_function(
         
     | 
| 
       203 
     | 
    
         
            -
                command, 
     | 
| 
      
 257 
     | 
    
         
            +
                command,
         
     | 
| 
      
 258 
     | 
    
         
            +
                entrypoint,
         
     | 
| 
      
 259 
     | 
    
         
            +
                config_file,
         
     | 
| 
      
 260 
     | 
    
         
            +
                parameters_file,
         
     | 
| 
      
 261 
     | 
    
         
            +
                log_level,
         
     | 
| 
      
 262 
     | 
    
         
            +
                data_folder,
         
     | 
| 
      
 263 
     | 
    
         
            +
                put_in_catalog,
         
     | 
| 
      
 264 
     | 
    
         
            +
                tag,
         
     | 
| 
      
 265 
     | 
    
         
            +
                run_id,
         
     | 
| 
       204 
266 
     | 
    
         
             
            ):
         
     | 
| 
       205 
267 
     | 
    
         
             
                """
         
     | 
| 
       206 
268 
     | 
    
         
             
                External entry point to execute a python function in isolation.
         
     | 
| 
         @@ -209,7 +271,10 @@ def execute_function( 
     | 
|
| 
       209 
271 
     | 
    
         
             
                The execution plan is unchained.
         
     | 
| 
       210 
272 
     | 
    
         
             
                """
         
     | 
| 
       211 
273 
     | 
    
         
             
                logger.setLevel(log_level)
         
     | 
| 
       212 
     | 
    
         
            -
                catalog_config = { 
     | 
| 
      
 274 
     | 
    
         
            +
                catalog_config = {
         
     | 
| 
      
 275 
     | 
    
         
            +
                    "compute_data_folder": data_folder,
         
     | 
| 
      
 276 
     | 
    
         
            +
                    "put": list(put_in_catalog) if put_in_catalog else None,
         
     | 
| 
      
 277 
     | 
    
         
            +
                }
         
     | 
| 
       213 
278 
     | 
    
         
             
                entrypoints.execute_function(
         
     | 
| 
       214 
279 
     | 
    
         
             
                    entrypoint=entrypoint,
         
     | 
| 
       215 
280 
     | 
    
         
             
                    command=command,
         
     | 
| 
         @@ -221,14 +286,35 @@ def execute_function( 
     | 
|
| 
       221 
286 
     | 
    
         
             
                )
         
     | 
| 
       222 
287 
     | 
    
         | 
| 
       223 
288 
     | 
    
         | 
| 
       224 
     | 
    
         
            -
            @cli.command( 
     | 
| 
      
 289 
     | 
    
         
            +
            @cli.command(
         
     | 
| 
      
 290 
     | 
    
         
            +
                "fan",
         
     | 
| 
      
 291 
     | 
    
         
            +
                short_help="Internal entry point to fan in or out a composite node",
         
     | 
| 
      
 292 
     | 
    
         
            +
                hidden=True,
         
     | 
| 
      
 293 
     | 
    
         
            +
            )
         
     | 
| 
       225 
294 
     | 
    
         
             
            @click.argument("run_id")
         
     | 
| 
       226 
295 
     | 
    
         
             
            @click.argument("step_name")
         
     | 
| 
       227 
     | 
    
         
            -
            @click.option("-m", "--mode", help="fan in or fan out", required=True, type=click.Choice(["in", "out"]))
         
     | 
| 
       228 
     | 
    
         
            -
            @click.option("--map-variable", default="", help="The map variable dictionary in str", show_default=True)
         
     | 
| 
       229 
     | 
    
         
            -
            @click.option("-f", "--file", default="", help="The pipeline definition file", show_default=True)
         
     | 
| 
       230 
296 
     | 
    
         
             
            @click.option(
         
     | 
| 
       231 
     | 
    
         
            -
                "- 
     | 
| 
      
 297 
     | 
    
         
            +
                "-m",
         
     | 
| 
      
 298 
     | 
    
         
            +
                "--mode",
         
     | 
| 
      
 299 
     | 
    
         
            +
                help="fan in or fan out",
         
     | 
| 
      
 300 
     | 
    
         
            +
                required=True,
         
     | 
| 
      
 301 
     | 
    
         
            +
                type=click.Choice(["in", "out"]),
         
     | 
| 
      
 302 
     | 
    
         
            +
            )
         
     | 
| 
      
 303 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 304 
     | 
    
         
            +
                "--map-variable",
         
     | 
| 
      
 305 
     | 
    
         
            +
                default="",
         
     | 
| 
      
 306 
     | 
    
         
            +
                help="The map variable dictionary in str",
         
     | 
| 
      
 307 
     | 
    
         
            +
                show_default=True,
         
     | 
| 
      
 308 
     | 
    
         
            +
            )
         
     | 
| 
      
 309 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 310 
     | 
    
         
            +
                "-f", "--file", default="", help="The pipeline definition file", show_default=True
         
     | 
| 
      
 311 
     | 
    
         
            +
            )
         
     | 
| 
      
 312 
     | 
    
         
            +
            @click.option(
         
     | 
| 
      
 313 
     | 
    
         
            +
                "-c",
         
     | 
| 
      
 314 
     | 
    
         
            +
                "--config-file",
         
     | 
| 
      
 315 
     | 
    
         
            +
                default=None,
         
     | 
| 
      
 316 
     | 
    
         
            +
                help="config file, in yaml, to be used for the run",
         
     | 
| 
      
 317 
     | 
    
         
            +
                show_default=True,
         
     | 
| 
       232 
318 
     | 
    
         
             
            )
         
     | 
| 
       233 
319 
     | 
    
         
             
            @click.option(
         
     | 
| 
       234 
320 
     | 
    
         
             
                "-p",
         
     | 
| 
         @@ -245,7 +331,17 @@ def execute_function( 
     | 
|
| 
       245 
331 
     | 
    
         
             
                type=click.Choice(["INFO", "DEBUG", "WARNING", "ERROR", "FATAL"]),
         
     | 
| 
       246 
332 
     | 
    
         
             
            )
         
     | 
| 
       247 
333 
     | 
    
         
             
            @click.option("--tag", default="", help="A tag attached to the run")
         
     | 
| 
       248 
     | 
    
         
            -
            def fan( 
     | 
| 
      
 334 
     | 
    
         
            +
            def fan(
         
     | 
| 
      
 335 
     | 
    
         
            +
                run_id,
         
     | 
| 
      
 336 
     | 
    
         
            +
                step_name,
         
     | 
| 
      
 337 
     | 
    
         
            +
                mode,
         
     | 
| 
      
 338 
     | 
    
         
            +
                map_variable,
         
     | 
| 
      
 339 
     | 
    
         
            +
                file,
         
     | 
| 
      
 340 
     | 
    
         
            +
                config_file,
         
     | 
| 
      
 341 
     | 
    
         
            +
                parameters_file,
         
     | 
| 
      
 342 
     | 
    
         
            +
                log_level,
         
     | 
| 
      
 343 
     | 
    
         
            +
                tag,
         
     | 
| 
      
 344 
     | 
    
         
            +
            ):
         
     | 
| 
       249 
345 
     | 
    
         
             
                """
         
     | 
| 
       250 
346 
     | 
    
         
             
                Internal entrypoint for runnable to fan in or out a composite node.
         
     | 
| 
       251 
347 
     | 
    
         | 
    
        runnable/datastore.py
    CHANGED
    
    | 
         @@ -18,7 +18,6 @@ from typing import ( 
     | 
|
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
            from pydantic import BaseModel, Field, computed_field
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
            import runnable.context as context
         
     | 
| 
       22 
21 
     | 
    
         
             
            from runnable import defaults, exceptions
         
     | 
| 
       23 
22 
     | 
    
         | 
| 
       24 
23 
     | 
    
         
             
            logger = logging.getLogger(defaults.LOGGER_NAME)
         
     | 
| 
         @@ -56,14 +55,11 @@ class DataCatalog(BaseModel, extra="allow"): 
     | 
|
| 
       56 
55 
     | 
    
         
             
                    return other.name == self.name
         
     | 
| 
       57 
56 
     | 
    
         | 
| 
       58 
57 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                Once the map state is complete, we can set the reduce to true and have the value as
         
     | 
| 
       65 
     | 
    
         
            -
                the reduced value. Its either a list or a custom function return.
         
     | 
| 
       66 
     | 
    
         
            -
            """
         
     | 
| 
      
 58 
     | 
    
         
            +
            # The theory behind reduced:
         
     | 
| 
      
 59 
     | 
    
         
            +
            #     parameters returned by steps in map node are only reduced by the end of the map step, fan-in.
         
     | 
| 
      
 60 
     | 
    
         
            +
            #     If they are accessed within the map step, the value should be the value returned by the step in the map step.
         
     | 
| 
      
 61 
     | 
    
         
            +
            #     Once the map state is complete, we can set the reduce to true and have the value as
         
     | 
| 
      
 62 
     | 
    
         
            +
            #     the reduced value. Its either a list or a custom function return.
         
     | 
| 
       67 
63 
     | 
    
         | 
| 
       68 
64 
     | 
    
         | 
| 
       69 
65 
     | 
    
         
             
            class JsonParameter(BaseModel):
         
     | 
| 
         @@ -125,7 +121,9 @@ class ObjectParameter(BaseModel): 
     | 
|
| 
       125 
121 
     | 
    
         
             
                    os.remove(self.file_name)  # Remove after loading
         
     | 
| 
       126 
122 
     | 
    
         | 
| 
       127 
123 
     | 
    
         | 
| 
       128 
     | 
    
         
            -
            Parameter = Annotated[ 
     | 
| 
      
 124 
     | 
    
         
            +
            Parameter = Annotated[
         
     | 
| 
      
 125 
     | 
    
         
            +
                Union[JsonParameter, ObjectParameter, MetricParameter], Field(discriminator="kind")
         
     | 
| 
      
 126 
     | 
    
         
            +
            ]
         
     | 
| 
       129 
127 
     | 
    
         | 
| 
       130 
128 
     | 
    
         | 
| 
       131 
129 
     | 
    
         
             
            class StepAttempt(BaseModel):
         
     | 
| 
         @@ -157,8 +155,12 @@ class CodeIdentity(BaseModel, extra="allow"): 
     | 
|
| 
       157 
155 
     | 
    
         | 
| 
       158 
156 
     | 
    
         
             
                code_identifier: Optional[str] = ""  # GIT sha code or docker image id
         
     | 
| 
       159 
157 
     | 
    
         
             
                code_identifier_type: Optional[str] = ""  # git or docker
         
     | 
| 
       160 
     | 
    
         
            -
                code_identifier_dependable: Optional[bool] =  
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
      
 158 
     | 
    
         
            +
                code_identifier_dependable: Optional[bool] = (
         
     | 
| 
      
 159 
     | 
    
         
            +
                    False  # If git, checks if the tree is clean.
         
     | 
| 
      
 160 
     | 
    
         
            +
                )
         
     | 
| 
      
 161 
     | 
    
         
            +
                code_identifier_url: Optional[str] = (
         
     | 
| 
      
 162 
     | 
    
         
            +
                    ""  # The git remote url or docker repository url
         
     | 
| 
      
 163 
     | 
    
         
            +
                )
         
     | 
| 
       162 
164 
     | 
    
         
             
                code_identifier_message: Optional[str] = ""  # Any optional message
         
     | 
| 
       163 
165 
     | 
    
         | 
| 
       164 
166 
     | 
    
         | 
| 
         @@ -185,18 +187,28 @@ class StepLog(BaseModel): 
     | 
|
| 
       185 
187 
     | 
    
         
             
                    summary: Dict[str, Any] = {}
         
     | 
| 
       186 
188 
     | 
    
         | 
| 
       187 
189 
     | 
    
         
             
                    summary["Name"] = self.internal_name
         
     | 
| 
       188 
     | 
    
         
            -
                    summary["Input catalog content"] = [ 
     | 
| 
      
 190 
     | 
    
         
            +
                    summary["Input catalog content"] = [
         
     | 
| 
      
 191 
     | 
    
         
            +
                        dc.name for dc in self.data_catalog if dc.stage == "get"
         
     | 
| 
      
 192 
     | 
    
         
            +
                    ]
         
     | 
| 
       189 
193 
     | 
    
         
             
                    summary["Available parameters"] = [
         
     | 
| 
       190 
     | 
    
         
            -
                        (p, v.description) 
     | 
| 
      
 194 
     | 
    
         
            +
                        (p, v.description)
         
     | 
| 
      
 195 
     | 
    
         
            +
                        for attempt in self.attempts
         
     | 
| 
      
 196 
     | 
    
         
            +
                        for p, v in attempt.input_parameters.items()
         
     | 
| 
       191 
197 
     | 
    
         
             
                    ]
         
     | 
| 
       192 
198 
     | 
    
         | 
| 
       193 
     | 
    
         
            -
                    summary["Output catalog content"] = [ 
     | 
| 
      
 199 
     | 
    
         
            +
                    summary["Output catalog content"] = [
         
     | 
| 
      
 200 
     | 
    
         
            +
                        dc.name for dc in self.data_catalog if dc.stage == "put"
         
     | 
| 
      
 201 
     | 
    
         
            +
                    ]
         
     | 
| 
       194 
202 
     | 
    
         
             
                    summary["Output parameters"] = [
         
     | 
| 
       195 
     | 
    
         
            -
                        (p, v.description) 
     | 
| 
      
 203 
     | 
    
         
            +
                        (p, v.description)
         
     | 
| 
      
 204 
     | 
    
         
            +
                        for attempt in self.attempts
         
     | 
| 
      
 205 
     | 
    
         
            +
                        for p, v in attempt.output_parameters.items()
         
     | 
| 
       196 
206 
     | 
    
         
             
                    ]
         
     | 
| 
       197 
207 
     | 
    
         | 
| 
       198 
208 
     | 
    
         
             
                    summary["Metrics"] = [
         
     | 
| 
       199 
     | 
    
         
            -
                        (p, v.description) 
     | 
| 
      
 209 
     | 
    
         
            +
                        (p, v.description)
         
     | 
| 
      
 210 
     | 
    
         
            +
                        for attempt in self.attempts
         
     | 
| 
      
 211 
     | 
    
         
            +
                        for p, v in attempt.user_defined_metrics.items()
         
     | 
| 
       200 
212 
     | 
    
         
             
                    ]
         
     | 
| 
       201 
213 
     | 
    
         | 
| 
       202 
214 
     | 
    
         
             
                    cis = []
         
     | 
| 
         @@ -312,10 +324,18 @@ class RunLog(BaseModel): 
     | 
|
| 
       312 
324 
     | 
    
         
             
                    summary["Catalog Location"] = _context.catalog_handler.get_summary()
         
     | 
| 
       313 
325 
     | 
    
         
             
                    summary["Full Run log present at: "] = _context.run_log_store.get_summary()
         
     | 
| 
       314 
326 
     | 
    
         | 
| 
       315 
     | 
    
         
            -
                    run_log = _context.run_log_store.get_run_log_by_id( 
     | 
| 
      
 327 
     | 
    
         
            +
                    run_log = _context.run_log_store.get_run_log_by_id(
         
     | 
| 
      
 328 
     | 
    
         
            +
                        run_id=_context.run_id, full=True
         
     | 
| 
      
 329 
     | 
    
         
            +
                    )
         
     | 
| 
       316 
330 
     | 
    
         | 
| 
       317 
     | 
    
         
            -
                    summary["Final Parameters"] = { 
     | 
| 
       318 
     | 
    
         
            -
             
     | 
| 
      
 331 
     | 
    
         
            +
                    summary["Final Parameters"] = {
         
     | 
| 
      
 332 
     | 
    
         
            +
                        p: v.description for p, v in run_log.parameters.items()
         
     | 
| 
      
 333 
     | 
    
         
            +
                    }
         
     | 
| 
      
 334 
     | 
    
         
            +
                    summary["Collected metrics"] = {
         
     | 
| 
      
 335 
     | 
    
         
            +
                        p: v.description
         
     | 
| 
      
 336 
     | 
    
         
            +
                        for p, v in run_log.parameters.items()
         
     | 
| 
      
 337 
     | 
    
         
            +
                        if v.kind == "metric"
         
     | 
| 
      
 338 
     | 
    
         
            +
                    }
         
     | 
| 
       319 
339 
     | 
    
         | 
| 
       320 
340 
     | 
    
         
             
                    return summary
         
     | 
| 
       321 
341 
     | 
    
         | 
| 
         @@ -338,7 +358,9 @@ class RunLog(BaseModel): 
     | 
|
| 
       338 
358 
     | 
    
         | 
| 
       339 
359 
     | 
    
         
             
                    return list(set(data_catalogs))
         
     | 
| 
       340 
360 
     | 
    
         | 
| 
       341 
     | 
    
         
            -
                def search_branch_by_internal_name( 
     | 
| 
      
 361 
     | 
    
         
            +
                def search_branch_by_internal_name(
         
     | 
| 
      
 362 
     | 
    
         
            +
                    self, i_name: str
         
     | 
| 
      
 363 
     | 
    
         
            +
                ) -> Tuple[Union[BranchLog, RunLog], Union[StepLog, None]]:
         
     | 
| 
       342 
364 
     | 
    
         
             
                    """
         
     | 
| 
       343 
365 
     | 
    
         
             
                    Given a branch internal name, search for it in the run log.
         
     | 
| 
       344 
366 
     | 
    
         | 
| 
         @@ -385,7 +407,9 @@ class RunLog(BaseModel): 
     | 
|
| 
       385 
407 
     | 
    
         | 
| 
       386 
408 
     | 
    
         
             
                    raise exceptions.BranchLogNotFoundError(self.run_id, i_name)
         
     | 
| 
       387 
409 
     | 
    
         | 
| 
       388 
     | 
    
         
            -
                def search_step_by_internal_name( 
     | 
| 
      
 410 
     | 
    
         
            +
                def search_step_by_internal_name(
         
     | 
| 
      
 411 
     | 
    
         
            +
                    self, i_name: str
         
     | 
| 
      
 412 
     | 
    
         
            +
                ) -> Tuple[StepLog, Union[BranchLog, None]]:
         
     | 
| 
       389 
413 
     | 
    
         
             
                    """
         
     | 
| 
       390 
414 
     | 
    
         
             
                    Given a steps internal name, search for the step name.
         
     | 
| 
       391 
415 
     | 
    
         | 
| 
         @@ -415,7 +439,9 @@ class RunLog(BaseModel): 
     | 
|
| 
       415 
439 
     | 
    
         
             
                            # Its odd, so we are in brach name
         
     | 
| 
       416 
440 
     | 
    
         
             
                            current_branch = current_step.branches[".".join(dot_path[: i + 1])]  # type: ignore
         
     | 
| 
       417 
441 
     | 
    
         
             
                            current_steps = current_branch.steps
         
     | 
| 
       418 
     | 
    
         
            -
                            logger.debug( 
     | 
| 
      
 442 
     | 
    
         
            +
                            logger.debug(
         
     | 
| 
      
 443 
     | 
    
         
            +
                                f"Finding step log for {i_name} in branch: {current_branch}"
         
     | 
| 
      
 444 
     | 
    
         
            +
                            )
         
     | 
| 
       419 
445 
     | 
    
         
             
                        else:
         
     | 
| 
       420 
446 
     | 
    
         
             
                            # Its even, so we are in step, we start here!
         
     | 
| 
       421 
447 
     | 
    
         
             
                            current_step = current_steps[".".join(dot_path[: i + 1])]
         
     | 
| 
         @@ -428,10 +454,6 @@ class RunLog(BaseModel): 
     | 
|
| 
       428 
454 
     | 
    
         
             
                    raise exceptions.StepLogNotFoundError(self.run_id, i_name)
         
     | 
| 
       429 
455 
     | 
    
         | 
| 
       430 
456 
     | 
    
         | 
| 
       431 
     | 
    
         
            -
            # All outside modules should interact with dataclasses using the RunLogStore to promote extensibility
         
     | 
| 
       432 
     | 
    
         
            -
            # If you want to customize dataclass, extend BaseRunLogStore and implement the methods as per the specification
         
     | 
| 
       433 
     | 
    
         
            -
             
     | 
| 
       434 
     | 
    
         
            -
             
     | 
| 
       435 
457 
     | 
    
         
             
            class BaseRunLogStore(ABC, BaseModel):
         
     | 
| 
       436 
458 
     | 
    
         
             
                """
         
     | 
| 
       437 
459 
     | 
    
         
             
                The base class of a Run Log Store with many common methods implemented.
         
     | 
| 
         @@ -441,8 +463,7 @@ class BaseRunLogStore(ABC, BaseModel): 
     | 
|
| 
       441 
463 
     | 
    
         
             
                service_type: str = "run_log_store"
         
     | 
| 
       442 
464 
     | 
    
         | 
| 
       443 
465 
     | 
    
         
             
                @abstractmethod
         
     | 
| 
       444 
     | 
    
         
            -
                def get_summary(self) -> Dict[str, Any]:
         
     | 
| 
       445 
     | 
    
         
            -
                    ...
         
     | 
| 
      
 466 
     | 
    
         
            +
                def get_summary(self) -> Dict[str, Any]: ...
         
     | 
| 
       446 
467 
     | 
    
         | 
| 
       447 
468 
     | 
    
         
             
                @property
         
     | 
| 
       448 
469 
     | 
    
         
             
                def _context(self):
         
     | 
| 
         @@ -629,7 +650,9 @@ class BaseRunLogStore(ABC, BaseModel): 
     | 
|
| 
       629 
650 
     | 
    
         
             
                        RunLogNotFoundError: If the run log for run_id is not found in the datastore
         
     | 
| 
       630 
651 
     | 
    
         
             
                        StepLogNotFoundError: If the step log for internal_name is not found in the datastore for run_id
         
     | 
| 
       631 
652 
     | 
    
         
             
                    """
         
     | 
| 
       632 
     | 
    
         
            -
                    logger.info( 
     | 
| 
      
 653 
     | 
    
         
            +
                    logger.info(
         
     | 
| 
      
 654 
     | 
    
         
            +
                        f"{self.service_name} Getting the step log: {internal_name} of {run_id}"
         
     | 
| 
      
 655 
     | 
    
         
            +
                    )
         
     | 
| 
       633 
656 
     | 
    
         
             
                    run_log = self.get_run_log_by_id(run_id=run_id)
         
     | 
| 
       634 
657 
     | 
    
         
             
                    step_log, _ = run_log.search_step_by_internal_name(internal_name)
         
     | 
| 
       635 
658 
     | 
    
         
             
                    return step_log
         
     | 
| 
         @@ -675,10 +698,14 @@ class BaseRunLogStore(ABC, BaseModel): 
     | 
|
| 
       675 
698 
     | 
    
         
             
                        BranchLog: Uncommitted and initialized with defaults BranchLog object
         
     | 
| 
       676 
699 
     | 
    
         
             
                    """
         
     | 
| 
       677 
700 
     | 
    
         
             
                    # Create a new BranchLog
         
     | 
| 
       678 
     | 
    
         
            -
                    logger.info( 
     | 
| 
      
 701 
     | 
    
         
            +
                    logger.info(
         
     | 
| 
      
 702 
     | 
    
         
            +
                        f"{self.service_name} Creating a Branch Log : {internal_branch_name}"
         
     | 
| 
      
 703 
     | 
    
         
            +
                    )
         
     | 
| 
       679 
704 
     | 
    
         
             
                    return BranchLog(internal_name=internal_branch_name, status=defaults.CREATED)
         
     | 
| 
       680 
705 
     | 
    
         | 
| 
       681 
     | 
    
         
            -
                def get_branch_log( 
     | 
| 
      
 706 
     | 
    
         
            +
                def get_branch_log(
         
     | 
| 
      
 707 
     | 
    
         
            +
                    self, internal_branch_name: str, run_id: str, **kwargs
         
     | 
| 
      
 708 
     | 
    
         
            +
                ) -> Union[BranchLog, RunLog]:
         
     | 
| 
       682 
709 
     | 
    
         
             
                    """
         
     | 
| 
       683 
710 
     | 
    
         
             
                    Returns the branch log by the internal branch name for the run id
         
     | 
| 
       684 
711 
     | 
    
         | 
| 
         @@ -697,7 +724,9 @@ class BaseRunLogStore(ABC, BaseModel): 
     | 
|
| 
       697 
724 
     | 
    
         
             
                    branch, _ = run_log.search_branch_by_internal_name(internal_branch_name)
         
     | 
| 
       698 
725 
     | 
    
         
             
                    return branch
         
     | 
| 
       699 
726 
     | 
    
         | 
| 
       700 
     | 
    
         
            -
                def add_branch_log( 
     | 
| 
      
 727 
     | 
    
         
            +
                def add_branch_log(
         
     | 
| 
      
 728 
     | 
    
         
            +
                    self, branch_log: Union[BranchLog, RunLog], run_id: str, **kwargs
         
     | 
| 
      
 729 
     | 
    
         
            +
                ):
         
     | 
| 
       701 
730 
     | 
    
         
             
                    """
         
     | 
| 
       702 
731 
     | 
    
         
             
                    The method should:
         
     | 
| 
       703 
732 
     | 
    
         
             
                    # Get the run log
         
     | 
| 
         @@ -775,7 +804,9 @@ class BufferRunLogstore(BaseRunLogStore): 
     | 
|
| 
       775 
804 
     | 
    
         
             
                """
         
     | 
| 
       776 
805 
     | 
    
         | 
| 
       777 
806 
     | 
    
         
             
                service_name: str = "buffered"
         
     | 
| 
       778 
     | 
    
         
            -
                run_log: Optional[RunLog] = Field( 
     | 
| 
      
 807 
     | 
    
         
            +
                run_log: Optional[RunLog] = Field(
         
     | 
| 
      
 808 
     | 
    
         
            +
                    default=None, exclude=True
         
     | 
| 
      
 809 
     | 
    
         
            +
                )  # For a buffered Run Log, this is the database
         
     | 
| 
       779 
810 
     | 
    
         | 
| 
       780 
811 
     | 
    
         
             
                def get_summary(self) -> Dict[str, Any]:
         
     | 
| 
       781 
812 
     | 
    
         
             
                    summary = {"Type": self.service_name, "Location": "Not persisted"}
         
     | 
| 
         @@ -826,5 +857,10 @@ class BufferRunLogstore(BaseRunLogStore): 
     | 
|
| 
       826 
857 
     | 
    
         
             
                    # Puts the run log in the db
         
     | 
| 
       827 
858 
     | 
    
         
             
                    # Raises Exception if not found
         
     | 
| 
       828 
859 
     | 
    
         
             
                    """
         
     | 
| 
       829 
     | 
    
         
            -
                    logger.info( 
     | 
| 
      
 860 
     | 
    
         
            +
                    logger.info(
         
     | 
| 
      
 861 
     | 
    
         
            +
                        f"{self.service_name} Putting the run log in the DB: {run_log.run_id}"
         
     | 
| 
      
 862 
     | 
    
         
            +
                    )
         
     | 
| 
       830 
863 
     | 
    
         
             
                    self.run_log = run_log
         
     | 
| 
      
 864 
     | 
    
         
            +
             
     | 
| 
      
 865 
     | 
    
         
            +
             
     | 
| 
      
 866 
     | 
    
         
            +
            import runnable.context as context  # noqa: F401, E402
         
     | 
    
        runnable/defaults.py
    CHANGED