apache-hamilton 1.90.0.dev0__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 (151) hide show
  1. apache_hamilton-1.90.0.dev0.dist-info/METADATA +407 -0
  2. apache_hamilton-1.90.0.dev0.dist-info/RECORD +151 -0
  3. apache_hamilton-1.90.0.dev0.dist-info/WHEEL +4 -0
  4. apache_hamilton-1.90.0.dev0.dist-info/entry_points.txt +9 -0
  5. apache_hamilton-1.90.0.dev0.dist-info/licenses/DISCLAIMER +10 -0
  6. apache_hamilton-1.90.0.dev0.dist-info/licenses/LICENSE +228 -0
  7. apache_hamilton-1.90.0.dev0.dist-info/licenses/NOTICE +5 -0
  8. hamilton/__init__.py +24 -0
  9. hamilton/ad_hoc_utils.py +132 -0
  10. hamilton/async_driver.py +465 -0
  11. hamilton/base.py +466 -0
  12. hamilton/caching/__init__.py +16 -0
  13. hamilton/caching/adapter.py +1475 -0
  14. hamilton/caching/cache_key.py +70 -0
  15. hamilton/caching/fingerprinting.py +287 -0
  16. hamilton/caching/stores/__init__.py +16 -0
  17. hamilton/caching/stores/base.py +242 -0
  18. hamilton/caching/stores/file.py +140 -0
  19. hamilton/caching/stores/memory.py +297 -0
  20. hamilton/caching/stores/sqlite.py +282 -0
  21. hamilton/caching/stores/utils.py +40 -0
  22. hamilton/cli/__init__.py +16 -0
  23. hamilton/cli/__main__.py +328 -0
  24. hamilton/cli/commands.py +126 -0
  25. hamilton/cli/logic.py +338 -0
  26. hamilton/common/__init__.py +76 -0
  27. hamilton/contrib/__init__.py +41 -0
  28. hamilton/data_quality/__init__.py +16 -0
  29. hamilton/data_quality/base.py +198 -0
  30. hamilton/data_quality/default_validators.py +560 -0
  31. hamilton/data_quality/pandera_validators.py +121 -0
  32. hamilton/dataflows/__init__.py +726 -0
  33. hamilton/dataflows/template/README.md +25 -0
  34. hamilton/dataflows/template/__init__.py +54 -0
  35. hamilton/dataflows/template/author.md +28 -0
  36. hamilton/dataflows/template/requirements.txt +0 -0
  37. hamilton/dataflows/template/tags.json +7 -0
  38. hamilton/dataflows/template/valid_configs.jsonl +1 -0
  39. hamilton/dev_utils/__init__.py +16 -0
  40. hamilton/dev_utils/deprecation.py +204 -0
  41. hamilton/driver.py +2112 -0
  42. hamilton/execution/__init__.py +16 -0
  43. hamilton/execution/debugging_utils.py +56 -0
  44. hamilton/execution/executors.py +502 -0
  45. hamilton/execution/graph_functions.py +421 -0
  46. hamilton/execution/grouping.py +430 -0
  47. hamilton/execution/state.py +539 -0
  48. hamilton/experimental/__init__.py +27 -0
  49. hamilton/experimental/databackend.py +61 -0
  50. hamilton/experimental/decorators/__init__.py +16 -0
  51. hamilton/experimental/decorators/parameterize_frame.py +233 -0
  52. hamilton/experimental/h_async.py +29 -0
  53. hamilton/experimental/h_cache.py +413 -0
  54. hamilton/experimental/h_dask.py +28 -0
  55. hamilton/experimental/h_databackends.py +174 -0
  56. hamilton/experimental/h_ray.py +28 -0
  57. hamilton/experimental/h_spark.py +32 -0
  58. hamilton/function_modifiers/README +40 -0
  59. hamilton/function_modifiers/__init__.py +121 -0
  60. hamilton/function_modifiers/adapters.py +900 -0
  61. hamilton/function_modifiers/base.py +859 -0
  62. hamilton/function_modifiers/configuration.py +310 -0
  63. hamilton/function_modifiers/delayed.py +202 -0
  64. hamilton/function_modifiers/dependencies.py +246 -0
  65. hamilton/function_modifiers/expanders.py +1230 -0
  66. hamilton/function_modifiers/macros.py +1634 -0
  67. hamilton/function_modifiers/metadata.py +434 -0
  68. hamilton/function_modifiers/recursive.py +908 -0
  69. hamilton/function_modifiers/validation.py +289 -0
  70. hamilton/function_modifiers_base.py +31 -0
  71. hamilton/graph.py +1153 -0
  72. hamilton/graph_types.py +264 -0
  73. hamilton/graph_utils.py +41 -0
  74. hamilton/htypes.py +450 -0
  75. hamilton/io/__init__.py +32 -0
  76. hamilton/io/data_adapters.py +216 -0
  77. hamilton/io/default_data_loaders.py +224 -0
  78. hamilton/io/materialization.py +500 -0
  79. hamilton/io/utils.py +158 -0
  80. hamilton/lifecycle/__init__.py +67 -0
  81. hamilton/lifecycle/api.py +833 -0
  82. hamilton/lifecycle/base.py +1130 -0
  83. hamilton/lifecycle/default.py +802 -0
  84. hamilton/log_setup.py +47 -0
  85. hamilton/models.py +92 -0
  86. hamilton/node.py +449 -0
  87. hamilton/plugins/README.md +48 -0
  88. hamilton/plugins/__init__.py +16 -0
  89. hamilton/plugins/dask_extensions.py +47 -0
  90. hamilton/plugins/dlt_extensions.py +161 -0
  91. hamilton/plugins/geopandas_extensions.py +49 -0
  92. hamilton/plugins/h_dask.py +331 -0
  93. hamilton/plugins/h_ddog.py +522 -0
  94. hamilton/plugins/h_diskcache.py +163 -0
  95. hamilton/plugins/h_experiments/__init__.py +22 -0
  96. hamilton/plugins/h_experiments/__main__.py +62 -0
  97. hamilton/plugins/h_experiments/cache.py +39 -0
  98. hamilton/plugins/h_experiments/data_model.py +68 -0
  99. hamilton/plugins/h_experiments/hook.py +219 -0
  100. hamilton/plugins/h_experiments/server.py +375 -0
  101. hamilton/plugins/h_kedro.py +152 -0
  102. hamilton/plugins/h_logging.py +454 -0
  103. hamilton/plugins/h_mcp/__init__.py +28 -0
  104. hamilton/plugins/h_mcp/__main__.py +33 -0
  105. hamilton/plugins/h_mcp/_helpers.py +129 -0
  106. hamilton/plugins/h_mcp/_templates.py +417 -0
  107. hamilton/plugins/h_mcp/server.py +328 -0
  108. hamilton/plugins/h_mlflow.py +335 -0
  109. hamilton/plugins/h_narwhals.py +134 -0
  110. hamilton/plugins/h_openlineage.py +400 -0
  111. hamilton/plugins/h_opentelemetry.py +167 -0
  112. hamilton/plugins/h_pandas.py +257 -0
  113. hamilton/plugins/h_pandera.py +117 -0
  114. hamilton/plugins/h_polars.py +304 -0
  115. hamilton/plugins/h_polars_lazyframe.py +282 -0
  116. hamilton/plugins/h_pyarrow.py +56 -0
  117. hamilton/plugins/h_pydantic.py +127 -0
  118. hamilton/plugins/h_ray.py +242 -0
  119. hamilton/plugins/h_rich.py +142 -0
  120. hamilton/plugins/h_schema.py +493 -0
  121. hamilton/plugins/h_slack.py +100 -0
  122. hamilton/plugins/h_spark.py +1380 -0
  123. hamilton/plugins/h_threadpool.py +125 -0
  124. hamilton/plugins/h_tqdm.py +122 -0
  125. hamilton/plugins/h_vaex.py +129 -0
  126. hamilton/plugins/huggingface_extensions.py +236 -0
  127. hamilton/plugins/ibis_extensions.py +93 -0
  128. hamilton/plugins/jupyter_magic.py +622 -0
  129. hamilton/plugins/kedro_extensions.py +117 -0
  130. hamilton/plugins/lightgbm_extensions.py +99 -0
  131. hamilton/plugins/matplotlib_extensions.py +108 -0
  132. hamilton/plugins/mlflow_extensions.py +216 -0
  133. hamilton/plugins/numpy_extensions.py +105 -0
  134. hamilton/plugins/pandas_extensions.py +1763 -0
  135. hamilton/plugins/plotly_extensions.py +150 -0
  136. hamilton/plugins/polars_extensions.py +71 -0
  137. hamilton/plugins/polars_implementations.py +25 -0
  138. hamilton/plugins/polars_lazyframe_extensions.py +302 -0
  139. hamilton/plugins/polars_post_1_0_0_extensions.py +877 -0
  140. hamilton/plugins/polars_pre_1_0_0_extension.py +836 -0
  141. hamilton/plugins/pydantic_extensions.py +98 -0
  142. hamilton/plugins/pyspark_pandas_extensions.py +47 -0
  143. hamilton/plugins/sklearn_plot_extensions.py +129 -0
  144. hamilton/plugins/spark_extensions.py +105 -0
  145. hamilton/plugins/vaex_extensions.py +51 -0
  146. hamilton/plugins/xgboost_extensions.py +91 -0
  147. hamilton/plugins/yaml_extensions.py +89 -0
  148. hamilton/registry.py +254 -0
  149. hamilton/settings.py +18 -0
  150. hamilton/telemetry.py +50 -0
  151. hamilton/version.py +18 -0
