# stop when the debuggee is returning from such generators.
prefix = 'Internal ' if (not exc_traceback
and exc_type is StopIteration) else ''
- self.message('%s%s' % (prefix,
- traceback.format_exception_only(exc_type, exc_value)[-1].strip()))
+ self.message('%s%s' % (prefix, self._format_exc(exc_value)))
self.interaction(frame, exc_traceback)
# General interaction function
displaying = self.displaying.get(self.curframe)
if displaying:
for expr, oldvalue in displaying.items():
- newvalue, _ = self._getval_except(expr)
+ newvalue = self._getval_except(expr)
# check for identity first; this prevents custom __eq__ to
# be called at every loop, and also prevents instances whose
# fields are changed to be displayed
if comma > 0:
# parse stuff after comma: "condition"
cond = arg[comma+1:].lstrip()
+ if err := self._compile_error_message(cond):
+ self.error('Invalid condition %s: %r' % (cond, err))
+ return
arg = arg[:comma].rstrip()
# parse stuff before comma: [filename:]lineno | function
colon = arg.rfind(':')
args = arg.split(' ', 1)
try:
cond = args[1]
+ if err := self._compile_error_message(cond):
+ self.error('Invalid condition %s: %r' % (cond, err))
+ return
except IndexError:
cond = None
try:
def _getval_except(self, arg, frame=None):
try:
if frame is None:
- return eval(arg, self.curframe.f_globals, self.curframe_locals), None
+ return eval(arg, self.curframe.f_globals, self.curframe_locals)
else:
- return eval(arg, frame.f_globals, frame.f_locals), None
+ return eval(arg, frame.f_globals, frame.f_locals)
except BaseException as exc:
- err = traceback.format_exception_only(exc)[-1].strip()
- return _rstr('** raised %s **' % err), exc
+ return _rstr('** raised %s **' % self._format_exc(exc))
def _error_exc(self):
- exc_info = sys.exc_info()[:2]
- self.error(traceback.format_exception_only(*exc_info)[-1].strip())
+ exc = sys.exc_info()[1]
+ self.error(self._format_exc(exc))
def _msg_val_func(self, arg, func):
try:
else:
self.message('No expression is being displayed')
else:
- val, exc = self._getval_except(arg)
- if isinstance(exc, SyntaxError):
- self.message('Unable to display %s: %r' % (arg, val))
+ if err := self._compile_error_message(arg):
+ self.error('Unable to display %s: %r' % (arg, err))
else:
+ val = self._getval_except(arg)
self.displaying.setdefault(self.curframe, {})[arg] = val
self.message('display %s: %r' % (arg, val))
self.run(target.code)
+ def _format_exc(self, exc: BaseException):
+ return traceback.format_exception_only(exc)[-1].strip()
+
+ def _compile_error_message(self, expr):
+ """Return the error message as string if compiling `expr` fails."""
+ try:
+ compile(expr, "<stdin>", "eval")
+ except SyntaxError as exc:
+ return _rstr(self._format_exc(exc))
+ return ""
# Collect all command help into docstring, if not run with -OO
>>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
... 'break 3',
+ ... 'break 4, +',
... 'disable 1',
... 'ignore 1 10',
... 'condition 1 1 < 2',
+ ... 'condition 1 1 <',
... 'break 4',
... 'break 4',
... 'break',
... 'commands 10', # out of range
... 'commands a', # display help
... 'commands 4', # already deleted
+ ... 'break 6, undefined', # condition causing `NameError` during evaluation
+ ... 'continue', # will stop, ignoring runtime error
... 'continue',
... ]):
... test_function()
-> print(1)
(Pdb) break 3
Breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3
+ (Pdb) break 4, +
+ *** Invalid condition +: SyntaxError: invalid syntax
(Pdb) disable 1
Disabled breakpoint 1 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:3
(Pdb) ignore 1 10
Will ignore next 10 crossings of breakpoint 1.
(Pdb) condition 1 1 < 2
New condition set for breakpoint 1.
+ (Pdb) condition 1 1 <
+ *** Invalid condition 1 <: SyntaxError: invalid syntax
(Pdb) break 4
Breakpoint 2 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:4
(Pdb) break 4
end
(Pdb) commands 4
*** cannot set commands: Breakpoint 4 already deleted
+ (Pdb) break 6, undefined
+ Breakpoint 5 at <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>:6
(Pdb) continue
3
+ > <doctest test.test_pdb.test_pdb_breakpoint_commands[0]>(6)test_function()
+ -> print(4)
+ (Pdb) continue
4
"""
... 'undisplay',
... 'display a < 1',
... 'n',
+ ... 'display undefined',
... 'continue',
... ]):
... test_function()
> <doctest test.test_pdb.test_pdb_display_command[0]>(4)test_function()
-> a = 1
(Pdb) display +
- Unable to display +: ** raised SyntaxError: invalid syntax **
+ *** Unable to display +: SyntaxError: invalid syntax
(Pdb) display
No expression is being displayed
(Pdb) display a
(Pdb) n
> <doctest test.test_pdb.test_pdb_display_command[0]>(7)test_function()
-> a = 4
+ (Pdb) display undefined
+ display undefined: ** raised NameError: name 'undefined' is not defined **
(Pdb) continue
"""