mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-09-11 04:00:38 +00:00
fix(code-runtime-python): stop the program's compile from inheriting the module's future annotations
bootstrap.py imports from __future__ import annotations; compile(wrapped) was inheriting that PEP 563 flag, stringifying the program's type annotations and changing the semantics of a legal program that reads f.__annotations__ at runtime. compile(..., dont_inherit=True) stops the leak; a regression test defines an annotated function and asserts the annotation is the live int class, verified fail-before by removing dont_inherit (the test turns red).
This commit is contained in:
@@ -1300,7 +1300,11 @@ async def _run(channel: ProtocolChannel) -> None:
|
||||
ast.copy_location(wrapper, anchor)
|
||||
wrapped = ast.Module(body=[wrapper], type_ignores=[])
|
||||
ast.fix_missing_locations(wrapped)
|
||||
code = compile(wrapped, "<model>", "exec")
|
||||
# `dont_inherit=True` stops this module's `from __future__ import
|
||||
# annotations` (line 14) from leaking into the program's compile: PEP 563
|
||||
# would otherwise stringify the program's type annotations, changing the
|
||||
# semantics of a legal program that reads `f.__annotations__` at runtime.
|
||||
code = compile(wrapped, "<model>", "exec", dont_inherit=True)
|
||||
exec(code, ns) # noqa: S102 -- defines __dsh_main__; executing model code is the point
|
||||
value = await ns["__dsh_main__"]()
|
||||
die_if_cpu_exhausted(cpu_seconds)
|
||||
|
||||
@@ -2689,6 +2689,24 @@ describe('PythonCodeRuntime — budgets, termination, disposal', () => {
|
||||
expect(result.value).toBe("read: ''")
|
||||
}, 15_000)
|
||||
|
||||
it('keeps runtime type annotations unevaluated-as-strings when the program reads them', async () => {
|
||||
// bootstrap.py imports `from __future__ import annotations`; without
|
||||
// dont_inherit=True on compile(), that PEP 563 flag leaks into the program's
|
||||
// compiled code and stringifies its type annotations, changing the semantics
|
||||
// of a legal program that reads `f.__annotations__` at runtime.
|
||||
const { runtime } = await setup()
|
||||
const result = await runtime.run({
|
||||
program: [
|
||||
'def f(x: int) -> int:',
|
||||
' return x',
|
||||
'return f.__annotations__["x"].__name__',
|
||||
].join('\n'),
|
||||
bindings: [],
|
||||
})
|
||||
expect(result.error).toBeUndefined()
|
||||
expect(result.value).toBe('int')
|
||||
}, 15_000)
|
||||
|
||||
it('reaps a same-group child that ignores SIGTERM and releases the pipes before close', async () => {
|
||||
// The same-group counterpart to the setsid-orphan case above. A descendant
|
||||
// left in the child's OWN process group (no setsid, so `kill(-pid)` reaches
|
||||
|
||||
Reference in New Issue
Block a user