Reforms#
The policyengine_core.reforms module contains the definition for Reform, a class which can be used to edit a TaxBenefitSystem instance.
Reform#
- class policyengine_core.reforms.Reform(baseline: TaxBenefitSystem)#
A modified TaxBenefitSystem
All reforms must subclass Reform and implement a method apply().
In this method, the reform can add or replace variables and call modify_parameters to modify the parameters of the legislation.
Example:
>>> from policyengine_core import reforms >>> from policyengine_core.parameters import load_parameter_file >>> >>> def modify_my_parameters(parameters): >>> # Add new parameters >>> new_parameters = load_parameter_file(name='reform_name', file_path='path_to_yaml_file.yaml') >>> parameters.add_child('reform_name', new_parameters) >>> >>> # Update a value >>> parameters.taxes.some_tax.some_param.update(period=some_period, value=1000.0) >>> >>> return parameters >>> >>> class MyReform(reforms.Reform): >>> def apply(self): >>> self.add_variable(some_variable) >>> self.update_variable(some_other_variable) >>> self.modify_parameters(modifier_function = modify_my_parameters)
- static from_dict(parameter_values: dict, country_id: str = None, name: str = None) Reform#
Create a reform from a dictionary of parameters.
- Parameters:
parameter_values – A mapping of
path -> {period_key: value}(or thepath -> scalarshorthand, applied acrossyear:2000:100).
Period-key formats, interpreted per parameter (see the module-level
_*_update_kwargshelpers):Bare ISO instant (
"2026"/"2026-01"/"2026-01-01"): the value applies from that instant onward, flattening any later scheduled breakpoints (e.g. uprating). The instant is literal:{"2026-06-01": v}applies from 1 June 2026, so an annual value read at 1 January 2026 is still the baseline — use"2026-01-01"for a full-year-onward change. To keep later breakpoints, bound the change with a range instead.Range
"start.stop"(e.g."2026-01-01.2027-12-31"): the value applies over the bounded interval[start, stop]; the prior value is restored afterwards.Compound bounded period (
"year:2026:5"/"month:2026-01:3"): the value applies over that bounded period only."ETERNITY": the value applies for all time.
Entries are applied in ascending start-instant order, so a later-starting key never clobbers an earlier one. Entries sharing a start instant are applied in their given order (the last wins for any overlap). Non-string keys are coerced to
str.Invalid input raises during construction before any parameter is modified: a malformed period key or bad value yields no partial reform, and errors from
Parameter.updatepropagate rather than being silently swallowed.- Returns:
A reform.
- modify_parameters(modifier_function: Callable[[ParameterNode], ParameterNode]) None#
Make modifications on the parameters of the legislation.
Call this function in apply() if the reform asks for legislation parameter modifications.
- Parameters:
modifier_function – A function that takes a
ParameterNodeand should return an object of the same type.
- preprocess_situation(situation: dict, default_period=None) dict#
Normalize entity-form input before the builder creates populations.
Country models can override this to fill missing entity definitions.
SimulationBuilder.build_from_entitiespasses a deep copy of the caller’s situation, with anyaxesstill present, and its default period as set (None, a string, an integer or aPeriod). Throughbuild_from_dictandSimulation(situation=...), singular entity aliases are already expanded; a directbuild_from_entitiescall passes the caller’s keys as given. The hook runs before the builder validates entities, so it may receive a situation with no persons. Return a dict holding an entity-form situation for the builder’s usual validation. AReformruns its country system’s hook with the reform as the system, so the hook sees reformed parameters and variables. Only the country system’s hook runs: aReformsubclass that overrides this method is skipped when another reform wraps it, and a hook set on the country system instance itself stays bound to that instance, so it reads the baseline’s values. Dataset and variable-only inputs do not use this hook.