mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-11 04:00:38 +00:00
fix(code-runtime-python): bind RuntimeError and _BindingRejection for dispatch's rejection path
dispatch's call_failure and its except clause resolved the module globals at call time, so a program rebinding __main__._BindingRejection = ValueError let the internal marker type leak into model code. Bind _RuntimeError_cls and _BindingRejection_cls into _run locals before the program runs (names distinct from the module globals so the assignment RHS resolves the global, not an unbound local); dispatch now uses the locals. A regression test rebinds _BindingRejection and asserts a host rejection still surfaces as RuntimeError. The sys.__stdout__ flush test now reconfigures the streams back to block buffering (write_through=False) so the settlement drain path is what the case pins — verified fail-before: binding the stream objects instead of their flush methods turns the test red.
This commit is contained in:
@@ -744,6 +744,15 @@ async def _run(channel: ProtocolChannel) -> None:
|
||||
# with no done frame, misreporting the run as a `worker-exit`. A frame local
|
||||
# is not reachable by `__main__._X = ...`, so the catch is immune.
|
||||
_BaseException = BaseException
|
||||
# `RuntimeError` and the `_BindingRejection` marker class are likewise bound
|
||||
# into locals: `dispatch`'s `call_failure` and its `except` clause resolve
|
||||
# them at call time, and the program (running as `__main__`) can rebind the
|
||||
# module globals — `__main__._BindingRejection = ValueError` would leak the
|
||||
# marker type into model code, violating the class's conversion contract.
|
||||
# The names differ from the module globals (`_RuntimeError_cls`) so the
|
||||
# assignment RHS resolves the module global, not an unbound local.
|
||||
_RuntimeError_cls = RuntimeError
|
||||
_BindingRejection_cls = _BindingRejection
|
||||
# 1. Boot handshake.
|
||||
boot = channel.read_frame()
|
||||
if boot is None or boot.get("type") != "boot":
|
||||
@@ -861,7 +870,7 @@ async def _run(channel: ProtocolChannel) -> None:
|
||||
# the pre-errorClass behavior for namespaces that declared none.
|
||||
if error_class is not None:
|
||||
return error_class(name, message)
|
||||
return RuntimeError(message)
|
||||
return _RuntimeError_cls(message)
|
||||
|
||||
# Validate the argument shape before claiming an id, so a rejected call
|
||||
# leaves no gap in the sequence the host checks. json.dumps would coerce
|
||||
@@ -907,7 +916,7 @@ async def _run(channel: ProtocolChannel) -> None:
|
||||
next_id += 1
|
||||
try:
|
||||
return await fut
|
||||
except _BindingRejection as exc:
|
||||
except _BindingRejection_cls as exc:
|
||||
raise call_failure(str(exc)) from None
|
||||
|
||||
namespaces: dict[str, Any] = {}
|
||||
|
||||
Reference in New Issue
Block a user