Skip to content

Report a non-UTF-8 Lean runtime reply as a protocol error and simplify request phases - #175

Draft
Deicyde wants to merge 4 commits into
mainfrom
golf/lean-client-request-phases
Draft

Deicyde wants to merge 4 commits into
mainfrom
golf/lean-client-request-phases

Conversation

@Deicyde

@Deicyde Deicyde commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

One fix and three cleanups in servers/lean_client.py (+27/-39), plus one test. The fix changes the exception type for a malformed reply. The cleanups keep every exception class and every message a caller could see.

Fix: non-UTF-8 replies. _read_line decoded the response line itself, outside every handler in _request_once. A reply with invalid UTF-8 therefore escaped as a raw UnicodeDecodeError instead of LeanRuntimeProtocolError, and the UnicodeDecodeError clause around json.loads could not run. _read_line now returns bytes, and the caller decodes them inside that clause. test_non_utf8_response_is_a_protocol_error fails on main with the UnicodeDecodeError and passes here.

Cleanups

  • Request phases. _request_once set a dispatched flag before sendall and branched on it in shared handlers. The connect call has its own handlers, so apart from settimeout, every OSError the shared handlers saw came after dispatch. A try around sendall and the read now maps those failures, and the outer handler covers settimeout. The no-retry rule after dispatch is unchanged, and test_connected_send_failure_is_never_retried still pins it: it fails if the post-dispatch handler raises LeanRuntimeUnavailable. The "timed out waiting for Lean runtime connection" message is gone because it could not occur: connect's own OSError handler turned socket.timeout into "cannot connect to Lean runtime: ...".
  • Errno fallback. The connect handler's errno in {2, 61, 111} check is gone. ENOENT and ECONNREFUSED already raise FileNotFoundError and ConnectionRefusedError, which the clause above catches. On Linux, 61 is ENODATA, which connect does not return.
  • Runtime sources. _build_id and _build_generation listed the same five files; they now share _RUNTIME_SOURCES. _build_id still hashes servers/__init__.py first, so its input order is unchanged.

No open PR edits lean_client.py. #168, #111 and #105 edit tests/test_shared_lean_runtime.py; each merges cleanly with this branch, and the merged file passes with #111 (which contains #168, 62 passed) and with #105 (39 passed).

Validation at exact head 301a1df6: ruff check autoform_cli servers tests is clean, and tests/test_shared_lean_runtime.py passes (38). In tests/test_plugin_runtime.py, 3 pass; the fourth, test_wheel_contains_only_the_minimal_runtime, fails the same way on main in this checkout, because uv build reads a parent directory's pyproject.toml. CI runs it.

_build_id and _build_generation spelled out the same five files;
_build_id also hashes servers/__init__.py.
_request_once set dispatched before sendall and branched on it in
shared handlers. The connect call has its own handlers, so apart from
settimeout every OSError those shared handlers saw came after dispatch.
A try around sendall and the response read now maps those failures, and
the outer handler covers settimeout. The "timed out waiting for Lean
runtime connection" message could not occur: connect's own OSError
handler turned socket.timeout into "cannot connect to Lean runtime".
ENOENT and ECONNREFUSED already raise FileNotFoundError and
ConnectionRefusedError, which the handler above catches. On Linux, 61
is ENODATA, which connect does not return.
_read_line decoded the response line outside every handler, so invalid
UTF-8 escaped _request_once as a raw UnicodeDecodeError instead of
LeanRuntimeProtocolError, and the UnicodeDecodeError clause around
json.loads could not run. _read_line now returns bytes, and the caller
decodes them inside that clause.
@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Oct 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant