Skip to content

0.18.0: get_pop_objs requires income_percentiles even in the homogeneous case (assert precedes the all-None branch) #1180

Description

@MaxGhenis

In 0.18.0, get_pop_objs fails for the homogeneous (no income heterogeneity) case that 0.17.x supported, because expand_pop_obj_J asserts income_percentiles is not None before reaching its own all-inputs-None branch.

Repro

from ogcore import demographics

demographics.get_pop_objs(
    E=20, S=80, T=320,
    country_id="826",
    initial_data_year=2026,
    final_data_year=2027,
    GraphDiag=False,
)
File "ogcore/demographics.py", line 1591, in get_pop_objs
    pop_objs = expand_pop_obj_J(
File "ogcore/demographics.py", line 942, in expand_pop_obj_J
    assert income_percentiles is not None, (
AssertionError: income_percentiles must be provided when using income-specific inputs.

Cause

get_pop_objs now calls expand_pop_obj_J unconditionally, and in expand_pop_obj_J the assert at demographics.py:942 sits above the all_income_inputs_none early-return branch (~:953) that handles the homogeneous case. So the assert fires even when every income-specific input (fert_gradient, mort_gradient, infmort_gradient, imm_pctiles) is None — i.e. for every pre-0.18 call signature. income_percentiles defaults to None in get_pop_objs, which makes the default signature self-contradictory.

Suggested fix

Either default to a single income group when all income-specific inputs are None (e.g. treat income_percentiles=None as [100] in that branch, preserving the 0.17 behavior and output shapes for existing consumers), or move the assert inside the income-specific path — plus a release-note flag if requiring income_percentiles is intended, since it's a breaking change for every downstream caller.

Downstream impact

OG-UK's calibrate() breaks on 0.18.0; we capped ogcore>=0.15.6,<0.18 in PSLmodels/OG-UK#69 pending resolution here, with migration to the income-heterogeneity API as a follow-up.

(Separate minor note hit while debugging: get_un_data wraps its input() token prompt in except EOFError only, so under pytest's capture the stdin read raises OSError instead of falling through — an env-var token path would make headless runs cleaner. Happy to file separately if useful.)

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