mirror of
https://github.com/python/cpython.git
synced 2025-11-01 06:01:29 +00:00
gh-76785: Show the Traceback for Uncaught Subinterpreter Exceptions (gh-113034)
When an exception is uncaught in Interpreter.exec_sync(), it helps to show that exception's error display if uncaught in the calling interpreter. We do so here by generating a TracebackException in the subinterpreter and passing it between interpreters using pickle.
This commit is contained in:
parent
7316dfb0eb
commit
8a4c1f3ff1
5 changed files with 351 additions and 16 deletions
|
|
@ -1,9 +1,16 @@
|
|||
import contextlib
|
||||
import os
|
||||
import os.path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import threading
|
||||
from textwrap import dedent
|
||||
import unittest
|
||||
|
||||
from test import support
|
||||
from test.support import os_helper
|
||||
|
||||
from test.support import interpreters
|
||||
|
||||
|
||||
|
|
@ -71,5 +78,70 @@ def ensure_closed(fd):
|
|||
self.addCleanup(lambda: ensure_closed(w))
|
||||
return r, w
|
||||
|
||||
def temp_dir(self):
|
||||
tempdir = tempfile.mkdtemp()
|
||||
tempdir = os.path.realpath(tempdir)
|
||||
self.addCleanup(lambda: os_helper.rmtree(tempdir))
|
||||
return tempdir
|
||||
|
||||
def make_script(self, filename, dirname=None, text=None):
|
||||
if text:
|
||||
text = dedent(text)
|
||||
if dirname is None:
|
||||
dirname = self.temp_dir()
|
||||
filename = os.path.join(dirname, filename)
|
||||
|
||||
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
||||
with open(filename, 'w', encoding='utf-8') as outfile:
|
||||
outfile.write(text or '')
|
||||
return filename
|
||||
|
||||
def make_module(self, name, pathentry=None, text=None):
|
||||
if text:
|
||||
text = dedent(text)
|
||||
if pathentry is None:
|
||||
pathentry = self.temp_dir()
|
||||
else:
|
||||
os.makedirs(pathentry, exist_ok=True)
|
||||
*subnames, basename = name.split('.')
|
||||
|
||||
dirname = pathentry
|
||||
for subname in subnames:
|
||||
dirname = os.path.join(dirname, subname)
|
||||
if os.path.isdir(dirname):
|
||||
pass
|
||||
elif os.path.exists(dirname):
|
||||
raise Exception(dirname)
|
||||
else:
|
||||
os.mkdir(dirname)
|
||||
initfile = os.path.join(dirname, '__init__.py')
|
||||
if not os.path.exists(initfile):
|
||||
with open(initfile, 'w'):
|
||||
pass
|
||||
filename = os.path.join(dirname, basename + '.py')
|
||||
|
||||
with open(filename, 'w', encoding='utf-8') as outfile:
|
||||
outfile.write(text or '')
|
||||
return filename
|
||||
|
||||
@support.requires_subprocess()
|
||||
def run_python(self, *argv):
|
||||
proc = subprocess.run(
|
||||
[sys.executable, *argv],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
return proc.returncode, proc.stdout, proc.stderr
|
||||
|
||||
def assert_python_ok(self, *argv):
|
||||
exitcode, stdout, stderr = self.run_python(*argv)
|
||||
self.assertNotEqual(exitcode, 1)
|
||||
return stdout, stderr
|
||||
|
||||
def assert_python_failure(self, *argv):
|
||||
exitcode, stdout, stderr = self.run_python(*argv)
|
||||
self.assertNotEqual(exitcode, 0)
|
||||
return stdout, stderr
|
||||
|
||||
def tearDown(self):
|
||||
clean_up_interpreters()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue