| # Licensed to the Apache Software Foundation (ASF) under one | |
| # or more contributor license agreements. See the NOTICE file | |
| # distributed with this work for additional information | |
| # regarding copyright ownership. The ASF licenses this file | |
| # to you under the Apache License, Version 2.0 (the | |
| # "License"); you may not use this file except in compliance | |
| # with the License. You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, | |
| # software distributed under the License is distributed on an | |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| # KIND, either express or implied. See the License for the | |
| # specific language governing permissions and limitations | |
| # under the License. | |
| """Functions that use Hamilton decorators. | |
| Decorators are a common source of confusion when testing. The point of this | |
| module is to show that decorators do not get in the way of unit testing -- the | |
| function below the decorator is still a plain Python callable, so you can call | |
| it directly from a test. To test what the decorator *expands to*, drive the | |
| function through a Driver instead (see ``test_decorated_functions.py``). | |
| """ | |
| import pandas as pd | |
| from hamilton.function_modifiers import extract_columns, parameterize, source, tag, value | |
| @tag(owner="growth-team", pii="false") | |
| def total_signups(signups: pd.Series) -> int: | |
| """Sum of signups across the time window.""" | |
| return int(signups.sum()) | |
| @parameterize( | |
| spend_in_thousands={"raw_value": source("spend"), "divisor": value(1000.0)}, | |
| signups_in_hundreds={"raw_value": source("signups"), "divisor": value(100.0)}, | |
| ) | |
| def scaled(raw_value: pd.Series, divisor: float) -> pd.Series: | |
| """Scale a series by a constant divisor. | |
| `@parameterize` produces one node per entry above. The function itself is | |
| still a normal callable, so a unit test can call ``scaled(some_series, 1000)`` | |
| directly without a Driver. | |
| """ | |
| return raw_value / divisor | |
| @extract_columns("scaled_spend", "scaled_signups") | |
| def scaled_features(spend_in_thousands: pd.Series, signups_in_hundreds: pd.Series) -> pd.DataFrame: | |
| """Bundle the two scaled series into a frame, then expose each column as a node.""" | |
| return pd.DataFrame({"scaled_spend": spend_in_thousands, "scaled_signups": signups_in_hundreds}) |