fix(flomni,lamni): use .get() in tomo_queue_show()'s job-line formatter #297

Merged
holler merged 1 commits from fix/tomo-queue-show-keyerror into main 2026-08-17 15:53:54 +02:00
4 changed files with 70 additions and 7 deletions
@@ -193,11 +193,17 @@ class LamNI(TomoQueueMixin, LamNIAlignmentMixin, LamNIOpticsMixin, LamniGuiTools
def _describe_tomo_job_line(self, job: dict) -> str:
"""lamni's tomo_queue_show() one-line summary: circfov instead of
fov, no range= (lamni is 360-only)."""
fov, no range= (lamni is 360-only).
Uses .get(): a job persisted before some key was added to
_TOMO_SCAN_PARAM_NAMES won't have it in its snapshotted params, and
tomo_queue_show() must stay usable rather than crashing on the
missing key.
"""
p = job["params"]
return (
f"type={p['tomo_type']} circfov={p['tomo_circfov']}um "
f"step={p['tomo_shellstep']}um ctime={p['tomo_countingtime']}s"
f"type={p.get('tomo_type')} circfov={p.get('tomo_circfov')}um "
f"step={p.get('tomo_shellstep')}um ctime={p.get('tomo_countingtime')}s"
)
def __init__(self, client):
@@ -3761,12 +3761,20 @@ class Flomni(
}
def _describe_tomo_job_line(self, job: dict) -> str:
"""flomni's tomo_queue_show() one-line summary: fov/type/step/ctime/range."""
"""flomni's tomo_queue_show() one-line summary: fov/type/step/ctime/range.
Uses .get() throughout: a job persisted before some key was added to
_TOMO_SCAN_PARAM_NAMES won't have it in its snapshotted params, and
tomo_queue_show() must stay usable (e.g. to delete/inspect such a
job) rather than crashing on the missing key.
"""
p = job["params"]
fovx, fovy = p.get("fovx"), p.get("fovy")
fov_str = f"{fovx}/{fovy}um" if fovx is not None and fovy is not None else "?"
return (
f"type={p['tomo_type']} fov={p['fovx']}/{p['fovy']}um "
f"step={p['tomo_shellstep']}um ctime={p['tomo_countingtime']}s "
f"range={p['tomo_angle_range']}deg"
f"type={p.get('tomo_type')} fov={fov_str} "
f"step={p.get('tomo_shellstep')}um ctime={p.get('tomo_countingtime')}s "
f"range={p.get('tomo_angle_range')}deg"
)
def rt_off(self):
+28
View File
@@ -157,3 +157,31 @@ def test_legacy_queue_migration(flomni_sim):
ids = [j.get("id") for j in jobs]
assert all(ids), f"every job should have been healed with an id, got {ids}"
assert len(set(ids)) == len(ids), f"healed ids should be unique, got {ids}"
def test_queue_show_survives_missing_param_key(flomni_sim):
"""A job snapshotted before some key (e.g. fovx) existed in
_TOMO_SCAN_PARAM_NAMES won't carry it in its persisted ``params`` dict.
tomo_queue_show() must still print a summary line for that job instead
of raising KeyError -- otherwise a single stale queue entry makes the
whole queue un-inspectable (and un-deletable via the index tomo_queue_show()
would have printed).
"""
flomni = flomni_sim
bec = flomni.client
params = _short_params(flomni)
del params["fovx"]
del params["fovy"]
legacy_job = {
"kind": "tomo",
"id": "legacy-missing-fov",
"label": "legacy_no_fov",
"params": params,
"status": "pending",
"added_at": datetime.datetime.now().isoformat(),
}
bec.set_global_var("tomo_queue", [legacy_job])
jobs = flomni.tomo_queue_show()
assert jobs[0]["label"] == "legacy_no_fov"
@@ -113,6 +113,27 @@ def test_tomo_queue_show_uses_lamni_specific_job_line(capsys):
assert "range=" not in out # lamni is 360-only, no angle-range field
def test_tomo_queue_show_survives_missing_param_key(capsys):
"""A job snapshotted before some key (e.g. tomo_circfov) existed in
_TOMO_SCAN_PARAM_NAMES won't carry it in its persisted params dict --
tomo_queue_show() must still print a line for it instead of raising
KeyError, or a single stale queue entry makes the whole queue
un-inspectable.
"""
lamni = make_lamni()
lamni.tomo_circfov = 15.0
lamni.tomo_queue_add(label="job1")
jobs = lamni._tomo_queue_proxy.as_list()
del jobs[0]["params"]["tomo_circfov"]
lamni.client.set_global_var("tomo_queue", jobs)
result = lamni.tomo_queue_show()
assert result[0]["label"] == "job1"
out = capsys.readouterr().out
assert "circfov=None" in out
def test_tomo_queue_execute_runs_fresh_job_then_marks_done():
lamni = make_lamni()
calls = []