Skip to content

Commit 9a783dc

Browse files
Address comments and add history
1 parent 5c3edfe commit 9a783dc

1 file changed

Lines changed: 51 additions & 16 deletions

File tree

Lib/pdb.py

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,34 @@ def namespace(self):
318318

319319

320320
class _PdbInteractiveConsole(code.InteractiveConsole):
321-
def __init__(self, ns, message):
321+
def __init__(self, ns=None, message=None):
322322
self._message = message
323323
super().__init__(locals=ns, local_exit=True)
324324

325325
def write(self, data):
326-
self._message(data, end='')
326+
if self._message is not None:
327+
self._message(data, end='')
328+
else:
329+
super().write(data)
330+
331+
def more_lines(self, text):
332+
# Generic Python multi-line completeness heuristic.
333+
# Strips pyrepl's trailing auto-indent before compiling.
334+
# This should be functionally identical to simple_interact._more_lines
335+
src = text.rstrip(" \t")
336+
n = len(src)
337+
if n > 0 and text[n-1] == '\n':
338+
text = src
339+
try:
340+
code_obj = self.compile(text, "<stdin>", "single")
341+
except (OverflowError, SyntaxError, ValueError):
342+
lines = text.splitlines(keepends=True)
343+
if len(lines) == 1:
344+
return False
345+
last = lines[-1]
346+
return ((last.startswith((" ", "\t")) or last.strip() != "")
347+
and not last.endswith("\n"))
348+
return code_obj is None
327349

328350

329351
# Interaction prompt line will separate file and call info from code
@@ -355,10 +377,13 @@ def get_default_backend():
355377
def _pyrepl_available():
356378
"""return whether pdb should use _pyrepl for input"""
357379
if not os.getenv("PYTHON_BASIC_REPL"):
358-
from _pyrepl.main import CAN_USE_PYREPL
359-
360-
return CAN_USE_PYREPL
361-
return False
380+
CAN_USE_PYREPL = False
381+
else:
382+
try:
383+
from _pyrepl.main import CAN_USE_PYREPL
384+
except ModuleNotFoundError:
385+
CAN_USE_PYREPL = False
386+
return CAN_USE_PYREPL
362387

363388

364389
class PdbPyReplInput:
@@ -367,7 +392,7 @@ def __init__(self, pdb_instance, stdin, stdout, prompt):
367392

368393
self.pdb_instance = pdb_instance
369394
self.prompt = prompt
370-
self.console = code.InteractiveConsole()
395+
self.console = _PdbInteractiveConsole()
371396
if not (os.isatty(stdin.fileno())):
372397
raise ValueError("stdin is not a TTY")
373398
self.readline_wrapper = _pyrepl.readline._ReadlineWrapper(
@@ -377,9 +402,12 @@ def __init__(self, pdb_instance, stdin, stdout, prompt):
377402
completer_delims=frozenset(' \t\n`@#%^&*()=+[{]}\\|;:\'",<>?')
378403
)
379404
)
405+
try:
406+
self.readline_wrapper.read_history_file()
407+
except (FileNotFoundError, PermissionError, OSError):
408+
pass
380409

381410
def readline(self):
382-
from _pyrepl.simple_interact import _more_lines
383411

384412
def more_lines(text):
385413
if text.strip() == "\x1a":
@@ -392,18 +420,24 @@ def more_lines(text):
392420
func = getattr(self.pdb_instance, 'do_' + cmd, None)
393421
if func is not None:
394422
return False
395-
return _more_lines(self.console, text)
423+
return self.console.more_lines(text)
396424

397425
try:
398426
pyrepl_completer = self.readline_wrapper.get_completer()
399427
self.readline_wrapper.set_completer(self.complete)
400-
return (
428+
multiline = (
401429
self.readline_wrapper.multiline_input(
402430
more_lines,
403431
self.prompt,
404432
'... ' + ' ' * (len(self.prompt) - 4)
405433
) + '\n'
406434
)
435+
try:
436+
self.readline_wrapper.append_history_file()
437+
except (FileNotFoundError, PermissionError, OSError) as e:
438+
import warnings
439+
warnings.warn(f"failed to open the history file for writing: {e}")
440+
return multiline
407441
except EOFError:
408442
return 'EOF'
409443
finally:
@@ -421,7 +455,7 @@ def complete(self, text, state):
421455
stripped = len(origline) - len(line)
422456
begidx = self.readline_wrapper.get_begidx() - stripped
423457
endidx = self.readline_wrapper.get_endidx() - stripped
424-
if begidx>0:
458+
if begidx > 0:
425459
cmd, args, foo = self.pdb_instance.parseline(line)
426460
if not cmd:
427461
compfunc = self.pdb_instance.completedefault
@@ -2484,19 +2518,20 @@ def do_interact(self, arg):
24842518
"""
24852519
ns = {**self.curframe.f_globals, **self.curframe.f_locals}
24862520
console = _PdbInteractiveConsole(ns, message=self.message)
2521+
banner = "*pdb interact start*"
2522+
exitmsg = "*exit from pdb interact command*"
24872523
if self.pyrepl_input is not None:
24882524
from _pyrepl.simple_interact import run_multiline_interactive_console
2489-
self.message("*pdb interact start*")
2525+
self.message(banner)
24902526
try:
24912527
run_multiline_interactive_console(console)
24922528
except SystemExit:
24932529
pass
2494-
self.message("*exit from pdb interact command*")
2530+
self.message(exitmsg)
24952531
else:
24962532
with self._enable_rlcompleter(ns):
2497-
console = _PdbInteractiveConsole(ns, message=self.message)
2498-
console.interact(banner="*pdb interact start*",
2499-
exitmsg="*exit from pdb interact command*")
2533+
console.interact(banner=banner,
2534+
exitmsg=exitmsg)
25002535

25012536
def do_alias(self, arg):
25022537
"""alias [name [command]]

0 commit comments

Comments
 (0)