]
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): ...
""")
return v;
}
+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,
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);
}