Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/645.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK reform contract's household route now runs when country imports are skipped, so the candidate script's `POLICYENGINE_SKIP_COUNTRY_IMPORTS` no longer turns every `wrapper.household` row into an error and rejects every UK candidate.
Original file line number Diff line number Diff line change
Expand Up @@ -1257,10 +1257,14 @@ class _WrapperHouseholdRoute:
route = "wrapper.household"

def _call(self, case: Case, year: int, reform, variables: Sequence[str]):
import policyengine as pe
# Import the country module itself, not ``policyengine.uk``: callers such
# as scripts/check_uk_candidate.py set POLICYENGINE_SKIP_COUNTRY_IMPORTS,
# which leaves ``policyengine.uk`` as None. It is the same
# ``calculate_household`` that ``policyengine.uk`` exposes.
from policyengine.tax_benefit_models import uk as pe_uk

household = case.household
return pe.uk.calculate_household(
return pe_uk.calculate_household(
people=[dict(person) for person in household.people],
benunit=dict(household.benunit),
household=dict(household.household),
Expand Down
46 changes: 46 additions & 0 deletions tests/test_uk_budget_reform_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@

import datetime
import json
import os
import subprocess
import sys
import textwrap

import pytest

Expand Down Expand Up @@ -2004,3 +2008,45 @@ def array(tag, variable, year):
order = status[(population.POPULATION_QUERY_ORDER, "unreformed")]
assert order["status"] == "fail"
assert order["detail"]["income_tax:2026_matches"] is False


def test_the_household_route_runs_when_country_imports_are_skipped():
# scripts/check_uk_candidate.py sets POLICYENGINE_SKIP_COUNTRY_IMPORTS=1
# before the qualification gates run this contract, and that leaves
# ``policyengine.uk`` as None. Reaching the wrapper through it made every
# wrapper.household row an error, so every UK candidate was rejected.
code = textwrap.dedent(
"""
import json
import os

os.environ["POLICYENGINE_SKIP_COUNTRY_IMPORTS"] = "1"
import policyengine

assert policyengine.uk is None
from policyengine.tax_benefit_models.uk.budget_reform_contract import (
CASES,
evaluate_case,
)

case = next(case for case in CASES if case.id == "april_rate_change")
rows = evaluate_case(case, "wrapper.household")
print(json.dumps([[row["status"], row.get("detail")] for row in rows]))
"""
)
env = {
key: value
for key, value in os.environ.items()
if key != "POLICYENGINE_SKIP_COUNTRY_IMPORTS"
}
result = subprocess.run(
[sys.executable, "-c", code],
capture_output=True,
text=True,
env=env,
timeout=900,
)
assert result.returncode == 0, result.stderr
rows = json.loads(result.stdout.strip().splitlines()[-1])
assert rows
assert [row for row in rows if row[0] == "error"] == [], rows
Loading