Guard the Dask scatter in run_TPI so serial (client=None) runs work - #1212
Guard the Dask scatter in run_TPI so serial (client=None) runs work#1212vahid-ahmadi wants to merge 1 commit into
Conversation
run_TPI called client.scatter(p, broadcast=True) unconditionally, so run_TPI(p, client=None) raised AttributeError before the TPI loop was entered -- making the serial fallback inside the loop unreachable in exactly the case it exists for. SS.inner_loop already guards the equivalent block with `if client:`; this matches that. Adds a fast regression test that seeds baseline SS results from the cached test_io_data pickles and monkeypatches TPI.inner_loop to raise a sentinel, asserting only that execution reaches the first serial household solve. No SS or TPI solve is performed, so it runs in ~1s and needs no Dask cluster. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XCKMb1aicxYaeUC1us2nvF
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1212 +/- ##
==========================================
+ Coverage 74.07% 75.71% +1.64%
==========================================
Files 22 22
Lines 5920 5921 +1
==========================================
+ Hits 4385 4483 +98
+ Misses 1535 1438 -97
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
|
On the Codecov flag (8.33% patch coverage, 11 lines missing) — worth explaining, since it reads worse than it is. The diff is a guard plus a re-indent, so Codecov counts the 11 re-indented lines of the schema-backup/scatter/restore block as new. Those lines only execute with a Dask client, and the non-local CI suite runs without one — so they show as uncovered even though they are byte-identical to what was already there and already ran in the The same report shows I have separately verified the serial path is not just reachable but numerically correct: with |
Why
run_TPI(p, client=None)crashes.client.scatteris called unconditionally, so passing no Dask client raisesAttributeErrorbefore the TPI loop is entered — which makes the serial fallback atTPI.py:1039unreachable in exactly the case it exists for.SS.inner_loopalready guards the equivalent block withif client:; TPI doesn't.What changes after merging
Serial TPI runs work. Anyone calling
run_TPIwithout a Dask cluster — scripts, notebooks, CI, small debugging runs — goes from a hard crash to a working solve. No behaviour changes when a client is supplied.Change
Wraps the schema-backup / scatter / restore block in
if client:.scattered_p_futureis only read inside theif client:submit branch, so this is a guard plus an indent — no logic moves.Evidence
New
tests/test_TPI.py::test_run_TPI_serial_no_clientseeds SS from the cachedtest_io_datapickles and monkeypatchesinner_loopto raise a sentinel, asserting execution reaches the first serial household solve. No solve is run; ~1s, no Dask, so it is unmarked and guards this path in normal CI.Fixes the first half of #1211. The second half (SS re-scattering per residual evaluation) is #1214.