-
-
Notifications
You must be signed in to change notification settings - Fork 121
Remove subprocess usage in test_examples.py for Pyodide support #1029
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR drops the checking of the return code. Copilot suggests that the following would capture the output and check like the original did:
exit_code = 0
try:
with contextlib.redirect_stdout(stdout_buffer), contextlib.redirect_stderr(stderr_buffer):
exec(_MOCK_OCP_VSCODE_CONTENTS + example_source, {})
except SystemExit as e:
exit_code = e.code if isinstance(e.code, int) else 1
finally:
os.chdir(oldwd)
sys.modules.pop("ocp_vscode", None)
self.assertEqual(
0, exit_code, f"stdout/stderr: {stdout_buffer.getvalue()} / {stderr_buffer.getvalue()}"
)
What do you think, is it worth doing the checking?
I ran a quick test to check how pytest handles sys.exit() and stdout/stderr during test execution. If I add the following to the end of e.g. import sys
print("This is some error message that is useful for debugging")
sys.exit(1) And now I run all example tests with
As you can see, it includes the stdout and the exit code of the failed test. Hence, it seems that Copilot's suggestion adds unnecessary "complexity" that is already handled by pytest. |
FWIW the use of |
@fischman if that seems valuable to you, I am ok with it -- can add a platform specific branch like: if sys.platform == 'emscripten':
# pyodide specific
else:
# existing behavior with subprocess What do you think? |
Thanks for the review @fischman. I believe that the ==================== Yes, you can pass an empty dictionary ( ✅ What Happens When You Pass
|
Thanks for looking into it, @yeicor. I think the overview generated by chatgpt is incomplete. For example imported modules are singletons in Python, and importing a module inside the exec context gets you a (mutable!) handle on the same module object outside the exec context, enabling leakage. I sympathize with wanting to avoid pyodide-specific code in b123d. |
Ok, I get it, things like this could have unintended effects:
I'm ok with any of the suggested solutions so far. I'll let the maintainers decide and update this pull request if required. |
As discussed on Discord, the
subprocess
module is not supported in browser environments likePyodide
. To address this, I replaced thesubprocess
calls intest_examples.py
withexec
-based evaluation.While
exec
does not provide the same isolation as spawning a newPython
process, it's acceptable here because we control the example scripts being tested.I already verified that the current examples run as expected in both
Pyodide
and standardPython
.