8000 Allow the repl to show source code and complete tracebacks · python/cpython@05f9437 · GitHub
[go: up one dir, main page]

Skip to content

Commit 05f9437

Browse files
committed
Allow the repl to show source code and complete tracebacks
1 parent e733136 commit 05f9437

File tree

7 files changed

+58
-8
lines changed

7 files changed

+58
-8
lines changed

Include/internal/pycore_interp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ struct _is {
233233

234234
/* the initial PyInterpreterState.threads.head */
235235
PyThreadState _initial_thread;
236+
Py_ssize_t _interactive_src_count;
236237
};
237238

238239

Include/internal/pycore_parser.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,17 @@ extern struct _mod* _PyParser_ASTFromFile(
5858
PyCompilerFlags *flags,
5959
int *errcode,
6060
PyArena *arena);
61-
61+
extern struct _mod* _PyParser_InteractiveASTFromFile(
62+
FILE *fp,
63+
PyObject *filename_ob,
64+
const char *enc,
65+
int mode,
66+
const char *ps1,
67+
const char *ps2,
68+
PyCompilerFlags *flags,
69+
int *errcode,
70+
PyObject **interactive_src,
71+
PyArena *arena);
6272

6373
#ifdef __cplusplus
6474
}

Lib/linecache.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import sys
1010
import os
1111
import tokenize
12+
import types
1213

1314
__all__ = ["getline", "clearcache", "checkcache", "lazycache"]
1415

@@ -42,6 +43,8 @@ def getlines(filename, module_globals=None):
4243
if len(entry) != 1:
4344
return cache[filename][2]
4445

46+
if isinstance(filename, types.CodeType):
47+
return []
4548
try:
4649
return updatecache(filename, module_globals)
4750
except MemoryError:
@@ -180,3 +183,10 @@ def lazycache(filename, module_globals):
180183
cache[filename] = (get_lines,)
181184
return True
182185
return False
186+
187+
def _register_code(code, string, name):
188+
cache[code] = (
189+
len(string),
190+
None,
191+
[line + '\n' for line in string.splitlines()],
192+
name)

Lib/traceback.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,8 @@ def line(self):
331331
if self._line is None:
332332
if self.lineno is None:
333333
return None
334-
self._line = linecache.getline(self.filename, self.lineno)
334+
if self._line is None:
335+
self._line = linecache.getline(self.filename, self.lineno)
335336
return self._line.strip()
336337

337338

@@ -434,7 +435,6 @@ def _extract_from_extended_frame_gen(klass, frame_gen, *, limit=None,
434435
co = f.f_code
435436
filename = co.co_filename
436437
name = co.co_name
437-
438438
fnames.add(filename)
439439
linecache.lazycache(filename, f.f_globals)
440440
# Must defer line lookups until we have called checkcache.
@@ -447,6 +447,7 @@ def _extract_from_extended_frame_gen(klass, frame_gen, *, limit=None,
447447
end_lineno=end_lineno, colno=colno, end_colno=end_colno))
448448
for filename in fnames:
449449
linecache.checkcache(filename)
450+
450451
# If immediate lookup was desired, trigger lookups now.
451452
if lookup_lines:
452453
for f in result:
@@ -479,8 +480,12 @@ def format_frame_summary(self, frame_summary):
479480
gets called for every frame to be printed in the stack summary.
480481
"""
481482
row = []
482-
row.append(' File "{}", line {}, in {}\n'.format(
483-
frame_summary.filename, frame_summary.lineno, frame_summary.name))
483+
if frame_summary.filename.startswith("<python-input"):
484+
row.append(' REPL, line {}, in {}\n'.format(
485+
frame_summary.lineno, frame_summary.name))
486+
else:
487+
row.append(' File "{}", line {}, in {}\n'.format(
488+
frame_summary.filename, frame_summary.lineno, frame_summary.name))
484489
if frame_summary.line:
485490
stripped_line = frame_summary.line.strip()
486491
row.append(' {}\n'.format(stripped_line))

Parser/peg_api.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,18 @@ _PyParser_ASTFromFile(FILE *fp, PyObject *filename_ob, const char *enc,
2323
return NULL;
2424
}
2525
return _PyPegen_run_parser_from_file_pointer(fp, mode, filename_ob, enc, ps1, ps2,
26-
flags, errcode, arena);
26+
flags, errcode, NULL, arena);
2727
}
28+
29+
mod_ty
30+
_PyParser_InteractiveASTFromFile(FILE *fp, PyObject *filename_ob, const char *enc,
31+
int mode, const char *ps1, const char* ps2,
32+
PyCompilerFlags *flags, int *errcode,
33+
PyObject **interactive_src, PyArena *arena)
34+
{
35+
if (PySys_Audit("compile", "OO", Py_None, filename_ob) < 0) {
36+
return NULL;
37+
}
38+
return _PyPegen_run_parser_from_file_pointer(fp, mode, filename_ob, enc, ps1, ps2,
39+
flags, errcode, interactive_src, arena);
40+
}

Parser/pegen.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,8 @@ _PyPegen_run_parser(Parser *p)
878878
mod_ty
879879
_PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filename_ob,
880880
const char *enc, const char *ps1, const char *ps2,
881-
PyCompilerFlags *flags, int *errcode, PyArena *arena)
881+
PyCompilerFlags *flags, int *errcode,
882+
PyObject **interactive_src, PyArena *arena)
882883
{
883884
struct tok_state *tok = _PyTokenizer_FromFile(fp, enc, ps1, ps2);
884885
if (tok == NULL) {
@@ -908,6 +909,15 @@ _PyPegen_run_parser_from_file_pointer(FILE *fp, int start_rule, PyObject *filena
908909
result = _PyPegen_run_parser(p);
909910
_PyPegen_Parser_Free(p);
910911

912+
if (tok->fp_interactive && tok->interactive_src_start && result && interactive_src != NULL) {
913+
*interactive_src = PyUnicode_FromString(tok->interactive_src_start);
914+
if (!interactive_src || _PyArena_AddPyObject(arena, *interactive_src) < 0) {
915+
Py_XDECREF(interactive_src);
916+
result = NULL;
917+
goto error;
918+
}
919+
}
920+
911921
error:
912922
_PyTokenizer_Free(tok);
913923
return result;

Parser/pegen.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ void *_PyPegen_nonparen_genexp_in_call(Parser *p, expr_ty args, asdl_comprehensi
350350
Parser *_PyPegen_Parser_New(struct tok_state *, int, int, int, int *, PyArena *);
351351
void _PyPegen_Parser_Free(Parser *);
352352
mod_ty _PyPegen_run_parser_from_file_pointer(FILE *, int, PyObject *, const char *,
353-
const char *, const char *, PyCompilerFlags *, int *, PyArena *);
353+
const char *, const char *, PyCompilerFlags *, int *, PyObject **,
354+
PyArena *);
354355
void *_PyPegen_run_parser(Parser *);
355356
mod_ty _PyPegen_run_parser_from_string(const char *, int, PyObject *, PyCompilerFlags *, PyArena *);
356357
asdl_stmt_seq *_PyPegen_interactive_exit(Parser *);

0 commit comments

Comments
 (0)
0