8a55137e57
Interface cleanup so the report_* family matches the typo-safe ethos of eq.names instead of leaking raw protobuf errors on a misspelled value. - Milestone / ModuleState / JobState: importable str-enums (member == its wire name, so plain strings still work) — autocomplete + a typo-checked happy path. The clean rule: equipment-specific *names* live on eq.names; fixed protocol *value-sets* are enums. - _enum_value(): resolves an enum-or-string arg client-side and, on a bad value, raises ValueError with a close-match hint *before* the wire. Wired into report_job / report_substrate / report_module / request_control_state (all previously raised a raw protobuf ValueError). - Equipment is now a context manager (with Equipment(...) as eq: ...). - examples/wafer_tool.py: a cluster tool tracking one wafer through one module end-to-end (E90 + E157), showing the enums + context manager. - tests/test_enums.py: asserts the enums stay in lockstep with the proto and that the typo path is helpful. Wired into run_interop.sh (pyclient step). - Interop drives both the enum and string forms on the wire + the ValueError typo path. Docs (ch16/ch42) updated; names-vs-enums rule documented. All Python unit tests + 25 pyclient interop checks pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
#!/usr/bin/env python3
|
|
"""The exported protocol enums must stay in lockstep with the proto, and the
|
|
typo-safe resolver must reject bad values with a helpful message. Plain
|
|
asserts — run directly."""
|
|
import sys
|
|
|
|
from secsgem_client import JobState, Milestone, ModuleState
|
|
from secsgem_client._client import _enum_value
|
|
from secsgem_client._proto import equipment_pb2 as pb
|
|
|
|
|
|
def members(e):
|
|
return {m.value for m in e}
|
|
|
|
|
|
def main() -> int:
|
|
# Each enum mirrors its proto source exactly — no drift, no missing member.
|
|
assert members(Milestone) == set(pb.SubstrateReport.Milestone.keys())
|
|
assert members(ModuleState) == set(pb.ModuleReport.State.keys())
|
|
assert members(JobState) == set(pb.ProcessJobState.State.keys())
|
|
|
|
# A member IS its wire name, so enum and plain string are interchangeable.
|
|
assert Milestone.ARRIVED == "ARRIVED"
|
|
assert _enum_value(pb.SubstrateReport.Milestone, Milestone.ARRIVED, "milestone") \
|
|
== _enum_value(pb.SubstrateReport.Milestone, "ARRIVED", "milestone")
|
|
|
|
# A typo raises ValueError (client-side, not a daemon round-trip) and the
|
|
# message offers the close match instead of leaking a raw protobuf error.
|
|
try:
|
|
_enum_value(pb.SubstrateReport.Milestone, "AT_WROK", "milestone")
|
|
raise SystemExit("expected ValueError for a misspelled milestone")
|
|
except ValueError as e:
|
|
assert "AT_WORK" in str(e), str(e)
|
|
|
|
print("enums: proto-sync + typo-safety checks passed")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|