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.)
In 0.18.0,
get_pop_objsfails for the homogeneous (no income heterogeneity) case that 0.17.x supported, becauseexpand_pop_obj_Jassertsincome_percentiles is not Nonebefore reaching its own all-inputs-Nonebranch.Repro
Cause
get_pop_objsnow callsexpand_pop_obj_Junconditionally, and inexpand_pop_obj_Jthe assert at demographics.py:942 sits above theall_income_inputs_noneearly-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) isNone— i.e. for every pre-0.18 call signature.income_percentilesdefaults toNoneinget_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. treatincome_percentiles=Noneas[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 requiringincome_percentilesis intended, since it's a breaking change for every downstream caller.Downstream impact
OG-UK's
calibrate()breaks on 0.18.0; we cappedogcore>=0.15.6,<0.18in 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_datawraps itsinput()token prompt inexcept EOFErroronly, so under pytest's capture the stdin read raisesOSErrorinstead of falling through — an env-var token path would make headless runs cleaner. Happy to file separately if useful.)