Skip to content

Guard against process-wide warning filters set while building the model #2377

Closed

Description

@MaxGhenis

Until 12 October 2026, three variable modules called warnings.filterwarnings("ignore") at import: LHA_allowed_bedrooms.py, LHA_cap.py and LHA_eligible.py. bi_household_phaseout's formula did the same on every call. policyengine-core runs every variable file again each time a CountryTaxBenefitSystem is built, so building a system or a Simulation put a global "ignore" at the front of warnings.filters. That silenced every warning in the process, including inside pytest.warns and warnings.catch_warnings blocks entered before the build. On 11 October a ReformPeriodWarning from policyengine_uk/utils/dated_reforms.py (#2305) never reached the caller, and pytest.warns recorded [].

#1846 (merged 12 October, commit 00c07d6) removed the four filters. It replaced the divisions they were hiding with np.divide(..., where=). Its fresh-interpreter test covers import policyengine_uk. Three gaps remain:

  1. No test checks that building CountryTaxBenefitSystem() or Simulation(situation=...), or calculating variables, leaves warnings.filters unchanged and lets a later UserWarning through. Each build runs every variable module again, so a filter at the top of any variable file would come back unnoticed.
  2. No static guard stops a module from changing the process's warning filters (or numpy's error state) outside warnings.catch_warnings() / np.errstate(). A filter inside a formula only runs when that formula runs, so a build test alone would not catch one.
  3. Apply dated reforms on the statutory timeline on every route #2305 worked around the filters. dated_reforms._warn logs each ReformPeriodWarning as well, with the comment "some variable modules switch warnings off when loaded", and its tests assert on caplog instead of pytest.warns. That reason no longer holds, and callers now see each message twice.

Where the filters came from (git history):

  • The LHA filter was added in Add Local Housing Allowance parameters #787 (2023-11-26) to LHA.py. That module time-shifted the BRMA list of rents with pandas and assigned columns on filtered slices (df.year = ..., df.weekly_rent = ...), which raises SettingWithCopyWarning. One variable per file #1139 (2025-06-06) split LHA.py into one file per variable and copied the header into all of them, including three files with no pandas code. 43ef96f (2026-10-01) removed it from BRMA_LHA_rate, LHA_category and uc_LHA_cap.
  • The basic income filter was added in 999424c (2022-10-31), just before where(household_bi > 0, capped_deduction / household_bi, 0). where evaluates both branches, so the 0/0 case raised a numpy RuntimeWarning.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions