mirror of
https://github.com/python/cpython.git
synced 2025-11-24 12:20:42 +00:00
[3.14] gh-137576: Fix for Basic REPL showing incorrect code in tracebacks with PYTHONSTARTUP (GH-137625) (#137771)
Co-authored-by: adam j hartz <hz@mit.edu> Co-authored-by: Kirill Podoprigora <kirill.bast9@mail.ru>
This commit is contained in:
parent
5caa6cde58
commit
6d30edbae2
4 changed files with 90 additions and 3 deletions
|
|
@ -188,6 +188,68 @@ class TestInteractiveInterpreter(unittest.TestCase):
|
|||
]
|
||||
self.assertEqual(traceback_lines, expected_lines)
|
||||
|
||||
def test_pythonstartup_error_reporting(self):
|
||||
# errors based on https://github.com/python/cpython/issues/137576
|
||||
|
||||
def make_repl(env):
|
||||
return subprocess.Popen(
|
||||
[os.path.join(os.path.dirname(sys.executable), '<stdin>'), "-i"],
|
||||
executable=sys.executable,
|
||||
text=True,
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
env=env,
|
||||
)
|
||||
|
||||
# case 1: error in user input, but PYTHONSTARTUP is fine
|
||||
with os_helper.temp_dir() as tmpdir:
|
||||
script = os.path.join(tmpdir, "pythonstartup.py")
|
||||
with open(script, "w") as f:
|
||||
f.write("print('from pythonstartup')" + os.linesep)
|
||||
|
||||
env = os.environ.copy()
|
||||
env['PYTHONSTARTUP'] = script
|
||||
env["PYTHON_HISTORY"] = os.path.join(tmpdir, ".pythonhist")
|
||||
p = make_repl(env)
|
||||
p.stdin.write("1/0")
|
||||
output = kill_python(p)
|
||||
expected = dedent("""
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
1/0
|
||||
~^~
|
||||
ZeroDivisionError: division by zero
|
||||
""")
|
||||
self.assertIn("from pythonstartup", output)
|
||||
self.assertIn(expected, output)
|
||||
|
||||
# case 2: error in PYTHONSTARTUP triggered by user input
|
||||
with os_helper.temp_dir() as tmpdir:
|
||||
script = os.path.join(tmpdir, "pythonstartup.py")
|
||||
with open(script, "w") as f:
|
||||
f.write("def foo():\n 1/0\n")
|
||||
|
||||
env = os.environ.copy()
|
||||
env['PYTHONSTARTUP'] = script
|
||||
env["PYTHON_HISTORY"] = os.path.join(tmpdir, ".pythonhist")
|
||||
p = make_repl(env)
|
||||
p.stdin.write('foo()')
|
||||
output = kill_python(p)
|
||||
expected = dedent("""
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
foo()
|
||||
~~~^^
|
||||
File "%s", line 2, in foo
|
||||
1/0
|
||||
~^~
|
||||
ZeroDivisionError: division by zero
|
||||
""") % script
|
||||
self.assertIn(expected, output)
|
||||
|
||||
|
||||
|
||||
def test_runsource_show_syntax_error_location(self):
|
||||
user_input = dedent("""def f(x, x): ...
|
||||
""")
|
||||
|
|
|
|||
|
|
@ -534,7 +534,7 @@ class StackSummary(list):
|
|||
colorize = kwargs.get("colorize", False)
|
||||
row = []
|
||||
filename = frame_summary.filename
|
||||
if frame_summary.filename.startswith("<stdin>-"):
|
||||
if frame_summary.filename.startswith("<stdin-") and frame_summary.filename.endswith('>'):
|
||||
filename = "<stdin>"
|
||||
if colorize:
|
||||
theme = _colorize.get_theme(force_color=True).traceback
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Fix for incorrect source code being shown in tracebacks from the Basic REPL
|
||||
when :envvar:`PYTHONSTARTUP` is given. Patch by Adam Hartz.
|
||||
|
|
@ -1365,6 +1365,29 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py
|
|||
return PyEval_EvalCode((PyObject*)co, globals, locals);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
get_interactive_filename(PyObject *filename, Py_ssize_t count)
|
||||
{
|
||||
PyObject *result;
|
||||
Py_ssize_t len = PyUnicode_GET_LENGTH(filename);
|
||||
|
||||
if (len >= 2
|
||||
&& PyUnicode_ReadChar(filename, 0) == '<'
|
||||
&& PyUnicode_ReadChar(filename, len - 1) == '>') {
|
||||
PyObject *middle = PyUnicode_Substring(filename, 1, len-1);
|
||||
if (middle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
result = PyUnicode_FromFormat("<%U-%d>", middle, count);
|
||||
Py_DECREF(middle);
|
||||
} else {
|
||||
result = PyUnicode_FromFormat(
|
||||
"%U-%d", filename, count);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
|
||||
PyCompilerFlags *flags, PyArena *arena, PyObject* interactive_src,
|
||||
|
|
@ -1375,8 +1398,8 @@ run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
|
|||
if (interactive_src) {
|
||||
PyInterpreterState *interp = tstate->interp;
|
||||
if (generate_new_source) {
|
||||
interactive_filename = PyUnicode_FromFormat(
|
||||
"%U-%d", filename, interp->_interactive_src_count++);
|
||||
interactive_filename = get_interactive_filename(
|
||||
filename, interp->_interactive_src_count++);
|
||||
} else {
|
||||
Py_INCREF(interactive_filename);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue