blob: 93f89e2aa81aeb151a82cee764eb613dd255ab9a [file]
# 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})