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

Skip to content

Commit 03e3f40

Browse files
committed
Allow the repl to show source code and complete tracebacks
1 parent d74b837 commit 03e3f40

File tree

7 files changed

+58
-8
lines changed
8000

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
@@ -206,6 +206,7 @@ struct _is {
206206

207207
/* the initial PyInterpreterState.threads.head */
208208
PyThreadState _initial_thread;
209+
Py_ssize_t _interactive_src_count;
209210
};
210211

211212

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
@@ -24,5 +24,18 @@ _PyParser_ASTFromFile(FILE *fp, PyObject *filename_ob, const char *enc,
2424
return NULL;
2525
}
2626
return _PyPegen_run_parser_from_file_pointer(fp, mode, filename_ob, enc, ps1, ps2,
27-
flags, errcode, arena);
27+
flags, errcode, NULL, arena);
2828
}
29+
30+
mod_ty
31+
_PyParser_InteractiveASTFromFile(FILE *fp, PyObject *filename_ob, const char *enc,
32+
int mode, const char *ps1, const char* ps2,
33+
PyCompilerFlags *flags, int *errcode,
34+
PyObject **interactive_src, PyArena *arena)
35+
{
36+
if (PySys_Audit("compile", "OO", Py_None, filename_ob) < 0) {
37+
return NULL;
38+
}
39+
return _PyPegen_run_parser_from_file_pointer(fp, mode, filename_ob, enc, ps1, ps2,
40+
flags, errcode, interactive_src, arena);
41+
}

Parser/pegen.c

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

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