config.when*

@config.when allows you to specify different implementations depending on configuration parameters.

Note the following:

  • The function cannot have the same name in the same file (or python gets unhappy), so we name it with a __ (dunderscore) as a suffix. The dunderscore is removed before it goes into the DAG.

  • There is currently no @config.otherwise(...) decorator, so make sure to have config.when specify set of configuration possibilities. Any missing cases will not have that output column (and subsequent downstream nodes may error out if they ask for it). To make this easier, we have a few more @config decorators:

    • @config.when_not(param=value) Will be included if the parameter is _not_ equal to the value specified.

    • @config.when_in(param=[value1, value2, ...]) Will be included if the parameter is equal to one of the specified values.

    • @config.when_not_in(param=[value1, value2, ...]) Will be included if the parameter is not equal to any of the specified values.

    • @config If you’re feeling adventurous, you can pass in a lambda function that takes in the entire configuration and resolves to True or False. You probably don’t want to do this.


Reference Documentation

class hamilton.function_modifiers.config(resolves: Callable[[Dict[str, Any]], bool], target_name: str = None, config_used: List[str] = None)

Decorator class that determines whether a function should be in the DAG based on some configuration variable.

Notes:

  1. Currently, functions that exist in all configurations have to be disjoint.

  2. There is currently no @config.otherwise(...) decorator, so make sure to have config.when specify set of configuration possibilities. Any missing cases will not have that output (and subsequent downstream functions may error out if they ask for it).

  3. To make this easier, we have a few more @config decorators:
    • @config.when_not(param=value) Will be included if the parameter is _not_ equal to the value specified.

    • @config.when_in(param=[value1, value2, ...]) Will be included if the parameter is equal to one of the specified values.

    • @config.when_not_in(param=[value1, value2, ...]) Will be included if the parameter is not equal to any of the specified values.

    • @config If you’re feeling adventurous, you can pass in a lambda function that takes in the entire configuration and resolves to True or False. You probably don’t want to do this.

Example:

@config.when_in(business_line=["mens","kids"], region=["uk"])
def LEAD_LOG_BASS_MODEL_TIMES_TREND(
     TREND_BSTS_WOMENS_ACQUISITIONS: pd.Series,
     LEAD_LOG_BASS_MODEL_SIGNUPS_NON_REFERRAL: pd.Series) -> pd.Series:
     # logic
     ...

Example - use of __suffix to differentiate between functions with the same name. This is required if you want to use the same function name in multiple configurations. Hamilton will automatically drop the suffix for you. The following will ensure only one function is registered with the name my_transform:

@config.when(region="us")
def my_transform__us(some_input: pd.Series, some_input_b: pd.Series) -> pd.Series:
     # logic
     ...

@config.when(region="uk")
def my_transform__uk(some_input: pd.Series, some_input_c: pd.Series) -> pd.Series:
     # logic
     ...

@config If you’re feeling adventurous, you can pass in a lambda function that takes in the entire configuration and resolves to True or False. You probably don’t want to do this.

__init__(resolves: Callable[[Dict[str, Any]], bool], target_name: str = None, config_used: List[str] = None)

Decorator that resolves a function based on the configuration…

Parameters:
  • resolves – the python function to use to resolve whether the wrapped function should exist in the graph or not.

  • target_name – Optional. The name of the “function”/”node” that we want to attach @config to.

  • config_used – Optional. The list of config names that this function uses.

static when(name=None, **key_value_pairs) config

Yields a decorator that resolves the function if all keys in the config are equal to the corresponding value.

Parameters:

key_value_pairs – Keys and corresponding values to look up in the config

Returns:

a configuration decorator

static when_in(name=None, **key_value_group_pairs: Collection[Any]) config

Yields a decorator that resolves the function if all of the values corresponding to the config keys are equal to one of items in the list of values.

@config.when_in(param=[value1, value2, ...]) Will be included if the parameter is equal to one of the specified values.

Parameters:

key_value_group_pairs – pairs of key-value mappings where the value is a list of possible values

Returns:

a configuration decorator

static when_not(name=None, **key_value_pairs: Any) config

Yields a decorator that resolves the function if none keys in the config are equal to the corresponding value

@config.when_not(param=value) will be included if the parameter is _not_ equal to the value specified.

Parameters:

key_value_pairs – Keys and corresponding values to look up in the config

Returns:

a configuration decorator

static when_not_in(**key_value_group_pairs: Collection[Any]) config

Yields a decorator that resolves the function only if none of the keys are in the list of values.

@config.when_not_in(param=[value1, value2, ...]) Will be included if the parameter is not equal to any of the specified values.

Parameters:

key_value_group_pairs – pairs of key-value mappings where the value is a list of possible values

Returns:

a configuration decorator

@config.when_not_in(business_line=["mens","kids"], region=["uk"])
def LEAD_LOG_BASS_MODEL_TIMES_TREND(
    TREND_BSTS_WOMENS_ACQUISITIONS: pd.Series,
    LEAD_LOG_BASS_MODEL_SIGNUPS_NON_REFERRAL: pd.Series) -> pd.Series:

above will resolve for config has {“business_line”: “womens”, “region”: “us”}, but not for configs that have {“business_line”: “mens”, “region”: “us”}, {“business_line”: “kids”, “region”: “us”}, or {“region”: “uk”}.

See also

:ref:config.when_not