diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29bb2d..08481968cd9 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,4 @@ +- bump: minor + changes: + added: + - Add five-year-forward check on all reforms diff --git a/policyengine_us/reforms/biden/budget_2025/__init__.py b/policyengine_us/reforms/biden/budget_2025/__init__.py index 6d3655bcf4a..587d35ff1a5 100644 --- a/policyengine_us/reforms/biden/budget_2025/__init__.py +++ b/policyengine_us/reforms/biden/budget_2025/__init__.py @@ -3,5 +3,5 @@ ) from .capital_gains_tax_increase import ( - create_capital_gains_tax_increase_reform, + create_capital_gains_tax_increase, ) diff --git a/policyengine_us/reforms/biden/budget_2025/capital_gains_tax_increase.py b/policyengine_us/reforms/biden/budget_2025/capital_gains_tax_increase.py index 8ec22746075..6d60586e2d6 100644 --- a/policyengine_us/reforms/biden/budget_2025/capital_gains_tax_increase.py +++ b/policyengine_us/reforms/biden/budget_2025/capital_gains_tax_increase.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_capital_gains_tax_increase() -> Reform: @@ -138,20 +139,10 @@ def apply(self): return reform -def create_capital_gains_tax_increase_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_capital_gains_tax_increase() - - p = parameters(period).gov.contrib.biden.budget_2025.capital_gains - - if p.active: - return create_capital_gains_tax_increase() - else: - return None - - -capital_gains_tax_increase = create_capital_gains_tax_increase_reform( - None, None, bypass=True +capital_gains_tax_increase = create_reform_if_active( + None, + None, + "gov.contrib.biden.budget_2025.capital_gains.active", + create_capital_gains_tax_increase, + bypass=True, ) diff --git a/policyengine_us/reforms/biden/budget_2025/medicare_and_investment_tax_increase.py b/policyengine_us/reforms/biden/budget_2025/medicare_and_investment_tax_increase.py index ba3c848c77e..ae3aa7b6dae 100644 --- a/policyengine_us/reforms/biden/budget_2025/medicare_and_investment_tax_increase.py +++ b/policyengine_us/reforms/biden/budget_2025/medicare_and_investment_tax_increase.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_core.periods import period as period_ def create_medicare_and_investment_tax_increase() -> Reform: @@ -74,9 +75,20 @@ def create_medicare_and_investment_tax_increase_reform( if bypass: return create_medicare_and_investment_tax_increase() - p = parameters(period).gov.contrib.biden.budget_2025 + p = parameters.gov.contrib.biden.budget_2025 + current_period = period_(period) + reform_active = False - if (p.medicare.rate > 0) | (p.net_investment_income.rate > 0): + for i in range(5): + if ( + p(current_period).medicare.rate > 0 + or p(current_period).net_investment_income.rate > 0 + ): + reform_active = True + break + current_period = current_period.offset(1, "year") + + if reform_active: return create_medicare_and_investment_tax_increase() else: return None diff --git a/policyengine_us/reforms/cbo/payroll/increase_taxable_earnings_for_social_security.py b/policyengine_us/reforms/cbo/payroll/increase_taxable_earnings_for_social_security.py index 1199cf18dbe..25a5e2dcaec 100644 --- a/policyengine_us/reforms/cbo/payroll/increase_taxable_earnings_for_social_security.py +++ b/policyengine_us/reforms/cbo/payroll/increase_taxable_earnings_for_social_security.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_core.periods import period as period_ def create_increase_taxable_earnings_for_social_security() -> Reform: @@ -32,9 +33,17 @@ def create_increase_taxable_earnings_for_social_security_reform( if bypass: return create_increase_taxable_earnings_for_social_security() - p = parameters(period).gov.contrib.cbo.payroll + p = parameters.gov.contrib.cbo.payroll + current_period = period_(period) + reform_active = False - if p.secondary_earnings_threshold < np.inf: + for i in range(5): + if p(current_period).secondary_earnings_threshold < np.inf: + reform_active = True + break + current_period = current_period.offset(1, "year") + + if reform_active: return create_increase_taxable_earnings_for_social_security() else: return None diff --git a/policyengine_us/reforms/congress/romney/family_security_act/__init__.py b/policyengine_us/reforms/congress/romney/family_security_act/__init__.py index 59c98945fb4..4fd517e8fdf 100644 --- a/policyengine_us/reforms/congress/romney/family_security_act/__init__.py +++ b/policyengine_us/reforms/congress/romney/family_security_act/__init__.py @@ -1 +1 @@ -from .remove_head_of_household import create_remove_head_of_household_reform +from .remove_head_of_household import create_remove_head_of_household diff --git a/policyengine_us/reforms/congress/romney/family_security_act/remove_head_of_household.py b/policyengine_us/reforms/congress/romney/family_security_act/remove_head_of_household.py index 5f79428a080..2d0445d8c5c 100644 --- a/policyengine_us/reforms/congress/romney/family_security_act/remove_head_of_household.py +++ b/policyengine_us/reforms/congress/romney/family_security_act/remove_head_of_household.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_core.periods import period as period_ +from policyengine_us.reforms.utils import create_reform_if_active def create_remove_head_of_household() -> Reform: @@ -10,29 +10,10 @@ def apply(self): return reform -def create_remove_head_of_household_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_remove_head_of_household() - - # Look ahead for the next five years - p = parameters.gov.contrib.congress.romney.family_security_act - reform_active = False - current_period = period_(period) - - for i in range(5): - if p(current_period).remove_head_of_household: - reform_active = True - break - current_period = current_period.offset(1, "year") - - if reform_active: - return create_remove_head_of_household() - else: - return None - - -remove_head_of_household = create_remove_head_of_household_reform( - None, None, bypass=True +remove_head_of_household = create_reform_if_active( + None, + None, + "gov.contrib.congress.romney.family_security_act.remove_head_of_household", + create_remove_head_of_household, + bypass=True, ) diff --git a/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/__init__.py b/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/__init__.py index e2c8cde734c..9506374c8b0 100644 --- a/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/__init__.py +++ b/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/__init__.py @@ -1,3 +1 @@ -from .family_security_act_2024_ctc import ( - create_family_security_act_2024_ctc_reform, -) +from .family_security_act_2024_ctc import create_family_security_act_2024_ctc diff --git a/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/family_security_act_2024_ctc.py b/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/family_security_act_2024_ctc.py index 4480b811fa5..8d8c4e5afbb 100644 --- a/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/family_security_act_2024_ctc.py +++ b/policyengine_us/reforms/congress/romney/family_security_act_2024/ctc/family_security_act_2024_ctc.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_core.periods import period as period_ +from policyengine_us.reforms.utils import create_reform_if_active def create_family_security_act_2024_ctc() -> Reform: @@ -139,29 +139,10 @@ def apply(self): return reform -def create_family_security_act_2024_ctc_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_family_security_act_2024_ctc() - - # Look ahead for the next five years - p = parameters.gov.contrib.congress.romney.family_security_act_2_0.ctc - reform_active = False - current_period = period_(period) - - for i in range(5): - if p(current_period).apply_ctc_structure: - reform_active = True - break - current_period = current_period.offset(1, "year") - - if reform_active: - return create_family_security_act_2024_ctc() - else: - return None - - -family_security_act_2024_ctc = create_family_security_act_2024_ctc_reform( - None, None, bypass=True +family_security_act_2024_ctc = create_reform_if_active( + None, + None, + "gov.contrib.congress.romney.family_security_act_2_0.ctc.apply_ctc_structure", + create_family_security_act_2024_ctc, + bypass=True, ) diff --git a/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/__init__.py b/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/__init__.py index de74b2a5f41..b77c3c96549 100644 --- a/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/__init__.py +++ b/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/__init__.py @@ -1,3 +1 @@ -from .family_security_act_2024_eitc import ( - create_family_security_act_2024_eitc_reform, -) +from .family_security_act_2024_eitc import create_family_security_act_2024_eitc diff --git a/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/family_security_act_2024_eitc.py b/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/family_security_act_2024_eitc.py index 00b7fc73be0..424d4ea6f8e 100644 --- a/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/family_security_act_2024_eitc.py +++ b/policyengine_us/reforms/congress/romney/family_security_act_2024/eitc/family_security_act_2024_eitc.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_core.periods import period as period_ +from policyengine_us.reforms.utils import create_reform_if_active def create_family_security_act_2024_eitc() -> Reform: @@ -30,29 +30,10 @@ def apply(self): return reform -def create_family_security_act_2024_eitc_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_family_security_act_2024_eitc() - - # Look ahead for the next five years - p = parameters.gov.contrib.congress.romney.family_security_act_2_0.eitc - reform_active = False - current_period = period_(period) - - for i in range(5): - if p(current_period).apply_eitc_structure: - reform_active = True - break - current_period = current_period.offset(1, "year") - - if reform_active: - return create_family_security_act_2024_eitc() - else: - return None - - -family_security_act_2024_eitc = create_family_security_act_2024_eitc_reform( - None, None, bypass=True +family_security_act_2024_eitc = create_reform_if_active( + None, + None, + "gov.contrib.congress.romney.family_security_act_2_0.eitc.apply_eitc_structure", + create_family_security_act_2024_eitc, + bypass=True, ) diff --git a/policyengine_us/reforms/congress/tlaib/__init__.py b/policyengine_us/reforms/congress/tlaib/__init__.py index df1660eaeed..d30891bbd6c 100644 --- a/policyengine_us/reforms/congress/tlaib/__init__.py +++ b/policyengine_us/reforms/congress/tlaib/__init__.py @@ -1,3 +1,3 @@ from .end_child_poverty_act import ( - create_end_child_poverty_act_reform, + create_end_child_poverty_act, ) diff --git a/policyengine_us/reforms/congress/tlaib/boost/__init__.py b/policyengine_us/reforms/congress/tlaib/boost/__init__.py index b485fd1bc65..ca25deb4815 100644 --- a/policyengine_us/reforms/congress/tlaib/boost/__init__.py +++ b/policyengine_us/reforms/congress/tlaib/boost/__init__.py @@ -1,3 +1,3 @@ from .boost_middle_class_tax_credit import ( - create_boost_middle_class_tax_credit_reform, + create_boost_middle_class_tax_credit, ) diff --git a/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py b/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py index 57a2d87df04..67a9c2ad354 100644 --- a/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py +++ b/policyengine_us/reforms/congress/tlaib/boost/boost_middle_class_tax_credit.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_boost_middle_class_tax_credit() -> Reform: @@ -140,20 +141,10 @@ def apply(self): return reform -def create_boost_middle_class_tax_credit_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_boost_middle_class_tax_credit() - - p = parameters(period).gov.contrib.harris.lift.middle_class_tax_credit - - if p.in_effect: - return create_boost_middle_class_tax_credit() - else: - return None - - -boost_middle_class_tax_credit = create_boost_middle_class_tax_credit_reform( - None, None, bypass=True +boost_middle_class_tax_credit = create_reform_if_active( + None, + None, + "gov.contrib.harris.lift.middle_class_tax_credit.in_effect", + create_boost_middle_class_tax_credit, + bypass=True, ) diff --git a/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py b/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py index e85f226b509..3fa9fa007f4 100644 --- a/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py +++ b/policyengine_us/reforms/congress/tlaib/end_child_poverty_act.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_end_child_poverty_act() -> Reform: @@ -176,17 +177,22 @@ def apply(self): def create_end_child_poverty_act_reform( parameters, period, bypass: bool = False ): - if bypass: + if bypass or parameters is None: return create_end_child_poverty_act() p = parameters(period).gov.contrib.congress.tlaib.end_child_poverty_act + reform_active = reform_is_active(p, period) - if p.in_effect: + if reform_active: return create_end_child_poverty_act() else: return None -end_child_poverty_act = create_end_child_poverty_act_reform( - None, None, bypass=True +end_child_poverty_act = create_reform_if_active( + None, + None, + "gov.contrib.congress.tlaib.end_child_poverty_act.in_effect", + create_end_child_poverty_act, + bypass=True, ) diff --git a/policyengine_us/reforms/congress/wyden_smith/__init__.py b/policyengine_us/reforms/congress/wyden_smith/__init__.py index 5fe7adb89a6..63da14da2ee 100644 --- a/policyengine_us/reforms/congress/wyden_smith/__init__.py +++ b/policyengine_us/reforms/congress/wyden_smith/__init__.py @@ -1 +1 @@ -from .ctc_expansion import create_ctc_expansion_reform +from .ctc_expansion import create_ctc_expansion diff --git a/policyengine_us/reforms/congress/wyden_smith/ctc_expansion.py b/policyengine_us/reforms/congress/wyden_smith/ctc_expansion.py index 91520b53eb3..b0a4039244a 100644 --- a/policyengine_us/reforms/congress/wyden_smith/ctc_expansion.py +++ b/policyengine_us/reforms/congress/wyden_smith/ctc_expansion.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_core.periods import period as period_ +from policyengine_us.reforms.utils import create_reform_if_active def create_ctc_expansion() -> Reform: @@ -104,30 +104,11 @@ def apply(self): return reform -def create_ctc_expansion_reform(parameters, period, bypass: bool = False): - if bypass: - return create_ctc_expansion() - - # Look ahead for the next five years - - p = parameters.gov.contrib.congress.wyden_smith - - reform_active = False - current_period = period_(period) - - for i in range(5): - if ( - p(current_period).actc_lookback - or p(current_period).per_child_actc_phase_in - ): - reform_active = True - break - current_period = current_period.offset(1, "year") - - if reform_active: - return create_ctc_expansion() - else: - return None - - -ctc_expansion = create_ctc_expansion_reform(None, None, bypass=True) +# actc_lookback / per_child_actc_phase_in +ctc_expansion = create_reform_if_active( + None, + None, + "gov.contrib.congress.wyden_smith", + create_ctc_expansion, + bypass=True, +) diff --git a/policyengine_us/reforms/dc_kccatc.py b/policyengine_us/reforms/dc_kccatc.py index 0bf5ee9d66e..1da701b26b2 100644 --- a/policyengine_us/reforms/dc_kccatc.py +++ b/policyengine_us/reforms/dc_kccatc.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_dc_kccatc_reform(parameters, period, bypass=False): @@ -87,10 +88,11 @@ class reform(Reform): def apply(self): self.update_variable(dc_kccatc) - if bypass or parameters(period).gov.contrib.dc_kccatc.active: - return reform - else: - return None - -dc_kccatc_reform = create_dc_kccatc_reform(None, None, True) +dc_kccatc_reform = create_reform_if_active( + None, + None, + "gov.contrib.dc_kccatc.active", + create_dc_kccatc_reform, + bypass=True, +) diff --git a/policyengine_us/reforms/eitc/__init__.py b/policyengine_us/reforms/eitc/__init__.py index b7c008b5e95..1040292a7d1 100644 --- a/policyengine_us/reforms/eitc/__init__.py +++ b/policyengine_us/reforms/eitc/__init__.py @@ -1,3 +1,3 @@ from .halve_joint_eitc_phase_out_rate import ( - create_halve_joint_eitc_phase_out_rate_reform, + create_halve_joint_eitc_phase_out_rate, ) diff --git a/policyengine_us/reforms/eitc/halve_joint_eitc_phase_out_rate.py b/policyengine_us/reforms/eitc/halve_joint_eitc_phase_out_rate.py index ac94bae72dc..f83c9e967fb 100644 --- a/policyengine_us/reforms/eitc/halve_joint_eitc_phase_out_rate.py +++ b/policyengine_us/reforms/eitc/halve_joint_eitc_phase_out_rate.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_halve_joint_eitc_phase_out_rate() -> Reform: @@ -25,20 +26,10 @@ def apply(self): return reform -def create_halve_joint_eitc_phase_out_rate_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_halve_joint_eitc_phase_out_rate() - - p = parameters(period).gov.contrib.joint_eitc - - if p.in_effect: - return create_halve_joint_eitc_phase_out_rate() - else: - return None - - -halve_joint_eitc_phase_out_rate = ( - create_halve_joint_eitc_phase_out_rate_reform(None, None, bypass=True) +halve_joint_eitc_phase_out_rate = create_reform_if_active( + None, + None, + "gov.contrib.joint_eitc.in_effect", + create_halve_joint_eitc_phase_out_rate, + bypass=True, ) diff --git a/policyengine_us/reforms/federal/__init__.py b/policyengine_us/reforms/federal/__init__.py index 818d777f5bf..6ee256220ae 100644 --- a/policyengine_us/reforms/federal/__init__.py +++ b/policyengine_us/reforms/federal/__init__.py @@ -1,5 +1,5 @@ from .abolish_federal_income_tax import ( - create_abolish_federal_income_tax_reform, + create_abolish_federal_income_tax, ) -from .abolish_payroll_tax import create_abolish_payroll_tax_reform -from .reported_state_income_tax import create_reported_state_income_tax_reform +from .abolish_payroll_tax import create_abolish_payroll_tax +from .reported_state_income_tax import create_reported_state_income_tax diff --git a/policyengine_us/reforms/federal/abolish_federal_income_tax.py b/policyengine_us/reforms/federal/abolish_federal_income_tax.py index 71517463770..104ee94ef24 100644 --- a/policyengine_us/reforms/federal/abolish_federal_income_tax.py +++ b/policyengine_us/reforms/federal/abolish_federal_income_tax.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_abolish_federal_income_tax() -> Reform: @@ -47,20 +48,10 @@ def apply(self): return reform -def create_abolish_federal_income_tax_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_abolish_federal_income_tax() - - p = parameters(period).gov.contrib.ubi_center.flat_tax - - if p.abolish_federal_income_tax: - return create_abolish_federal_income_tax() - else: - return None - - -abolish_federal_income_tax = create_abolish_federal_income_tax_reform( - None, None, bypass=True +abolish_federal_income_tax = create_reform_if_active( + None, + None, + "gov.contrib.ubi_center.flat_tax.abolish_federal_income_tax", + create_abolish_federal_income_tax, + bypass=True, ) diff --git a/policyengine_us/reforms/federal/abolish_payroll_tax.py b/policyengine_us/reforms/federal/abolish_payroll_tax.py index d6192b47671..31b16218a62 100644 --- a/policyengine_us/reforms/federal/abolish_payroll_tax.py +++ b/policyengine_us/reforms/federal/abolish_payroll_tax.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_abolish_payroll_tax() -> Reform: @@ -27,20 +28,10 @@ def apply(self): return reform -def create_abolish_payroll_tax_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_abolish_payroll_tax() - - p = parameters(period).gov.contrib.ubi_center.flat_tax - - if p.abolish_payroll_tax: - return create_abolish_payroll_tax() - else: - return None - - -abolish_payroll_tax = create_abolish_payroll_tax_reform( - None, None, bypass=True +abolish_payroll_tax = create_reform_if_active( + None, + None, + "gov.contrib.ubi_center.flat_tax.abolish_payroll_tax", + create_abolish_payroll_tax, + bypass=True, ) diff --git a/policyengine_us/reforms/federal/reported_state_income_tax.py b/policyengine_us/reforms/federal/reported_state_income_tax.py index 5f6b90294fc..cba7a18bbf5 100644 --- a/policyengine_us/reforms/federal/reported_state_income_tax.py +++ b/policyengine_us/reforms/federal/reported_state_income_tax.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_reported_state_income_tax() -> Reform: @@ -54,20 +55,10 @@ def apply(self): return reform -def create_reported_state_income_tax_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_reported_state_income_tax() - - p = parameters(period).simulation - - if p.reported_state_income_tax: - return create_reported_state_income_tax() - else: - return None - - -reported_state_income_tax = create_reported_state_income_tax_reform( - None, None, bypass=True +reported_state_income_tax = create_reform_if_active( + None, + None, + "simulation.reported_state_income_tax", + create_reported_state_income_tax, + bypass=True, ) diff --git a/policyengine_us/reforms/harris/lift/__init__.py b/policyengine_us/reforms/harris/lift/__init__.py index 73bd8fd8f2a..ed14a4e8c4b 100644 --- a/policyengine_us/reforms/harris/lift/__init__.py +++ b/policyengine_us/reforms/harris/lift/__init__.py @@ -1,3 +1,3 @@ from .middle_class_tax_credit import ( - create_middle_class_tax_credit_reform, + create_middle_class_tax_credit, ) diff --git a/policyengine_us/reforms/harris/lift/middle_class_tax_credit.py b/policyengine_us/reforms/harris/lift/middle_class_tax_credit.py index a438321d9ef..b2fd66cd31f 100644 --- a/policyengine_us/reforms/harris/lift/middle_class_tax_credit.py +++ b/policyengine_us/reforms/harris/lift/middle_class_tax_credit.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_middle_class_tax_credit() -> Reform: @@ -54,20 +55,10 @@ def apply(self): return reform -def create_middle_class_tax_credit_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_middle_class_tax_credit() - - p = parameters(period).gov.contrib.harris.lift.middle_class_tax_credit - - if p.in_effect: - return create_middle_class_tax_credit() - else: - return None - - -middle_class_tax_credit = create_middle_class_tax_credit_reform( - None, None, bypass=True +middle_class_tax_credit = create_reform_if_active( + None, + None, + "gov.contrib.harris.lift.middle_class_tax_credit.in_effect", + create_middle_class_tax_credit, + bypass=True, ) diff --git a/policyengine_us/reforms/harris/rent_relief_act/__init__.py b/policyengine_us/reforms/harris/rent_relief_act/__init__.py index 264d741974b..e414a954df3 100644 --- a/policyengine_us/reforms/harris/rent_relief_act/__init__.py +++ b/policyengine_us/reforms/harris/rent_relief_act/__init__.py @@ -1,3 +1,3 @@ from .rent_relief_tax_credit import ( - create_rent_relief_tax_credit_reform, + create_rent_relief_tax_credit, ) diff --git a/policyengine_us/reforms/harris/rent_relief_act/rent_relief_tax_credit.py b/policyengine_us/reforms/harris/rent_relief_act/rent_relief_tax_credit.py index a3db48068a7..2aa4e0e1b98 100644 --- a/policyengine_us/reforms/harris/rent_relief_act/rent_relief_tax_credit.py +++ b/policyengine_us/reforms/harris/rent_relief_act/rent_relief_tax_credit.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_rent_relief_tax_credit() -> Reform: @@ -74,22 +75,10 @@ def apply(self): return reform -def create_rent_relief_tax_credit_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_rent_relief_tax_credit() - - p = parameters( - period - ).gov.contrib.harris.rent_relief_act.rent_relief_credit - - if p.in_effect: - return create_rent_relief_tax_credit() - else: - return None - - -rent_relief_tax_credit = create_rent_relief_tax_credit_reform( - None, None, bypass=True +rent_relief_tax_credit = create_reform_if_active( + None, + None, + "gov.contrib.harris.rent_relief_act.rent_relief_credit.in_effect", + create_rent_relief_tax_credit, + bypass=True, ) diff --git a/policyengine_us/reforms/local/nyc/stc/adjust_income_limit_by_filing_status_and_eligibility_by_children.py b/policyengine_us/reforms/local/nyc/stc/adjust_income_limit_by_filing_status_and_eligibility_by_children.py index 46cd0d13ae4..97d1822045c 100644 --- a/policyengine_us/reforms/local/nyc/stc/adjust_income_limit_by_filing_status_and_eligibility_by_children.py +++ b/policyengine_us/reforms/local/nyc/stc/adjust_income_limit_by_filing_status_and_eligibility_by_children.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_adjust_income_limit_and_min_children_by_filing_status() -> Reform: @@ -48,20 +49,10 @@ def apply(self): return reform -def create_adjust_income_limit_by_filing_status_and_eligibility_by_children_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_adjust_income_limit_and_min_children_by_filing_status() - - p = parameters(period).gov.contrib.local.nyc.stc - - if p.adjust_income_limit_by_filing_status_and_eligibility_by_children: - return create_adjust_income_limit_and_min_children_by_filing_status() - else: - return None - - -adjust_income_limit_and_min_children_by_filing_status = create_adjust_income_limit_by_filing_status_and_eligibility_by_children_reform( - None, None, bypass=True +adjust_income_limit_and_min_children_by_filing_status = create_reform_if_active( + None, + None, + "gov.contrib.local.nyc.stc.adjust_income_limit_by_filing_status_and_eligibility_by_children", + create_adjust_income_limit_and_min_children_by_filing_status, + bypass=True, ) diff --git a/policyengine_us/reforms/reforms.py b/policyengine_us/reforms/reforms.py index 7e392e4080f..30e2014d3a8 100644 --- a/policyengine_us/reforms/reforms.py +++ b/policyengine_us/reforms/reforms.py @@ -5,54 +5,55 @@ create_dc_tax_threshold_joint_ratio_reform, ) from .congress.romney.family_security_act import ( - create_remove_head_of_household_reform, + create_remove_head_of_household, ) from .cbo.payroll import ( create_increase_taxable_earnings_for_social_security_reform, ) -from .congress.wyden_smith import create_ctc_expansion_reform -from .federal import create_abolish_federal_income_tax_reform -from .federal import create_abolish_payroll_tax_reform -from .federal import create_reported_state_income_tax_reform +from .congress.wyden_smith import create_ctc_expansion +from .federal import create_abolish_federal_income_tax +from .federal import create_abolish_payroll_tax +from .federal import create_reported_state_income_tax from .biden.budget_2025 import ( create_medicare_and_investment_tax_increase_reform, ) -from .biden.budget_2025 import create_capital_gains_tax_increase_reform -from .eitc import create_halve_joint_eitc_phase_out_rate_reform -from .states.ny.wftc import create_ny_working_families_tax_credit_reform +from .biden.budget_2025 import create_capital_gains_tax_increase +from .eitc import create_halve_joint_eitc_phase_out_rate +from .states.ny.wftc import create_ny_working_families_tax_credit from .states.dc.dc_ctc import ( - create_dc_ctc_reform, + create_dc_ctc, ) from .harris.lift.middle_class_tax_credit import ( - create_middle_class_tax_credit_reform, + create_middle_class_tax_credit, ) from .harris.rent_relief_act.rent_relief_tax_credit import ( - create_rent_relief_tax_credit_reform, + create_rent_relief_tax_credit, ) from .congress.tlaib import ( - create_end_child_poverty_act_reform, + create_end_child_poverty_act, ) from .congress.tlaib.boost import ( - create_boost_middle_class_tax_credit_reform, + create_boost_middle_class_tax_credit, ) from .states.mn.walz import ( - create_mn_walz_hf1938_repeal_reform, + create_mn_walz_hf1938_repeal, ) from .states.oregon.rebate import ( - create_or_rebate_state_tax_exempt_reform, + create_or_rebate_state_tax_exempt, ) from .congress.romney.family_security_act_2024.ctc import ( - create_family_security_act_2024_ctc_reform, + create_family_security_act_2024_ctc, ) from .congress.romney.family_security_act_2024.eitc import ( - create_family_security_act_2024_eitc_reform, + create_family_security_act_2024_eitc, ) from .treasury.repeal_dependent_exemptions import ( - create_repeal_dependent_exemptions_reform, + create_repeal_dependent_exemptions, ) from policyengine_core.reforms import Reform import warnings +from policyengine_us.reforms.utils import create_reform_if_active def create_structural_reforms_from_parameters(parameters, period): @@ -64,8 +65,12 @@ def create_structural_reforms_from_parameters(parameters, period): dc_tax_threshold_joint_ratio_reform = ( create_dc_tax_threshold_joint_ratio_reform(parameters, period) ) - remove_head_of_household = create_remove_head_of_household_reform( - parameters, period + remove_head_of_household = create_reform_if_active( + parameters, + period, + "gov.contrib.congress.romney.family_security_act.remove_head_of_household", + create_remove_head_of_household, + bypass=True, ) increase_taxable_earnings_for_social_security_reform = ( create_increase_taxable_earnings_for_social_security_reform( @@ -75,50 +80,128 @@ def create_structural_reforms_from_parameters(parameters, period): medicare_and_investment_tax_increase = ( create_medicare_and_investment_tax_increase_reform(parameters, period) ) - ctc_expansion = create_ctc_expansion_reform(parameters, period) - - abolish_federal_income_tax = create_abolish_federal_income_tax_reform( - parameters, period - ) - abolish_payroll_tax = create_abolish_payroll_tax_reform(parameters, period) - reported_state_income_tax = create_reported_state_income_tax_reform( - parameters, period + ctc_expansion = create_reform_if_active( + parameters, + period, + "gov.contrib.congress.wyden_smith", + create_ctc_expansion, + bypass=True, ) - capital_gains_tax_increase = create_capital_gains_tax_increase_reform( - parameters, period - ) - halve_joint_eitc_phase_out_rate = ( - create_halve_joint_eitc_phase_out_rate_reform(parameters, period) - ) - ny_wftc = create_ny_working_families_tax_credit_reform(parameters, period) - - dc_ctc = create_dc_ctc_reform(parameters, period) - middle_class_tax_credit = create_middle_class_tax_credit_reform( - parameters, period + abolish_federal_income_tax = create_reform_if_active( + parameters, + period, + "gov.contrib.ubi_center.flat_tax.abolish_federal_income_tax", + create_abolish_federal_income_tax, + bypass=True, + ) + abolish_payroll_tax = create_reform_if_active( + parameters, + period, + "gov.contrib.ubi_center.flat_tax.abolish_payroll_tax", + create_abolish_payroll_tax, + bypass=True, + ) + reported_state_income_tax = create_reform_if_active( + parameters, + period, + "simulation.reported_state_income_tax", + create_reported_state_income_tax, + bypass=True, + ) + capital_gains_tax_increase = create_reform_if_active( + parameters, + period, + "gov.contrib.biden.budget_2025.capital_gains.active", + create_capital_gains_tax_increase, + bypass=True, + ) + halve_joint_eitc_phase_out_rate = create_reform_if_active( + parameters, + period, + "gov.contrib.joint_eitc.in_effect", + create_halve_joint_eitc_phase_out_rate, + bypass=True, + ) + ny_wftc = create_reform_if_active( + parameters, + period, + "gov.contrib.states.ny.wftc.in_effect", + create_ny_working_families_tax_credit, + bypass=True, ) - rent_relief_tax_credit = create_rent_relief_tax_credit_reform( - parameters, period - ) - end_child_poverty_act = create_end_child_poverty_act_reform( - parameters, period - ) - boost_middle_class_tax_credit = ( - create_boost_middle_class_tax_credit_reform(parameters, period) - ) - mn_walz_hf1938 = create_mn_walz_hf1938_repeal_reform(parameters, period) - or_rebate_state_tax_exempt = create_or_rebate_state_tax_exempt_reform( - parameters, period + dc_ctc = create_reform_if_active( + parameters, + period, + "gov.contrib.states.dc.ctc.in_effect", + create_dc_ctc, + bypass=True, ) - family_security_act_2024_ctc = create_family_security_act_2024_ctc_reform( - parameters, period - ) - family_security_act_2024_eitc = ( - create_family_security_act_2024_eitc_reform(parameters, period) + + middle_class_tax_credit = create_reform_if_active( + parameters, + period, + "gov.contrib.harris.lift.middle_class_tax_credit.in_effect", + create_middle_class_tax_credit, + bypass=True, + ) + rent_relief_tax_credit = create_reform_if_active( + parameters, + period, + "gov.contrib.harris.rent_relief_act.rent_relief_credit.in_effect", + create_rent_relief_tax_credit, + bypass=True, + ) + end_child_poverty_act = create_reform_if_active( + parameters, + period, + "gov.contrib.congress.tlaib.end_child_poverty_act.in_effect", + create_end_child_poverty_act, + bypass=True, + ) + boost_middle_class_tax_credit = create_reform_if_active( + parameters, + period, + "gov.contrib.harris.lift.middle_class_tax_credit.in_effect", + create_boost_middle_class_tax_credit, + bypass=True, + ) + mn_walz_hf1938 = create_reform_if_active( + parameters, + period, + "gov.contrib.states.mn.walz.hf1938.repeal", + create_mn_walz_hf1938_repeal, + bypass=True, ) - repeal_dependent_exemptions = create_repeal_dependent_exemptions_reform( - parameters, period + + or_rebate_state_tax_exempt = create_reform_if_active( + parameters, + period, + "gov.contrib.states.or.rebate.state_tax_exempt", + create_or_rebate_state_tax_exempt, + bypass=True, + ) + family_security_act_2024_ctc = create_reform_if_active( + parameters, + period, + "gov.contrib.congress.romney.family_security_act_2_0.ctc.apply_ctc_structure", + create_family_security_act_2024_ctc, + bypass=True, + ) + family_security_act_2024_eitc = create_reform_if_active( + parameters, + period, + "gov.contrib.congress.romney.family_security_act_2_0.eitc.apply_eitc_structure", + create_family_security_act_2024_eitc, + bypass=True, + ) + repeal_dependent_exemptions = create_reform_if_active( + parameters, + period, + "gov.contrib.treasury.repeal_dependent_exemptions", + create_repeal_dependent_exemptions, + bypass=True, ) reforms = [ diff --git a/policyengine_us/reforms/states/dc/__init__.py b/policyengine_us/reforms/states/dc/__init__.py index 499ba20f994..528edb05544 100644 --- a/policyengine_us/reforms/states/dc/__init__.py +++ b/policyengine_us/reforms/states/dc/__init__.py @@ -1,3 +1,3 @@ from .dc_ctc import ( - create_dc_ctc_reform, + create_dc_ctc, ) diff --git a/policyengine_us/reforms/states/dc/dc_ctc.py b/policyengine_us/reforms/states/dc/dc_ctc.py index d49d37a2363..80b6ab01ace 100644 --- a/policyengine_us/reforms/states/dc/dc_ctc.py +++ b/policyengine_us/reforms/states/dc/dc_ctc.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_core.periods import period as period_ +from policyengine_us.reforms.utils import create_reform_if_active def create_dc_ctc() -> Reform: @@ -56,19 +56,10 @@ def apply(self): return reform -def create_dc_ctc_reform(parameters, period, bypass: bool = False): - if bypass: - return create_dc_ctc() - - p = parameters.gov.contrib.states.dc.ctc - - current_period = period_(period) - - for i in range(5): - if p(current_period).in_effect: - return create_dc_ctc() - current_period = current_period.offset(1, "year") - return None - - -dc_ctc = create_dc_ctc_reform(None, None, bypass=True) +dc_ctc = create_reform_if_active( + None, + None, + "gov.contrib.states.dc.ctc.in_effect", + create_dc_ctc, + bypass=True, +) diff --git a/policyengine_us/reforms/states/mn/walz/__init__.py b/policyengine_us/reforms/states/mn/walz/__init__.py index 1ce9082695b..0b73f2b6c16 100644 --- a/policyengine_us/reforms/states/mn/walz/__init__.py +++ b/policyengine_us/reforms/states/mn/walz/__init__.py @@ -1,3 +1,3 @@ from .mn_walz_hf1938 import ( - create_mn_walz_hf1938_repeal_reform, + create_mn_walz_hf1938_repeal, ) diff --git a/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py b/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py index 16f729546dd..609847b71a5 100644 --- a/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py +++ b/policyengine_us/reforms/states/mn/walz/mn_walz_hf1938.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active # Repealing Minnesota Bill HF1938 to pre 2023 rules @@ -205,18 +206,10 @@ def apply(self): return reform -def create_mn_walz_hf1938_repeal_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_mn_walz_hf1938_repeal() - - p = parameters(period).gov.contrib.states.mn.walz.hf1938 - - if p.repeal: - return create_mn_walz_hf1938_repeal() - else: - return None - - -mn_walz_hf1938 = create_mn_walz_hf1938_repeal_reform(None, None, bypass=True) +mn_walz_hf1938 = create_reform_if_active( + None, + None, + "gov.contrib.states.mn.walz.hf1938.repeal", + create_mn_walz_hf1938_repeal, + bypass=True, +) diff --git a/policyengine_us/reforms/states/ny/wftc/__init__.py b/policyengine_us/reforms/states/ny/wftc/__init__.py index b3426cf2007..f4446f05ba5 100644 --- a/policyengine_us/reforms/states/ny/wftc/__init__.py +++ b/policyengine_us/reforms/states/ny/wftc/__init__.py @@ -1,3 +1,3 @@ from .ny_working_families_tax_credit import ( - create_ny_working_families_tax_credit_reform, + create_ny_working_families_tax_credit, ) diff --git a/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py b/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py index aa879a39906..7324493f16d 100644 --- a/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py +++ b/policyengine_us/reforms/states/ny/wftc/ny_working_families_tax_credit.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_ny_working_families_tax_credit() -> Reform: @@ -523,20 +524,10 @@ def apply(self): return reform -def create_ny_working_families_tax_credit_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_ny_working_families_tax_credit() - - p = parameters(period).gov.contrib.states.ny.wftc - - if p.in_effect: - return create_ny_working_families_tax_credit() - else: - return None - - -ny_working_families_tax_credit = create_ny_working_families_tax_credit_reform( - None, None, bypass=True +ny_working_families_tax_credit = create_reform_if_active( + None, + None, + "gov.contrib.states.ny.wftc.in_effect", + create_ny_working_families_tax_credit, + bypass=True, ) diff --git a/policyengine_us/reforms/states/oregon/rebate/__init__.py b/policyengine_us/reforms/states/oregon/rebate/__init__.py index dcdb3de90a4..780057c2beb 100644 --- a/policyengine_us/reforms/states/oregon/rebate/__init__.py +++ b/policyengine_us/reforms/states/oregon/rebate/__init__.py @@ -1,3 +1,3 @@ from .or_rebate_state_tax_exempt import ( - create_or_rebate_state_tax_exempt_reform, + create_or_rebate_state_tax_exempt, ) diff --git a/policyengine_us/reforms/states/oregon/rebate/or_rebate_state_tax_exempt.py b/policyengine_us/reforms/states/oregon/rebate/or_rebate_state_tax_exempt.py index 6752deaafb3..159b53d44df 100644 --- a/policyengine_us/reforms/states/oregon/rebate/or_rebate_state_tax_exempt.py +++ b/policyengine_us/reforms/states/oregon/rebate/or_rebate_state_tax_exempt.py @@ -1,4 +1,5 @@ from policyengine_us.model_api import * +from policyengine_us.reforms.utils import create_reform_if_active def create_or_rebate_state_tax_exempt() -> Reform: @@ -42,20 +43,10 @@ def apply(self): return reform -def create_or_rebate_state_tax_exempt_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_or_rebate_state_tax_exempt() - - p = parameters(period).gov.contrib.states["or"].rebate - - if p.state_tax_exempt: - return create_or_rebate_state_tax_exempt() - else: - return None - - -or_rebate_state_tax_exempt = create_or_rebate_state_tax_exempt_reform( - None, None, bypass=True +or_rebate_state_tax_exempt = create_reform_if_active( + None, + None, + "gov.contrib.states.or.rebate.state_tax_exempt", + create_or_rebate_state_tax_exempt, + bypass=True, ) diff --git a/policyengine_us/reforms/treasury/__init__.py b/policyengine_us/reforms/treasury/__init__.py index 7f07b4360a7..0a19a4458ed 100644 --- a/policyengine_us/reforms/treasury/__init__.py +++ b/policyengine_us/reforms/treasury/__init__.py @@ -1,3 +1,3 @@ from .repeal_dependent_exemptions import ( - create_repeal_dependent_exemptions_reform, + create_repeal_dependent_exemptions, ) diff --git a/policyengine_us/reforms/treasury/repeal_dependent_exemptions.py b/policyengine_us/reforms/treasury/repeal_dependent_exemptions.py index 47a35439834..2d5763e29e0 100644 --- a/policyengine_us/reforms/treasury/repeal_dependent_exemptions.py +++ b/policyengine_us/reforms/treasury/repeal_dependent_exemptions.py @@ -1,5 +1,5 @@ from policyengine_us.model_api import * -from policyengine_core.periods import period as period_ +from policyengine_us.reforms.utils import create_reform_if_active def create_repeal_dependent_exemptions() -> Reform: @@ -22,29 +22,10 @@ def apply(self): return reform -def create_repeal_dependent_exemptions_reform( - parameters, period, bypass: bool = False -): - if bypass: - return create_repeal_dependent_exemptions() - - p = parameters.gov.contrib.treasury - - reform_active = False - current_period = period_(period) - - for i in range(5): - if p(current_period).repeal_dependent_exemptions: - reform_active = True - break - current_period = current_period.offset(1, "year") - - if reform_active: - return create_repeal_dependent_exemptions() - else: - return None - - -repeal_dependent_exemptions = create_repeal_dependent_exemptions_reform( - None, None, bypass=True +repeal_dependent_exemptions = create_reform_if_active( + None, + None, + "gov.contrib.treasury.repeal_dependent_exemptions", + create_repeal_dependent_exemptions, + bypass=True, ) diff --git a/policyengine_us/reforms/utils.py b/policyengine_us/reforms/utils.py new file mode 100644 index 00000000000..6e848584047 --- /dev/null +++ b/policyengine_us/reforms/utils.py @@ -0,0 +1,37 @@ +from policyengine_core.periods import period as period_ + + +def create_reform_if_active( + parameters, period, parameter_path, reform_function, bypass: bool = False +): + """ + Check if a reform's parameter is truthy in any of the next five years and create the reform if so. + + Args: + parameters: The parameters object from the reform function. + period: The current period. + parameter_path: A string representing the path to the relevant parameter. + reform_function: A function that creates and returns the reform. + bypass: If True, always return the reform regardless of the parameter value. + + Returns: + Reform or None: The reform if the parameter is truthy or bypassed, None otherwise. + """ + + def create_reform(): + if "parameters" in reform_function.__code__.co_varnames: + return reform_function(parameters, period) + else: + return reform_function() + + if bypass: + return create_reform() + + current_period = period_(period) + + for _ in range(5): + if parameters(current_period).get_descendants(parameter_path): + return create_reform() + current_period = current_period.offset(1, "year") + + return None