mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-11 04:00:38 +00:00
test(code-runtime-python): pin the pump reader against a class-attribute rebind; correct the staging comment
The review's three remaining items: - A regression test rebinds __main__.ProtocolChannel.read_frame_async and asserts a binding reply still round-trips (the pump's reader is a bound method captured by _run before the program runs). - The settlement note (en + zh) records that send_done's frame-shape check uses _run's bound _str/_isinstance. - The staging-removal comment no longer claims teardown retries tracked state: teardown deliberately does not sweep staging, so a removal failure is the one case the gone-by-settlement contract degrades on. Pairing re-recorded.
This commit is contained in:
@@ -1704,9 +1704,11 @@ export class PythonCodeRuntime extends CodeRuntime {
|
||||
// Swallows only a failure to remove this run's staging directory —
|
||||
// `force` already absorbs a missing one, so what remains is a
|
||||
// filesystem-level refusal. The run's own outcome is already decided
|
||||
// and must still be delivered, and teardown retries what stays
|
||||
// tracked; the directory holds no secret, only a copy of two
|
||||
// checked-in scripts.
|
||||
// and must still be delivered; the directory holds no secret, only a
|
||||
// copy of two checked-in scripts. teardown deliberately does not
|
||||
// sweep staging (its staging is cleared inside each run's settle), so
|
||||
// a removal failure here is the one case the "gone by settlement"
|
||||
// contract degrades on.
|
||||
}
|
||||
resolve({ ...result, logs })
|
||||
// Mark the fiber quiescent for THIS run: drop it from `live` and resolve
|
||||
|
||||
@@ -696,6 +696,31 @@ describe('PythonCodeRuntime — programs and bindings', () => {
|
||||
expect(result.value).toEqual({ echoed: { n: 1 } })
|
||||
}, 15_000)
|
||||
|
||||
it('keeps the reply pump reading when the read_frame_async class attribute is rebound', async () => {
|
||||
// _pump_replies' frame reader is a bound method captured by _run before the
|
||||
// program runs and passed in as an explicit argument, so a program rebinding
|
||||
// `__main__.ProtocolChannel.read_frame_async` cannot redirect the pump (a
|
||||
// body-local `channel.read_frame_async` lookup would resolve the rebound
|
||||
// class attribute, since the pump starts after the program's top-level
|
||||
// statements).
|
||||
const { runtime } = await setup()
|
||||
const result = await runtime.run({
|
||||
program: [
|
||||
'import __main__',
|
||||
'async def boom(*a, **k):',
|
||||
' raise RuntimeError("hijacked reader")',
|
||||
'__main__.ProtocolChannel.read_frame_async = boom',
|
||||
'first = await tools.echo({"n": 1})',
|
||||
'return first',
|
||||
].join('\n'),
|
||||
bindings: tools({
|
||||
echo: async args => ({ echoed: args as CodeJsonValue }),
|
||||
}),
|
||||
})
|
||||
expect(result.error).toBeUndefined()
|
||||
expect(result.value).toEqual({ echoed: { n: 1 } })
|
||||
}, 15_000)
|
||||
|
||||
it('keeps the rejection contract when _BindingRejection is rebound', async () => {
|
||||
// `dispatch`'s except clause resolves `_BindingRejection` at call time; a
|
||||
// program that rebinds `__main__._BindingRejection = ValueError` would
|
||||
|
||||
Reference in New Issue
Block a user