bpo-41602: raise SIGINT exit code on KeyboardInterrupt from pymain_run_module (#21956)
Closes bpo issue 41602
This commit is contained in:
parent
ea0711a9f9
commit
a68a2ad19c
|
@ -1,15 +1,18 @@
|
||||||
# Test the runpy module
|
# Test the runpy module
|
||||||
import unittest
|
import contextlib
|
||||||
import os
|
import importlib.machinery, importlib.util
|
||||||
import os.path
|
import os.path
|
||||||
import sys
|
|
||||||
import re
|
|
||||||
import tempfile
|
|
||||||
import importlib, importlib.machinery, importlib.util
|
|
||||||
import py_compile
|
|
||||||
import warnings
|
|
||||||
import pathlib
|
import pathlib
|
||||||
from test.support import verbose, no_tracing
|
import py_compile
|
||||||
|
import re
|
||||||
|
import signal
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import textwrap
|
||||||
|
import unittest
|
||||||
|
import warnings
|
||||||
|
from test.support import no_tracing, verbose
|
||||||
from test.support.import_helper import forget, make_legacy_pyc, unload
|
from test.support.import_helper import forget, make_legacy_pyc, unload
|
||||||
from test.support.os_helper import create_empty_file, temp_dir
|
from test.support.os_helper import create_empty_file, temp_dir
|
||||||
from test.support.script_helper import make_script, make_zip_script
|
from test.support.script_helper import make_script, make_zip_script
|
||||||
|
@ -752,5 +755,82 @@ s = "non-ASCII: h\xe9"
|
||||||
self.assertEqual(result['s'], "non-ASCII: h\xe9")
|
self.assertEqual(result['s'], "non-ASCII: h\xe9")
|
||||||
|
|
||||||
|
|
||||||
|
class TestExit(unittest.TestCase):
|
||||||
|
STATUS_CONTROL_C_EXIT = 0xC000013A
|
||||||
|
EXPECTED_CODE = (
|
||||||
|
STATUS_CONTROL_C_EXIT
|
||||||
|
if sys.platform == "win32"
|
||||||
|
else -signal.SIGINT
|
||||||
|
)
|
||||||
|
@staticmethod
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def tmp_path(*args, **kwargs):
|
||||||
|
with temp_dir() as tmp_fn:
|
||||||
|
yield pathlib.Path(tmp_fn)
|
||||||
|
|
||||||
|
|
||||||
|
def run(self, *args, **kwargs):
|
||||||
|
with self.tmp_path() as tmp:
|
||||||
|
self.ham = ham = tmp / "ham.py"
|
||||||
|
ham.write_text(
|
||||||
|
textwrap.dedent(
|
||||||
|
"""\
|
||||||
|
raise KeyboardInterrupt
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
super().run(*args, **kwargs)
|
||||||
|
|
||||||
|
def assertSigInt(self, *args, **kwargs):
|
||||||
|
proc = subprocess.run(*args, **kwargs, text=True, stderr=subprocess.PIPE)
|
||||||
|
self.assertTrue(proc.stderr.endswith("\nKeyboardInterrupt\n"))
|
||||||
|
self.assertEqual(proc.returncode, self.EXPECTED_CODE)
|
||||||
|
|
||||||
|
def test_pymain_run_file(self):
|
||||||
|
self.assertSigInt([sys.executable, self.ham])
|
||||||
|
|
||||||
|
def test_pymain_run_file_runpy_run_module(self):
|
||||||
|
tmp = self.ham.parent
|
||||||
|
run_module = tmp / "run_module.py"
|
||||||
|
run_module.write_text(
|
||||||
|
textwrap.dedent(
|
||||||
|
"""\
|
||||||
|
import runpy
|
||||||
|
runpy.run_module("ham")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertSigInt([sys.executable, run_module], cwd=tmp)
|
||||||
|
|
||||||
|
def test_pymain_run_file_runpy_run_module_as_main(self):
|
||||||
|
tmp = self.ham.parent
|
||||||
|
run_module_as_main = tmp / "run_module_as_main.py"
|
||||||
|
run_module_as_main.write_text(
|
||||||
|
textwrap.dedent(
|
||||||
|
"""\
|
||||||
|
import runpy
|
||||||
|
runpy._run_module_as_main("ham")
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
self.assertSigInt([sys.executable, run_module_as_main], cwd=tmp)
|
||||||
|
|
||||||
|
def test_pymain_run_command_run_module(self):
|
||||||
|
self.assertSigInt(
|
||||||
|
[sys.executable, "-c", "import runpy; runpy.run_module('ham')"],
|
||||||
|
cwd=self.ham.parent,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_pymain_run_command(self):
|
||||||
|
self.assertSigInt([sys.executable, "-c", "import ham"], cwd=self.ham.parent)
|
||||||
|
|
||||||
|
def test_pymain_run_stdin(self):
|
||||||
|
self.assertSigInt([sys.executable], input="import ham", cwd=self.ham.parent)
|
||||||
|
|
||||||
|
def test_pymain_run_module(self):
|
||||||
|
ham = self.ham
|
||||||
|
self.assertSigInt([sys.executable, "-m", ham.stem], cwd=ham.parent)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Add tests for SIGINT handling in the runpy module.
|
|
@ -287,7 +287,11 @@ pymain_run_module(const wchar_t *modname, int set_argv0)
|
||||||
Py_DECREF(module);
|
Py_DECREF(module);
|
||||||
return pymain_exit_err_print();
|
return pymain_exit_err_print();
|
||||||
}
|
}
|
||||||
|
_Py_UnhandledKeyboardInterrupt = 0;
|
||||||
result = PyObject_Call(runmodule, runargs, NULL);
|
result = PyObject_Call(runmodule, runargs, NULL);
|
||||||
|
if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
|
||||||
|
_Py_UnhandledKeyboardInterrupt = 1;
|
||||||
|
}
|
||||||
Py_DECREF(runpy);
|
Py_DECREF(runpy);
|
||||||
Py_DECREF(runmodule);
|
Py_DECREF(runmodule);
|
||||||
Py_DECREF(module);
|
Py_DECREF(module);
|
||||||
|
|
Loading…
Reference in New Issue