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.
- apache_hamilton-1.90.0.dev0.dist-info/METADATA +407 -0
- apache_hamilton-1.90.0.dev0.dist-info/RECORD +151 -0
- apache_hamilton-1.90.0.dev0.dist-info/WHEEL +4 -0
- apache_hamilton-1.90.0.dev0.dist-info/entry_points.txt +9 -0
- apache_hamilton-1.90.0.dev0.dist-info/licenses/DISCLAIMER +10 -0
- apache_hamilton-1.90.0.dev0.dist-info/licenses/LICENSE +228 -0
- apache_hamilton-1.90.0.dev0.dist-info/licenses/NOTICE +5 -0
- hamilton/__init__.py +24 -0
- hamilton/ad_hoc_utils.py +132 -0
- hamilton/async_driver.py +465 -0
- hamilton/base.py +466 -0
- hamilton/caching/__init__.py +16 -0
- hamilton/caching/adapter.py +1475 -0
- hamilton/caching/cache_key.py +70 -0
- hamilton/caching/fingerprinting.py +287 -0
- hamilton/caching/stores/__init__.py +16 -0
- hamilton/caching/stores/base.py +242 -0
- hamilton/caching/stores/file.py +140 -0
- hamilton/caching/stores/memory.py +297 -0
- hamilton/caching/stores/sqlite.py +282 -0
- hamilton/caching/stores/utils.py +40 -0
- hamilton/cli/__init__.py +16 -0
- hamilton/cli/__main__.py +328 -0
- hamilton/cli/commands.py +126 -0
- hamilton/cli/logic.py +338 -0
- hamilton/common/__init__.py +76 -0
- hamilton/contrib/__init__.py +41 -0
- hamilton/data_quality/__init__.py +16 -0
- hamilton/data_quality/base.py +198 -0
- hamilton/data_quality/default_validators.py +560 -0
- hamilton/data_quality/pandera_validators.py +121 -0
- hamilton/dataflows/__init__.py +726 -0
- hamilton/dataflows/template/README.md +25 -0
- hamilton/dataflows/template/__init__.py +54 -0
- hamilton/dataflows/template/author.md +28 -0
- hamilton/dataflows/template/requirements.txt +0 -0
- hamilton/dataflows/template/tags.json +7 -0
- hamilton/dataflows/template/valid_configs.jsonl +1 -0
- hamilton/dev_utils/__init__.py +16 -0
- hamilton/dev_utils/deprecation.py +204 -0
- hamilton/driver.py +2112 -0
- hamilton/execution/__init__.py +16 -0
- hamilton/execution/debugging_utils.py +56 -0
- hamilton/execution/executors.py +502 -0
- hamilton/execution/graph_functions.py +421 -0
- hamilton/execution/grouping.py +430 -0
- hamilton/execution/state.py +539 -0
- hamilton/experimental/__init__.py +27 -0
- hamilton/experimental/databackend.py +61 -0
- hamilton/experimental/decorators/__init__.py +16 -0
- hamilton/experimental/decorators/parameterize_frame.py +233 -0
- hamilton/experimental/h_async.py +29 -0
- hamilton/experimental/h_cache.py +413 -0
- hamilton/experimental/h_dask.py +28 -0
- hamilton/experimental/h_databackends.py +174 -0
- hamilton/experimental/h_ray.py +28 -0
- hamilton/experimental/h_spark.py +32 -0
- hamilton/function_modifiers/README +40 -0
- hamilton/function_modifiers/__init__.py +121 -0
- hamilton/function_modifiers/adapters.py +900 -0
- hamilton/function_modifiers/base.py +859 -0
- hamilton/function_modifiers/configuration.py +310 -0
- hamilton/function_modifiers/delayed.py +202 -0
- hamilton/function_modifiers/dependencies.py +246 -0
- hamilton/function_modifiers/expanders.py +1230 -0
- hamilton/function_modifiers/macros.py +1634 -0
- hamilton/function_modifiers/metadata.py +434 -0
- hamilton/function_modifiers/recursive.py +908 -0
- hamilton/function_modifiers/validation.py +289 -0
- hamilton/function_modifiers_base.py +31 -0
- hamilton/graph.py +1153 -0
- hamilton/graph_types.py +264 -0
- hamilton/graph_utils.py +41 -0
- hamilton/htypes.py +450 -0
- hamilton/io/__init__.py +32 -0
- hamilton/io/data_adapters.py +216 -0
- hamilton/io/default_data_loaders.py +224 -0
- hamilton/io/materialization.py +500 -0
- hamilton/io/utils.py +158 -0
- hamilton/lifecycle/__init__.py +67 -0
- hamilton/lifecycle/api.py +833 -0
- hamilton/lifecycle/base.py +1130 -0
- hamilton/lifecycle/default.py +802 -0
- hamilton/log_setup.py +47 -0
- hamilton/models.py +92 -0
- hamilton/node.py +449 -0
- hamilton/plugins/README.md +48 -0
- hamilton/plugins/__init__.py +16 -0
- hamilton/plugins/dask_extensions.py +47 -0
- hamilton/plugins/dlt_extensions.py +161 -0
- hamilton/plugins/geopandas_extensions.py +49 -0
- hamilton/plugins/h_dask.py +331 -0
- hamilton/plugins/h_ddog.py +522 -0
- hamilton/plugins/h_diskcache.py +163 -0
- hamilton/plugins/h_experiments/__init__.py +22 -0
- hamilton/plugins/h_experiments/__main__.py +62 -0
- hamilton/plugins/h_experiments/cache.py +39 -0
- hamilton/plugins/h_experiments/data_model.py +68 -0
- hamilton/plugins/h_experiments/hook.py +219 -0
- hamilton/plugins/h_experiments/server.py +375 -0
- hamilton/plugins/h_kedro.py +152 -0
- hamilton/plugins/h_logging.py +454 -0
- hamilton/plugins/h_mcp/__init__.py +28 -0
- hamilton/plugins/h_mcp/__main__.py +33 -0
- hamilton/plugins/h_mcp/_helpers.py +129 -0
- hamilton/plugins/h_mcp/_templates.py +417 -0
- hamilton/plugins/h_mcp/server.py +328 -0
- hamilton/plugins/h_mlflow.py +335 -0
- hamilton/plugins/h_narwhals.py +134 -0
- hamilton/plugins/h_openlineage.py +400 -0
- hamilton/plugins/h_opentelemetry.py +167 -0
- hamilton/plugins/h_pandas.py +257 -0
- hamilton/plugins/h_pandera.py +117 -0
- hamilton/plugins/h_polars.py +304 -0
- hamilton/plugins/h_polars_lazyframe.py +282 -0
- hamilton/plugins/h_pyarrow.py +56 -0
- hamilton/plugins/h_pydantic.py +127 -0
- hamilton/plugins/h_ray.py +242 -0
- hamilton/plugins/h_rich.py +142 -0
- hamilton/plugins/h_schema.py +493 -0
- hamilton/plugins/h_slack.py +100 -0
- hamilton/plugins/h_spark.py +1380 -0
- hamilton/plugins/h_threadpool.py +125 -0
- hamilton/plugins/h_tqdm.py +122 -0
- hamilton/plugins/h_vaex.py +129 -0
- hamilton/plugins/huggingface_extensions.py +236 -0
- hamilton/plugins/ibis_extensions.py +93 -0
- hamilton/plugins/jupyter_magic.py +622 -0
- hamilton/plugins/kedro_extensions.py +117 -0
- hamilton/plugins/lightgbm_extensions.py +99 -0
- hamilton/plugins/matplotlib_extensions.py +108 -0
- hamilton/plugins/mlflow_extensions.py +216 -0
- hamilton/plugins/numpy_extensions.py +105 -0
- hamilton/plugins/pandas_extensions.py +1763 -0
- hamilton/plugins/plotly_extensions.py +150 -0
- hamilton/plugins/polars_extensions.py +71 -0
- hamilton/plugins/polars_implementations.py +25 -0
- hamilton/plugins/polars_lazyframe_extensions.py +302 -0
- hamilton/plugins/polars_post_1_0_0_extensions.py +877 -0
- hamilton/plugins/polars_pre_1_0_0_extension.py +836 -0
- hamilton/plugins/pydantic_extensions.py +98 -0
- hamilton/plugins/pyspark_pandas_extensions.py +47 -0
- hamilton/plugins/sklearn_plot_extensions.py +129 -0
- hamilton/plugins/spark_extensions.py +105 -0
- hamilton/plugins/vaex_extensions.py +51 -0
- hamilton/plugins/xgboost_extensions.py +91 -0
- hamilton/plugins/yaml_extensions.py +89 -0
- hamilton/registry.py +254 -0
- hamilton/settings.py +18 -0
- hamilton/telemetry.py +50 -0
- hamilton/version.py +18 -0
|
@@ -0,0 +1,246 @@
|
|
|
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 dataclasses
|
|
20
|
+
import enum
|
|
21
|
+
import typing
|
|
22
|
+
from collections.abc import Mapping, Sequence
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
import typing_inspect
|
|
26
|
+
|
|
27
|
+
from hamilton.function_modifiers.base import InvalidDecoratorException
|
|
28
|
+
|
|
29
|
+
"""Utilities for specifying dependencies/dependency types in other decorators."""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ParametrizedDependencySource(enum.Enum):
|
|
33
|
+
LITERAL = "literal"
|
|
34
|
+
UPSTREAM = "upstream"
|
|
35
|
+
GROUPED_LIST = "grouped_list"
|
|
36
|
+
GROUPED_DICT = "grouped_dict"
|
|
37
|
+
CONFIGURATION = "configuration"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ParametrizedDependency:
|
|
41
|
+
@abc.abstractmethod
|
|
42
|
+
def get_dependency_type(self) -> ParametrizedDependencySource:
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class SingleDependency(ParametrizedDependency, abc.ABC):
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclasses.dataclass
|
|
51
|
+
class LiteralDependency(SingleDependency):
|
|
52
|
+
value: Any
|
|
53
|
+
|
|
54
|
+
def get_dependency_type(self) -> ParametrizedDependencySource:
|
|
55
|
+
return ParametrizedDependencySource.LITERAL
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
@dataclasses.dataclass
|
|
59
|
+
class UpstreamDependency(SingleDependency):
|
|
60
|
+
source: str
|
|
61
|
+
|
|
62
|
+
def get_dependency_type(self) -> ParametrizedDependencySource:
|
|
63
|
+
return ParametrizedDependencySource.UPSTREAM
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@dataclasses.dataclass
|
|
67
|
+
class ConfigDependency(SingleDependency):
|
|
68
|
+
source: str
|
|
69
|
+
|
|
70
|
+
def get_dependency_type(self) -> ParametrizedDependencySource:
|
|
71
|
+
return ParametrizedDependencySource.CONFIGURATION
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class GroupedDependency(ParametrizedDependency, abc.ABC):
|
|
75
|
+
@classmethod
|
|
76
|
+
@abc.abstractmethod
|
|
77
|
+
def resolve_dependency_type(cls, annotated_type: type[type], param_name: str) -> type[type]:
|
|
78
|
+
"""Resolves dependency type for an annotated parameter. E.G. List[str] -> str,
|
|
79
|
+
or Dict[str, int] -> int.
|
|
80
|
+
|
|
81
|
+
:param type: Type to inspect
|
|
82
|
+
:param param_name: Name of the parameter, used for good error messages
|
|
83
|
+
:return:Resolved dependency type
|
|
84
|
+
:raises: InvalidDecoratorException if the dependency type cannot be resolved appropriately.
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclasses.dataclass
|
|
89
|
+
class GroupedListDependency(GroupedDependency):
|
|
90
|
+
sources: list[ParametrizedDependency]
|
|
91
|
+
|
|
92
|
+
@classmethod
|
|
93
|
+
def resolve_dependency_type(cls, annotated_type: type[Sequence[type]], param_name: str):
|
|
94
|
+
if typing_inspect.is_optional_type(
|
|
95
|
+
annotated_type
|
|
96
|
+
): # need to pull out the type from Optional.
|
|
97
|
+
annotated_type = typing_inspect.get_args(annotated_type)[0]
|
|
98
|
+
origin = typing_inspect.get_origin(annotated_type)
|
|
99
|
+
if origin is None or not issubclass(origin, typing.Sequence):
|
|
100
|
+
raise InvalidDecoratorException(
|
|
101
|
+
f"Type: {annotated_type} for parameter: {param_name} needs to be "
|
|
102
|
+
f"sequence to use the group() dependency specification. Otherwise hamilton"
|
|
103
|
+
f"cannot validate that the types are correct."
|
|
104
|
+
)
|
|
105
|
+
args = typing_inspect.get_args(annotated_type)
|
|
106
|
+
if not len(args) == 1:
|
|
107
|
+
raise InvalidDecoratorException(
|
|
108
|
+
f"Type: {annotated_type} for parameter: {param_name} needs to be "
|
|
109
|
+
f"sequence with one type argument to use the group() dependency specification. "
|
|
110
|
+
f"Otherwise Hamilton cannot validate that the types are correct."
|
|
111
|
+
)
|
|
112
|
+
return args[0]
|
|
113
|
+
|
|
114
|
+
def get_dependency_type(self) -> ParametrizedDependencySource:
|
|
115
|
+
return ParametrizedDependencySource.GROUPED_LIST
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@dataclasses.dataclass
|
|
119
|
+
class GroupedDictDependency(GroupedDependency):
|
|
120
|
+
sources: dict[str, ParametrizedDependency]
|
|
121
|
+
|
|
122
|
+
def get_dependency_type(self) -> ParametrizedDependencySource:
|
|
123
|
+
return ParametrizedDependencySource.GROUPED_DICT
|
|
124
|
+
|
|
125
|
+
@classmethod
|
|
126
|
+
def resolve_dependency_type(cls, annotated_type: type[Mapping[str, type]], param_name: str):
|
|
127
|
+
if typing_inspect.is_optional_type(
|
|
128
|
+
annotated_type
|
|
129
|
+
): # need to pull out the type from Optional.
|
|
130
|
+
annotated_type = typing_inspect.get_args(annotated_type)[0]
|
|
131
|
+
origin = typing_inspect.get_origin(annotated_type)
|
|
132
|
+
if origin is None or not issubclass(origin, typing.Mapping):
|
|
133
|
+
raise InvalidDecoratorException(
|
|
134
|
+
f"Type: {annotated_type} for parameter: {param_name} needs to be a"
|
|
135
|
+
f"mapping type to use the group() dependency specification with **kwargs. "
|
|
136
|
+
f"Otherwise hamilton cannot validate that the types are correct!"
|
|
137
|
+
)
|
|
138
|
+
args = typing_inspect.get_args(annotated_type)
|
|
139
|
+
if not len(args) == 2 or not issubclass(args[0], str):
|
|
140
|
+
raise InvalidDecoratorException(
|
|
141
|
+
f"Type: {annotated_type} for parameter: {param_name} needs to be a"
|
|
142
|
+
f"mapping with types [str, Type] to use the group() dependency specification with "
|
|
143
|
+
f"**kwargs. Otherwise Hamilton cannot validate that the types are correct."
|
|
144
|
+
)
|
|
145
|
+
return args[1]
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def value(literal_value: Any) -> LiteralDependency:
|
|
149
|
+
"""Specifies that a parameterized dependency comes from a "literal" source.
|
|
150
|
+
|
|
151
|
+
E.G. value("foo") means that the value is actually the string value "foo".
|
|
152
|
+
|
|
153
|
+
:param literal_value: Python literal value to use.
|
|
154
|
+
:return: A LiteralDependency object -- a signifier to the internal framework of the dependency type.
|
|
155
|
+
"""
|
|
156
|
+
if isinstance(literal_value, LiteralDependency):
|
|
157
|
+
return literal_value
|
|
158
|
+
return LiteralDependency(value=literal_value)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def source(dependency_on: Any) -> UpstreamDependency:
|
|
162
|
+
"""Specifies that a parameterized dependency comes from an `upstream` source.
|
|
163
|
+
|
|
164
|
+
This means that it comes from a node somewhere else. E.G. source("foo") means that it should
|
|
165
|
+
be assigned the value that "foo" outputs.
|
|
166
|
+
|
|
167
|
+
:param dependency_on: Upstream function (i.e. node) to come from.
|
|
168
|
+
:return: An UpstreamDependency object -- a signifier to the internal framework of the dependency type.
|
|
169
|
+
"""
|
|
170
|
+
if isinstance(dependency_on, UpstreamDependency):
|
|
171
|
+
return dependency_on
|
|
172
|
+
return UpstreamDependency(source=dependency_on)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def configuration(dependency_on: str) -> ConfigDependency:
|
|
176
|
+
"""Specifies that a parameterized dependency comes from the global `config` passed in.
|
|
177
|
+
|
|
178
|
+
This means that it comes from a global configuration key value. E.G. config("foo") means that it should
|
|
179
|
+
be assigned the value that the "foo" key in global configuration passed to Hamilton maps to.
|
|
180
|
+
|
|
181
|
+
:param dependency_on: name of the configuration key to pull from.
|
|
182
|
+
:return: An ConfigDependency object -- a signifier to the internal framework of the dependency type.
|
|
183
|
+
"""
|
|
184
|
+
return ConfigDependency(source=dependency_on)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _validate_group_params(
|
|
188
|
+
dependency_args: list[ParametrizedDependency],
|
|
189
|
+
dependency_kwargs: dict[str, ParametrizedDependency],
|
|
190
|
+
):
|
|
191
|
+
"""Validates the following for params to group(...):
|
|
192
|
+
1. That either dependency_args or dependency_kwargs is non-empty, but not both.
|
|
193
|
+
2. That all values in dependency_args are of type either LiteralDependency or UpstreamDependency.
|
|
194
|
+
|
|
195
|
+
:param dependency_args: List of dependencies.
|
|
196
|
+
:param dependency_kwargs: Dict of dependencies.
|
|
197
|
+
:raises: InvalidDecoratorException if the above conditions are not met.
|
|
198
|
+
"""
|
|
199
|
+
if dependency_args and dependency_kwargs:
|
|
200
|
+
raise InvalidDecoratorException(
|
|
201
|
+
"group() can either represent a dictionary or a list of dependencies, not both!"
|
|
202
|
+
)
|
|
203
|
+
elif dependency_args:
|
|
204
|
+
for dependency in dependency_args:
|
|
205
|
+
if not isinstance(dependency, (LiteralDependency, UpstreamDependency)):
|
|
206
|
+
raise InvalidDecoratorException(
|
|
207
|
+
f"Dependency: {dependency} is not a valid dependency type for group(), must be "
|
|
208
|
+
f"a LiteralDependency or UpstreamDependency."
|
|
209
|
+
)
|
|
210
|
+
elif dependency_kwargs:
|
|
211
|
+
for dependency in dependency_kwargs.values():
|
|
212
|
+
if not isinstance(dependency, (LiteralDependency, UpstreamDependency)):
|
|
213
|
+
raise InvalidDecoratorException(
|
|
214
|
+
f"Dependency: {dependency} is not a valid dependency type for group(), must be "
|
|
215
|
+
f"a LiteralDependency or UpstreamDependency."
|
|
216
|
+
)
|
|
217
|
+
else:
|
|
218
|
+
raise InvalidDecoratorException(
|
|
219
|
+
"Either dependency_args or dependency_kwargs must be non-empty for group()!"
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def group(
|
|
224
|
+
*dependency_args: ParametrizedDependency, **dependency_kwargs: ParametrizedDependency
|
|
225
|
+
) -> GroupedDependency:
|
|
226
|
+
"""Specifies that a parameterized dependency comes from a "grouped" source.
|
|
227
|
+
|
|
228
|
+
This means that it gets injected into a list of dependencies that are grouped together. E.G.
|
|
229
|
+
dep=group(source("foo"), source("bar")) for the function:
|
|
230
|
+
|
|
231
|
+
.. code-block:: python
|
|
232
|
+
|
|
233
|
+
@inject(dep=group(source("foo"), source("bar")))
|
|
234
|
+
def f(dep: List[pd.Series]) -> pd.Series:
|
|
235
|
+
return ...
|
|
236
|
+
|
|
237
|
+
Would result in dep getting foo and bar dependencies injected.
|
|
238
|
+
|
|
239
|
+
:param dependency_args: Dependencies, list of dependencies (e.g. source("foo"), source("bar"))
|
|
240
|
+
:param dependency_kwargs: Dependencies, kwarg dependencies (e.g. foo=source("foo"))
|
|
241
|
+
:return:
|
|
242
|
+
"""
|
|
243
|
+
_validate_group_params(dependency_args, dependency_kwargs)
|
|
244
|
+
if dependency_args:
|
|
245
|
+
return GroupedListDependency(sources=list(dependency_args))
|
|
246
|
+
return GroupedDictDependency(sources=dependency_kwargs)
|