laundry: apply cleanup review to the cloud-cycle branch
Four parallel reviews (reuse, simplification, efficiency, altitude). The two that change behavior: - observe() could report "changed" on every poll forever, rewriting the config entry each time. If both tokens name the same slot with different payloads -- a downloaded program with its settings tweaked for one run is exactly that shape -- each pass wrote the default's blob then the one-shot's over it, so neither was ever already stored. On the SD-card installs this integration runs on, sustained entry rewrites are the one cost here that bites. The end state is stable, so "changed" is now start-vs-end, not per-assignment. - The write path copied every tracked href to read one rep, walking past the accessor added to avoid exactly that. New entity_rep() does the merge for a single href; cycle_write drops the resources parameter it never used. Structure: - device_resources() is a second accessor giving the pure device view, used by diagnostics and the debug read service. That deletes strip_synthetic, the _SYNTHETIC_KEY_PREFIX convention and the redact filter added last commit: "a dump is what the device said" is now which method you call rather than something every future exporter has to remember. - apply_cloud_courses() is the single mutation path. The flow was reaching past the coordinator into the store and relying on a later call to persist and invalidate for it; nine names are also now one entry write, not nine. - option_value/hex_pairs move to capabilities/common.py. The duplicate's stated reason -- that the coordinator shouldn't import from registry.capabilities -- was simply false; it already does, and so does learned.py. The real constraint is narrower: laundry.py imports cloudcourse, so the reverse would be a cycle. Dropped rather than kept: - The cloud-vs-translated-local-course name check, and catalog. translated_state_labels with it. The catalog this process can read is English while the dropdown is localized in the frontend, so it rejected "Cotton" for a German user seeing "Baumwolle" and missed the real collision when they typed "Baumwolle" -- wrong in both directions outside one locale, against an outcome option ordering already makes deterministic. The checks that survive compare strings that are the same in every locale: the user's own names, and the device's personal-course labels. - stored(), clear()/forget_cloud_courses(), blob(), download_course() -- no production callers. stored() was a template artifact whose docstring described a caller that cannot exist here. Diagnostics gains a cloud_courses block, which the store was missing next to learned_modes -- payloads and which slots are named, but not the names themselves, since those are the user's words and dumps get pasted publicly. Kept against one reviewer's advice: option_tokens (two others called generalizing option_write the right direction) and select._display's uncatalogued branch, which names a condition the old fallback-is-None proxy only got right by accident. Deferred: making the store per-subdevice. It is MAIN-only today and no device seen advertises cloud programs elsewhere; the limitation is now documented where it is made.
This commit is contained in:
1 parent
b921bdbb28
commit
2265c52c77
12 files changed
+220
-247
No files matched your search
@@ -90,8 +90,8 @@ class TestRealDumps:
|
||||
|
||||
store = cloudcourse.CloudCourses()
|
||||
assert store.observe(rep) is True
|
||||
assert store.blob("55") == SPORTS
|
||||
assert store.blob("6B") == JEANS
|
||||
assert store.snapshot()["slots"]["55"]["blob"] == SPORTS
|
||||
assert store.snapshot()["slots"]["6B"]["blob"] == JEANS
|
||||
# Learned but unnamed -- nothing is offerable yet.
|
||||
assert store.named() == {}
|
||||
assert store.view() == {}
|
||||
@@ -102,7 +102,7 @@ class TestRealDumps:
|
||||
store.observe(rep)
|
||||
assert store.download_candidates() == ["87"]
|
||||
# A candidate is never used until confirmed.
|
||||
assert store.download_course() is None
|
||||
assert store.snapshot()["download_course"] is None
|
||||
|
||||
def test_wa55_learns_its_saved_program_but_not_the_sentinel(self):
|
||||
rep = _load_device("washer_wa55a7700av")["/course/vs/0"]
|
||||
@@ -110,8 +110,8 @@ class TestRealDumps:
|
||||
|
||||
store = cloudcourse.CloudCourses()
|
||||
store.observe(rep)
|
||||
assert store.blob("59") == "001C590549164D114A224C2037F0AC22"
|
||||
assert store.blob("01") is None # the FFFF sentinel's byte 2
|
||||
assert store.snapshot()["slots"]["59"]["blob"] == "001C590549164D114A224C2037F0AC22"
|
||||
assert "01" not in store.snapshot()["slots"] # the FFFF sentinel's byte 2
|
||||
|
||||
def test_wa55_proposes_no_download_course(self):
|
||||
"""It is sitting on an ordinary local course with no override
|
||||
@@ -160,7 +160,7 @@ class TestRealDumps:
|
||||
for blob in (b06c, b048):
|
||||
store = cloudcourse.CloudCourses()
|
||||
store.observe(_rep(["CloudExtraCourse_0A", f"CloudCourse_{blob}"]))
|
||||
assert store.blob("0A") == blob
|
||||
assert store.snapshot()["slots"]["0A"]["blob"] == blob
|
||||
|
||||
def test_a_sentinel_slot_byte_is_not_the_current_course(self):
|
||||
"""The two sentinels in the corpus disagree about this -- WA55's byte
|
||||
@@ -192,14 +192,14 @@ class TestStoreRules:
|
||||
offers."""
|
||||
store = cloudcourse.CloudCourses()
|
||||
store.observe(_rep(["CloudExtraCourse_55", f"OneTimeCloudCourse_{JEANS}"]))
|
||||
assert store.blob("6B") is None
|
||||
assert "6B" not in store.snapshot()["slots"]
|
||||
|
||||
def test_a_relearned_blob_replaces_the_old_payload(self):
|
||||
store = cloudcourse.CloudCourses()
|
||||
store.observe(_rep(["CloudExtraCourse_55", f"CloudCourse_{SPORTS}"]))
|
||||
rewritten = SPORTS.replace("F005F0AC00", "F005F0AC11")
|
||||
assert store.observe(_rep(["CloudExtraCourse_55", f"CloudCourse_{rewritten}"])) is True
|
||||
assert store.blob("55") == rewritten
|
||||
assert store.snapshot()["slots"]["55"]["blob"] == rewritten
|
||||
|
||||
def test_observing_the_same_rep_twice_changes_nothing(self):
|
||||
store = cloudcourse.CloudCourses()
|
||||
|
||||
Reference in new issue
Block a user