Repository navigation
Run -c code as the __main__ module - #2080
Conversation
run_code() evaluated the code with an empty globals dict, so __name__ resolved to the builtins module name and "if __name__ == '__main__'" blocks never ran. Classes defined in the code also could not be pickled. Run the code in a temporary __main__ module, the same way run_path() does for a file target.
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
|
🔒 Automated review in progress — Rich Chiodo (@rchiodo) is auto-reviewing this PR. |
|
Result: Verification detailsVerification: The relevant tests could not be fully run in the isolated environment; this review is not fully verified. Summary: On CPython 3.13.16, targeted code-launch, argument, shell-expansion, and breakpoint tests produced 13 passes and 2 expected skips. A real debugpy CLI reproduction also passed, matching native `python -c` for the main guard and class/function pickle round trips. The full CLI test file timed out after 180 seconds without returning results, so the PR's new regression test could not be confirmed. Verification is partial; no assertion failures were observed. Test runs: 4 passed, 1 not run
|
Rich Chiodo (rchiodo)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
Heejae Chang (heejaechang)
left a comment
There was a problem hiding this comment.
Approved via Review Center.
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Fixes #2079.
run_code()insrc/debugpy/server/cli.pyran the code witheval(code, {}). That globals dict has no__name__, so the name resolves through builtins as"builtins"and anif __name__ == "__main__":block never runs. Classes the code defines get__module__ == "builtins", so pickle can't find them either. A"code"launch goes through the same function, because the adapter turns it into-cfor the debugpy CLI in the debuggee.The code now runs in the namespace of a
runpy._TempModule("__main__"), the helperrun_path()already uses for a file target. While the code runs,__name__is"__main__"andsys.modules["__main__"]is the module it runs in. The original__main__is put back afterwards, the same as for a file target.The new test
test_run_code_runs_as_mainintests/debugpy/server/test_cli.pycallsrun_code()in process withstart_debuggingstubbed out. It checks__name__, thatsys.modules["__main__"]is the module the code runs in, that a class the code defines round trips throughpickle, and that the original__main__is restored. Without the change tocli.pyit fails withPicklingError: Can't pickle <class 'Point'>: attribute lookup Point on builtins failed.Testing on macOS 26.6.2 with CPython 3.10.6, one worker:
tests/debugpy/server/test_cli.py: 96 passed.codetarget cases oftest_run,test_nodebug,test_args,test_shell_expansionandtest_break_apithat go through the CLI: 14 passed, 1 skipped (shell expansion is not supported forinternalConsole).python -con 3.10.6 and 3.14.3, and a"code"launch prints__name__ is __main__andmain block ran.ruff checkpasses on both files.