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,417 @@
|
|
|
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 __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import dataclasses
|
|
21
|
+
import textwrap
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
import pandas # noqa: F401
|
|
25
|
+
|
|
26
|
+
HAS_PANDAS = True
|
|
27
|
+
except ImportError:
|
|
28
|
+
HAS_PANDAS = False
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
import numpy # noqa: F401
|
|
32
|
+
|
|
33
|
+
HAS_NUMPY = True
|
|
34
|
+
except ImportError:
|
|
35
|
+
HAS_NUMPY = False
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
import polars # noqa: F401
|
|
39
|
+
|
|
40
|
+
HAS_POLARS = True
|
|
41
|
+
except ImportError:
|
|
42
|
+
HAS_POLARS = False
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
import graphviz # noqa: F401
|
|
46
|
+
|
|
47
|
+
HAS_GRAPHVIZ = True
|
|
48
|
+
except ImportError:
|
|
49
|
+
HAS_GRAPHVIZ = False
|
|
50
|
+
|
|
51
|
+
AVAILABLE_LIBS: dict[str, bool] = {
|
|
52
|
+
"pandas": HAS_PANDAS,
|
|
53
|
+
"numpy": HAS_NUMPY,
|
|
54
|
+
"polars": HAS_POLARS,
|
|
55
|
+
"graphviz": HAS_GRAPHVIZ,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclasses.dataclass(frozen=True)
|
|
60
|
+
class ScaffoldTemplate:
|
|
61
|
+
"""A scaffold template with its library requirements."""
|
|
62
|
+
|
|
63
|
+
name: str
|
|
64
|
+
description: str
|
|
65
|
+
code: str
|
|
66
|
+
requires: frozenset[str] = frozenset()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
ALL_TEMPLATES: list[ScaffoldTemplate] = [
|
|
70
|
+
ScaffoldTemplate(
|
|
71
|
+
name="basic_pure_python",
|
|
72
|
+
description="Simple data processing pipeline using only built-in Python types.",
|
|
73
|
+
requires=frozenset(),
|
|
74
|
+
code=textwrap.dedent('''\
|
|
75
|
+
"""Basic Hamilton module example (pure Python, no external libraries)."""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def raw_value(raw_value_input: int) -> int:
|
|
79
|
+
"""Pass-through for raw input value."""
|
|
80
|
+
return raw_value_input
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def doubled(raw_value: int) -> int:
|
|
84
|
+
"""Double the value."""
|
|
85
|
+
return raw_value * 2
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def message(doubled: int) -> str:
|
|
89
|
+
"""Create a summary message."""
|
|
90
|
+
return f"Result: {doubled}"
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# --- Driver script ---
|
|
94
|
+
# from hamilton import driver
|
|
95
|
+
# import my_module
|
|
96
|
+
#
|
|
97
|
+
# dr = driver.Builder().with_modules(my_module).build()
|
|
98
|
+
# result = dr.execute(
|
|
99
|
+
# ["message", "doubled"],
|
|
100
|
+
# inputs={"raw_value_input": 5},
|
|
101
|
+
# )
|
|
102
|
+
# print(result)
|
|
103
|
+
'''),
|
|
104
|
+
),
|
|
105
|
+
ScaffoldTemplate(
|
|
106
|
+
name="basic",
|
|
107
|
+
description="Simple data processing pipeline with pandas.",
|
|
108
|
+
requires=frozenset({"pandas"}),
|
|
109
|
+
code=textwrap.dedent('''\
|
|
110
|
+
"""Basic Hamilton module example."""
|
|
111
|
+
import pandas as pd
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def raw_data(raw_data_input: pd.DataFrame) -> pd.DataFrame:
|
|
115
|
+
"""Pass-through for raw input data."""
|
|
116
|
+
return raw_data_input
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def cleaned(raw_data: pd.DataFrame) -> pd.DataFrame:
|
|
120
|
+
"""Drop rows with missing values."""
|
|
121
|
+
return raw_data.dropna()
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def row_count(cleaned: pd.DataFrame) -> int:
|
|
125
|
+
"""Count rows after cleaning."""
|
|
126
|
+
return len(cleaned)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# --- Driver script ---
|
|
130
|
+
# from hamilton import driver
|
|
131
|
+
# import my_module
|
|
132
|
+
#
|
|
133
|
+
# dr = driver.Builder().with_modules(my_module).build()
|
|
134
|
+
# result = dr.execute(
|
|
135
|
+
# ["row_count", "cleaned"],
|
|
136
|
+
# inputs={"raw_data_input": pd.DataFrame({"a": [1, 2, None], "b": [4, None, 6]})},
|
|
137
|
+
# )
|
|
138
|
+
# print(result)
|
|
139
|
+
'''),
|
|
140
|
+
),
|
|
141
|
+
ScaffoldTemplate(
|
|
142
|
+
name="parameterized",
|
|
143
|
+
description="Using @parameterize to create multiple nodes from one function.",
|
|
144
|
+
requires=frozenset({"pandas"}),
|
|
145
|
+
code=textwrap.dedent('''\
|
|
146
|
+
"""Hamilton module using @parameterize to create multiple nodes."""
|
|
147
|
+
import pandas as pd
|
|
148
|
+
|
|
149
|
+
from hamilton.function_modifiers import parameterize, value
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@parameterize(
|
|
153
|
+
weekly_mean={"window": value(7)},
|
|
154
|
+
monthly_mean={"window": value(30)},
|
|
155
|
+
)
|
|
156
|
+
def rolling_mean(time_series: pd.Series, window: int) -> pd.Series:
|
|
157
|
+
"""Compute a rolling mean with a given window size."""
|
|
158
|
+
return time_series.rolling(window).mean()
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def time_series(time_series_input: pd.Series) -> pd.Series:
|
|
162
|
+
"""Pass-through for time series input."""
|
|
163
|
+
return time_series_input
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# --- Driver script ---
|
|
167
|
+
# from hamilton import driver
|
|
168
|
+
# import my_module
|
|
169
|
+
#
|
|
170
|
+
# dr = driver.Builder().with_modules(my_module).build()
|
|
171
|
+
# result = dr.execute(
|
|
172
|
+
# ["weekly_mean", "monthly_mean"],
|
|
173
|
+
# inputs={"time_series_input": pd.Series(range(60))},
|
|
174
|
+
# )
|
|
175
|
+
'''),
|
|
176
|
+
),
|
|
177
|
+
ScaffoldTemplate(
|
|
178
|
+
name="config_based",
|
|
179
|
+
description="Conditional logic with @config.when.",
|
|
180
|
+
requires=frozenset({"pandas"}),
|
|
181
|
+
code=textwrap.dedent('''\
|
|
182
|
+
"""Hamilton module using @config.when for conditional logic."""
|
|
183
|
+
import pandas as pd
|
|
184
|
+
|
|
185
|
+
from hamilton.function_modifiers import config
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@config.when(env="production")
|
|
189
|
+
def data_source__prod(db_connection_string: str) -> pd.DataFrame:
|
|
190
|
+
"""Load data from production database."""
|
|
191
|
+
# In real code: pd.read_sql("SELECT * FROM table", db_connection_string)
|
|
192
|
+
return pd.DataFrame({"value": [1, 2, 3]})
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
@config.when(env="development")
|
|
196
|
+
def data_source__dev() -> pd.DataFrame:
|
|
197
|
+
"""Return sample data for development."""
|
|
198
|
+
return pd.DataFrame({"value": [10, 20, 30]})
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def processed(data_source: pd.DataFrame) -> pd.DataFrame:
|
|
202
|
+
"""Process the data source."""
|
|
203
|
+
return data_source.assign(doubled=data_source["value"] * 2)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# --- Driver script ---
|
|
207
|
+
# from hamilton import driver
|
|
208
|
+
# import my_module
|
|
209
|
+
#
|
|
210
|
+
# dr = (
|
|
211
|
+
# driver.Builder()
|
|
212
|
+
# .with_modules(my_module)
|
|
213
|
+
# .with_config({"env": "development"})
|
|
214
|
+
# .build()
|
|
215
|
+
# )
|
|
216
|
+
# result = dr.execute(["processed"])
|
|
217
|
+
'''),
|
|
218
|
+
),
|
|
219
|
+
ScaffoldTemplate(
|
|
220
|
+
name="data_pipeline",
|
|
221
|
+
description="ETL workflow: ingest -> clean -> transform -> aggregate.",
|
|
222
|
+
requires=frozenset({"pandas"}),
|
|
223
|
+
code=textwrap.dedent('''\
|
|
224
|
+
"""Hamilton data pipeline: ingest -> clean -> transform -> aggregate."""
|
|
225
|
+
import pandas as pd
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def raw_data(raw_data_input: pd.DataFrame) -> pd.DataFrame:
|
|
229
|
+
"""Ingest raw data."""
|
|
230
|
+
return raw_data_input
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def cleaned_data(raw_data: pd.DataFrame) -> pd.DataFrame:
|
|
234
|
+
"""Remove nulls and duplicates."""
|
|
235
|
+
return raw_data.dropna().drop_duplicates()
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def spend(cleaned_data: pd.DataFrame) -> pd.Series:
|
|
239
|
+
"""Extract the spend column."""
|
|
240
|
+
return cleaned_data["spend"].abs()
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def avg_spend(spend: pd.Series) -> float:
|
|
244
|
+
"""Average spend across all records."""
|
|
245
|
+
return spend.mean()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def total_spend(spend: pd.Series) -> float:
|
|
249
|
+
"""Total spend across all records."""
|
|
250
|
+
return spend.sum()
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
# --- Driver script ---
|
|
254
|
+
# from hamilton import driver
|
|
255
|
+
# import my_module
|
|
256
|
+
#
|
|
257
|
+
# dr = driver.Builder().with_modules(my_module).build()
|
|
258
|
+
# result = dr.execute(
|
|
259
|
+
# ["avg_spend", "total_spend"],
|
|
260
|
+
# inputs={"raw_data_input": pd.DataFrame({"spend": [-10, 20, -30]})},
|
|
261
|
+
# )
|
|
262
|
+
'''),
|
|
263
|
+
),
|
|
264
|
+
ScaffoldTemplate(
|
|
265
|
+
name="ml_pipeline",
|
|
266
|
+
description="Feature engineering and train/test split with pandas and numpy.",
|
|
267
|
+
requires=frozenset({"pandas", "numpy"}),
|
|
268
|
+
code=textwrap.dedent('''\
|
|
269
|
+
"""Hamilton ML pipeline: features -> train/test split -> model -> metrics."""
|
|
270
|
+
import pandas as pd
|
|
271
|
+
import numpy as np
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def feature_matrix(feature_matrix_input: pd.DataFrame) -> pd.DataFrame:
|
|
275
|
+
"""Input feature matrix."""
|
|
276
|
+
return feature_matrix_input
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def target(target_input: pd.Series) -> pd.Series:
|
|
280
|
+
"""Input target variable."""
|
|
281
|
+
return target_input
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def train_fraction() -> float:
|
|
285
|
+
"""Fraction of data for training."""
|
|
286
|
+
return 0.8
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def train_indices(
|
|
290
|
+
feature_matrix: pd.DataFrame, train_fraction: float
|
|
291
|
+
) -> np.ndarray:
|
|
292
|
+
"""Random train indices."""
|
|
293
|
+
n = len(feature_matrix)
|
|
294
|
+
idx = np.arange(n)
|
|
295
|
+
np.random.shuffle(idx)
|
|
296
|
+
return idx[: int(n * train_fraction)]
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def test_indices(
|
|
300
|
+
feature_matrix: pd.DataFrame, train_indices: np.ndarray
|
|
301
|
+
) -> np.ndarray:
|
|
302
|
+
"""Test indices (complement of train)."""
|
|
303
|
+
all_idx = set(range(len(feature_matrix)))
|
|
304
|
+
return np.array(sorted(all_idx - set(train_indices)))
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def train_X(feature_matrix: pd.DataFrame, train_indices: np.ndarray) -> pd.DataFrame:
|
|
308
|
+
"""Training features."""
|
|
309
|
+
return feature_matrix.iloc[train_indices]
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def test_X(feature_matrix: pd.DataFrame, test_indices: np.ndarray) -> pd.DataFrame:
|
|
313
|
+
"""Test features."""
|
|
314
|
+
return feature_matrix.iloc[test_indices]
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def train_y(target: pd.Series, train_indices: np.ndarray) -> pd.Series:
|
|
318
|
+
"""Training target."""
|
|
319
|
+
return target.iloc[train_indices]
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def test_y(target: pd.Series, test_indices: np.ndarray) -> pd.Series:
|
|
323
|
+
"""Test target."""
|
|
324
|
+
return target.iloc[test_indices]
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
# --- Driver script ---
|
|
328
|
+
# from hamilton import driver
|
|
329
|
+
# import my_module
|
|
330
|
+
#
|
|
331
|
+
# dr = driver.Builder().with_modules(my_module).build()
|
|
332
|
+
# result = dr.execute(
|
|
333
|
+
# ["train_X", "test_X", "train_y", "test_y"],
|
|
334
|
+
# inputs={
|
|
335
|
+
# "feature_matrix_input": pd.DataFrame({"a": range(100), "b": range(100)}),
|
|
336
|
+
# "target_input": pd.Series(range(100)),
|
|
337
|
+
# },
|
|
338
|
+
# )
|
|
339
|
+
'''),
|
|
340
|
+
),
|
|
341
|
+
ScaffoldTemplate(
|
|
342
|
+
name="data_quality",
|
|
343
|
+
description="Data validation with @check_output.",
|
|
344
|
+
requires=frozenset({"pandas", "numpy"}),
|
|
345
|
+
code=textwrap.dedent('''\
|
|
346
|
+
"""Hamilton module with data quality checks using @check_output."""
|
|
347
|
+
import pandas as pd
|
|
348
|
+
import numpy as np
|
|
349
|
+
|
|
350
|
+
from hamilton.function_modifiers import check_output
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
@check_output(
|
|
354
|
+
data_type=np.float64,
|
|
355
|
+
range=(0, None),
|
|
356
|
+
)
|
|
357
|
+
def spend(spend_raw: pd.Series) -> pd.Series:
|
|
358
|
+
"""Clean spend: ensure non-negative floats."""
|
|
359
|
+
return spend_raw.abs().astype(float)
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
@check_output(
|
|
363
|
+
data_type=np.float64,
|
|
364
|
+
)
|
|
365
|
+
def revenue(revenue_raw: pd.Series) -> pd.Series:
|
|
366
|
+
"""Clean revenue data."""
|
|
367
|
+
return revenue_raw.astype(float)
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def profit(revenue: pd.Series, spend: pd.Series) -> pd.Series:
|
|
371
|
+
"""Profit = revenue - spend."""
|
|
372
|
+
return revenue - spend
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
# --- Driver script ---
|
|
376
|
+
# from hamilton import driver
|
|
377
|
+
# import my_module
|
|
378
|
+
#
|
|
379
|
+
# dr = driver.Builder().with_modules(my_module).build()
|
|
380
|
+
# result = dr.execute(
|
|
381
|
+
# ["profit"],
|
|
382
|
+
# inputs={
|
|
383
|
+
# "spend_raw": pd.Series([10, 20, 30]),
|
|
384
|
+
# "revenue_raw": pd.Series([100, 200, 300]),
|
|
385
|
+
# },
|
|
386
|
+
# )
|
|
387
|
+
'''),
|
|
388
|
+
),
|
|
389
|
+
]
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
def get_available_templates(
|
|
393
|
+
preferred_libraries: set[str] | None = None,
|
|
394
|
+
) -> dict[str, ScaffoldTemplate]:
|
|
395
|
+
"""Return templates filtered by library availability.
|
|
396
|
+
|
|
397
|
+
If *preferred_libraries* is provided, only templates whose requirements
|
|
398
|
+
are a subset of the preferred set are returned. Otherwise, falls back
|
|
399
|
+
to auto-detection via ``AVAILABLE_LIBS``.
|
|
400
|
+
"""
|
|
401
|
+
if preferred_libraries is not None:
|
|
402
|
+
return {t.name: t for t in ALL_TEMPLATES if t.requires <= preferred_libraries}
|
|
403
|
+
return {
|
|
404
|
+
t.name: t
|
|
405
|
+
for t in ALL_TEMPLATES
|
|
406
|
+
if all(AVAILABLE_LIBS.get(lib, False) for lib in t.requires)
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
def get_capabilities(
|
|
411
|
+
preferred_libraries: set[str] | None = None,
|
|
412
|
+
) -> dict:
|
|
413
|
+
"""Return capabilities, optionally filtered by user-specified libraries."""
|
|
414
|
+
return {
|
|
415
|
+
"libraries": dict(AVAILABLE_LIBS),
|
|
416
|
+
"available_scaffolds": sorted(get_available_templates(preferred_libraries).keys()),
|
|
417
|
+
}
|