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,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)