@@ -0,0 +1,242 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ import abc
19
+ import functools
20
+ import json
21
+ import logging
22
+ import time
23
+ import typing
24
+
25
+ import ray
26
+
27
+ from hamilton import base, htypes, lifecycle, node
28
+ from hamilton.execution import executors
29
+ from hamilton.execution.executors import TaskFuture
30
+ from hamilton.execution.grouping import TaskImplementation
31
+ from hamilton.function_modifiers.metadata import RAY_REMOTE_TAG_NAMESPACE
32
+
33
+ logger = logging.getLogger(__name__)
34
+
35
+
36
+ def raify(fn):
37
+ """Makes the function into something ray-friendly.
38
+ This is necessary due to https://github.com/ray-project/ray/issues/28146.
39
+
40
+ :param fn: Function to make ray-friendly
41
+ :return: The ray-friendly version
42
+ """
43
+ if isinstance(fn, functools.partial):
44
+
45
+ def new_fn(*args, **kwargs):
46
+ return fn(*args, **kwargs)
47
+
48
+ return new_fn
49
+ return fn
50
+
51
+
52
+ def parse_ray_remote_options_from_tags(tags: dict[str, str]) -> dict[str, typing.Any]:
53
+ """DRY helper to parse ray.remote(**options) from Hamilton Tags
54
+
55
+ Tags are added to nodes via the @ray_remote_options decorator
56
+
57
+ :param tags: Full set of Tags for a Node
58
+ :return: The ray-friendly version
59
+ """
60
+
61
+ ray_tags = {
62
+ tag_name: tag_value
63
+ for tag_name, tag_value in tags.items()
64
+ if tag_name.startswith(f"{RAY_REMOTE_TAG_NAMESPACE}.")
65
+ }
66
+ ray_options = {name.split(".", 1)[1]: json.loads(value) for name, value in ray_tags.items()}
67
+
68
+ return ray_options
69
+
70
+
71
+ class RayGraphAdapter(
72
+ lifecycle.base.BaseDoRemoteExecute,
73
+ lifecycle.base.BaseDoBuildResult,
74
+ lifecycle.base.BaseDoValidateInput,
75
+ lifecycle.base.BaseDoCheckEdgeTypesMatch,
76
+ lifecycle.base.BasePostGraphExecute,
77
+ abc.ABC,
78
+ ):
79
+ """Class representing what's required to make Hamilton run on Ray.
80
+
81
+ This walks the graph and translates it to run onto `Ray <https://ray.io/>`__.
82
+
83
+ Use `pip install sf-hamilton[ray]` to get the dependencies required to run this.
84
+
85
+ Use this if:
86
+
87
+ * you want to utilize multiple cores on a single machine, or you want to scale to larger data set sizes with\
88
+ a Ray cluster that you can connect to. Note (1): you are still constrained by machine memory size with Ray; you\
89
+ can't just scale to any dataset size. Note (2): serialization costs can outweigh the benefits of parallelism \
90
+ so you should benchmark your code to see if it's worth it.
91
+
92
+ Notes on scaling:
93
+ -----------------
94
+ - Multi-core on single machine ✅
95
+ - Distributed computation on a Ray cluster ✅
96
+ - Scales to any size of data ⛔️; you are LIMITED by the memory on the instance/computer 💻.
97
+
98
+ Function return object types supported:
99
+ ---------------------------------------
100
+ - Works for any python object that can be serialized by the Ray framework. ✅
101
+
102
+ Pandas?
103
+ --------
104
+ - ⛔️ Ray DOES NOT do anything special about Pandas.
105
+
106
+ CAVEATS
107
+ -------
108
+ - Serialization costs can outweigh the benefits of parallelism, so you should benchmark your code to see if it's\
109
+ worth it.
110
+
111
+ DISCLAIMER -- this class is experimental, so signature changes are a possibility!
112
+ """
113
+
114
+ def __init__(
115
+ self,
116
+ result_builder: base.ResultMixin,
117
+ ray_init_config: dict[str, typing.Any] = None,
118
+ shutdown_ray_on_completion: bool = False,
119
+ ):
120
+ """Constructor
121
+
122
+ You have the ability to pass in a ResultMixin object to the constructor to control the return type that gets \
123
+ produce by running on Ray.
124
+
125
+ :param result_builder: Required. An implementation of base.ResultMixin.
126
+ :param ray_init_config: allows to connect to an existing cluster or start a new one with custom configuration (https://docs.ray.io/en/latest/ray-core/api/doc/ray.init.html)
127
+ :param shutdown_ray_on_completion: by default we leave the cluster open, but we can also shut it down
128
+
129
+ """
130
+ self.result_builder = result_builder
131
+ if not self.result_builder:
132
+ raise ValueError(
133
+ "Error: ResultMixin object required. Please pass one in for `result_builder`."
134
+ )
135
+
136
+ self.shutdown_ray_on_completion = shutdown_ray_on_completion
137
+
138
+ if ray_init_config is not None:
139
+ ray.init(**ray_init_config)
140
+
141
+ @staticmethod
142
+ def do_validate_input(node_type: type, input_value: typing.Any) -> bool:
143
+ # NOTE: the type of a raylet is unknown until they are computed
144
+ if isinstance(input_value, ray._raylet.ObjectRef):
145
+ return True
146
+ return htypes.check_input_type(node_type, input_value)
147
+
148
+ @staticmethod
149
+ def do_check_edge_types_match(type_from: type, type_to: type) -> bool:
150
+ return type_from == type_to
151
+
152
+ def do_remote_execute(
153
+ self,
154
+ *,
155
+ execute_lifecycle_for_node: typing.Callable,
156
+ node: node.Node,
157
+ **kwargs: dict[str, typing.Any],
158
+ ) -> typing.Any:
159
+ """Function that is called as we walk the graph to determine how to execute a hamilton function.
160
+
161
+ :param execute_lifecycle_for_node: wrapper function that executes lifecycle hooks and methods
162
+ :param kwargs: the arguments that should be passed to it.
163
+ :return: returns a ray object reference.
164
+ """
165
+ ray_options = parse_ray_remote_options_from_tags(node.tags)
166
+ return ray.remote(raify(execute_lifecycle_for_node)).options(**ray_options).remote(**kwargs)
167
+
168
+ def do_build_result(self, outputs: dict[str, typing.Any]) -> typing.Any:
169
+ """Builds the result and brings it back to this running process.
170
+
171
+ :param outputs: the dictionary of key -> Union[ray object reference | value]
172
+ :return: The type of object returned by self.result_builder.
173
+ """
174
+ if logger.isEnabledFor(logging.DEBUG):
175
+ for k, v in outputs.items():
176
+ logger.debug(f"Got output {k}, with type [{type(v)}].")
177
+ # need to wrap our result builder in a remote call and then pass in what we want to build from.
178
+ remote_combine = ray.remote(self.result_builder.build_result).remote(**outputs)
179
+ result = ray.get(remote_combine) # this materializes the object locally
180
+ return result
181
+
182
+ def post_graph_execute(self, *args, **kwargs):
183
+ """We have the option to close the cluster down after execution."""
184
+
185
+ if self.shutdown_ray_on_completion:
186
+ # In case we have Hamilton Tracker to have enough time to properly flush
187
+ time.sleep(5)
188
+ ray.shutdown()
189
+
190
+
191
+ class RayTaskExecutor(executors.TaskExecutor):
192
+ """Task executor using Ray for the new task-based execution mechanism in Hamilton.
193
+ This is still experimental, so the API might change.
194
+ """
195
+
196
+ def __init__(
197
+ self,
198
+ num_cpus: int = None,
199
+ ray_init_config: dict[str, typing.Any] = None,
200
+ skip_init: bool = False,
201
+ ):
202
+ """Creates a ray task executor. Note this will likely take in more parameters. This is
203
+ experimental, so the API will likely change, although we will do our best to make it
204
+ backwards compatible.
205
+
206
+ :param num_cpus: Number of cores to use for initialization, passed directly to ray.init. Defaults to all cores.
207
+ :param ray_init_config: General configuration to pass to ray.init. Defaults to None.
208
+ :param skip_init: Skips ray init if you already have Ray initialized. Default is False.
209
+ """
210
+ self.num_cpus = num_cpus
211
+ self.ray_init_config = ray_init_config or {}
212
+ self.skip_init = skip_init
213
+
214
+ def init(self):
215
+ if self.skip_init:
216
+ return
217
+ ray.init(num_cpus=self.num_cpus, **self.ray_init_config)
218
+
219
+ def finalize(self):
220
+ if self.skip_init:
221
+ # we assume that if we didn't init it, we don't need to shutdown either.
222
+ return
223
+ ray.shutdown()
224
+
225
+ def submit_task(self, task: TaskImplementation) -> TaskFuture:
226
+ """Submits a task, wrapping it in a TaskFuture (after getting the corresponding python
227
+ future).
228
+
229
+ :param task: Task to wrap
230
+ :return: A future
231
+ """
232
+
233
+ return executors.TaskFutureWrappingPythonFuture(
234
+ ray.remote(executors.base_execute_task).remote(task=task).future()
235
+ )
236
+
237
+ def can_submit_task(self) -> bool:
238
+ """For now we can always submit a task -- it might just be delayed.
239
+
240
+ :return: True
241
+ """
242
+ return True
@@ -0,0 +1,142 @@
1
+ # Licensed to the Apache Software Foundation (ASF) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The ASF licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ from collections.abc import Collection
19
+ from typing import Any
20
+
21
+ import rich.progress
22
+
23
+ from hamilton.execution.grouping import NodeGroupPurpose
24
+
25
+ try:
26
+ from typing import override
27
+ except ImportError:
28
+ override = lambda x: x # noqa E731
29
+
30
+ import rich
31
+ from rich.progress import Progress
32
+
33
+ from hamilton.lifecycle import (
34
+ GraphExecutionHook,
35
+ NodeExecutionHook,
36
+ TaskExecutionHook,
37
+ TaskGroupingHook,
38
+ )
39
+
40
+
41
+ class RichProgressBar(TaskExecutionHook, TaskGroupingHook, GraphExecutionHook, NodeExecutionHook):
42
+ """An adapter that uses rich to show simple progress bars for the graph execution.
43
+
44
+ Note: you need to have rich installed for this to work. If you don't have it installed, you can
45
+ install it with `pip install rich` (or `pip install sf-hamilton[rich]` -- use quotes if you're
46
+ using zsh).
47
+
48
+ .. code-block:: python
49
+
50
+ from hamilton import driver
51
+ from hamilton.plugins import h_rich
52
+
53
+ dr = (
54
+ driver.Builder()
55
+ .with_config({})
56
+ .with_modules(some_modules)
57
+ .with_adapters(h_rich.RichProgressBar())
58
+ .build()
59
+ )
60
+
61
+ and then when you call .execute() or .materialize() you'll get a progress bar!
62
+
63
+ Additionally, this progress bar will also work with task-based execution, showing the progress
64
+ of overall execution as well as the tasks within a parallelized group.
65
+
66
+ .. code-block:: python
67
+
68
+ from hamilton import driver
69
+ from hamilton.execution import executors
70
+ from hamilton.plugins import h_rich
71
+
72
+ dr = (
73
+ driver.Builder()
74
+ .with_modules(__main__)
75
+ .enable_dynamic_execution(allow_experimental_mode=True)
76
+ .with_adapters(RichProgressBar())
77
+ .with_local_executor(executors.SynchronousLocalTaskExecutor())
78
+ .with_remote_executor(executors.SynchronousLocalTaskExecutor())
79
+ .build()
80
+ )
81
+ """
82
+
83
+ def __init__(
84
+ self,
85
+ run_desc: str = "",
86
+ collect_desc: str = "",
87
+ columns: list[str | rich.progress.ProgressColumn] | None = None,
88
+ **kwargs,
89
+ ) -> None:
90
+ """Create a new Rich Progress Bar adapter.
91
+
92
+ :param run_desc: The description to show for the running phase.
93
+ :param collect_desc: The description to show for the collecting phase (if applicable).
94
+ :param columns: Column configuration for the progress bar. See rich docs for more info.
95
+ :param kwargs: Additional kwargs to pass to rich.progress.Progress. See rich docs for more info.
96
+ """
97
+ self._group_desc = run_desc or "Running:"
98
+ self._expand_desc = collect_desc or "Collecting:"
99
+ columns = columns or []
100
+ self._progress = Progress(*columns, **kwargs)
101
+ self._task_based = False
102
+
103
+ @override
104
+ def run_before_graph_execution(self, *, execution_path: Collection[str], **kwargs: Any):
105
+ self._progress.add_task(self._group_desc, total=len(execution_path))
106
+ self._progress.start()
107
+
108
+ @override
109
+ def run_after_graph_execution(self, **kwargs: Any):
110
+ self._progress.stop() # in case progress thread is lagging
111
+
112
+ @override
113
+ def run_after_task_grouping(self, *, task_ids: list[str], **kwargs):
114
+ # Change the total of the task group to the number of tasks in the group
115
+ self._progress.update(self._progress.task_ids[0], total=len(task_ids))
116
+ self._task_based = True
117
+
118
+ @override
119
+ def run_after_task_expansion(self, *, parameters: dict[str, Any], **kwargs):
120
+ self._progress.add_task(self._expand_desc, total=len(parameters))
121
+
122
+ @override
123
+ def run_before_task_execution(self, *, purpose: NodeGroupPurpose, **kwargs):
124
+ if purpose == NodeGroupPurpose.GATHER:
125
+ self._progress.advance(self._progress.task_ids[0])
126
+ self._progress.stop_task(self._progress.task_ids[-1])
127
+
128
+ @override
129
+ def run_after_task_execution(self, *, purpose: NodeGroupPurpose, **kwargs):
130
+ if purpose == NodeGroupPurpose.EXECUTE_BLOCK:
131
+ self._progress.advance(self._progress.task_ids[-1])
132
+ else:
133
+ self._progress.advance(self._progress.task_ids[0])
134
+
135
+ @override
136
+ def run_before_node_execution(self, **kwargs):
137
+ pass
138
+
139
+ @override
140
+ def run_after_node_execution(self, **kwargs):
141
+ if not self._task_based:
142
+ self._progress.advance(self._progress.task_ids[0])