8000 gh-110805: Allow the repl to show source code and complete tracebacks by pablogsal · Pull Request #110775 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

gh-110805: Allow the repl to show source code and complete tracebacks #110775

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

Merged
merged 7 commits into from
Oct 13, 2023
Prev Previous commit
Next Next commit
fixup! fixup! fixup! fixup! Allow the repl to show source code and co…
…mplete tracebacks
  • Loading branch information
pablogsal committed Oct 13, 2023
commit 64e1c41a37f0f6a54b1fd66f28d744001e557291
2 changes: 1 addition & 1 deletion Lib/test/test_repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ def bar(x):
p.stdin.write(user_input2)
output = kill_python(p)
self.assertEqual(p.returncode, 0)
expected = "(30, None, [\'def foo(x):\\n\', \' return x + 1\\n\', \'\\n\'], \'<python-input-1>\')"
expected = "(30, None, [\'def foo(x):\\n\', \' return x + 1\\n\', \'\\n\'], \'<stdin>\')"
self.assertIn(expected, output, expected)


Expand Down
3 changes: 1 addition & 2 deletions Lib/traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,7 @@ def line(self):
if self._line is None:
if self.lineno is None:
return None
if self._line is None:
self._line = linecache.getline(self.filename, self.lineno)
self._line = linecache.getline(self.filename, self.lineno)
return self._line.strip()


Expand Down
31 changes: 24 additions & 7 deletions Python/pythonrun.c
Original file line number Diff line number Diff line change
Expand Up @@ -1267,33 +1267,50 @@ run_mod(mod_ty mod, PyObject *filename, PyObject *globals, PyObject *locals,
PyCompilerFlags *flags, PyArena *arena, PyObject* interactive_src)
{
PyThreadState *tstate = _PyThreadState_GET();
PyObject* interactive_filename = NULL;
PyObject* interactive_filename = filename;
if (interactive_src) {
PyInterpreterState *interp = tstate->interp;
interactive_filename = PyUnicode_FromFormat("<python-input-%d>", interp->_interactive_src_count++);
// TODO: Maybe we are leaking
filename = interactive_filename;
interactive_filename = PyUnicode_FromFormat(
"<python-input-%d>", interp->_interactive_src_count++
);
if (interactive_filename == NULL) {
return NULL;
}
}

PyCodeObject *co = _PyAST_Compile(mod, filename, flags, -1, arena);
if (co == NULL)
PyCodeObject *co = _PyAST_Compile(mod, interactive_filename, flags, -1, arena);
if (co == NULL) {
Py_DECREF(interactive_filename);
return NULL;
}

if (interactive_src) {
PyObject *linecache_module = PyImport_ImportModule("linecache");

if (linecache_module == NULL) {
Py_DECREF(co);
Py_DECREF(interactive_filename);
return NULL;
}

PyObject *print_tb_func = PyObject_GetAttrString(linecache_module, "_register_code");

if (print_tb_func == NULL || !PyCallable_Check(print_tb_func)) {
Py_DECREF(co);
Py_DECREF(interactive_filename);
Py_DECREF(linecache_module);
return NULL;
}

PyObject* result = PyObject_CallFunction(print_tb_func, "OOO", interactive_filename, interactive_src, filename);
PyObject* result = PyObject_CallFunction(
print_tb_func, "OOO",
interactive_filename,
interactive_src,
filename
);

Py_DECREF(interactive_filename);

if (!result) {
Py_DECREF(linecache_module);
Py_XDECREF(print_tb_func);
Expand Down
0