try:
bnum = int(arg)
except:
- self.error("Usage: commands [bnum]\n ...\n end")
+ self._print_invalid_arg(arg)
return
try:
self.get_bpbynumber(bnum)
condition evaluates to true.
"""
args = arg.split()
- try:
- count = int(args[1].strip())
- except:
+ if not args:
+ self.error('Breakpoint number expected')
+ return
+ if len(args) == 1:
count = 0
+ elif len(args) == 2:
+ try:
+ count = int(args[1])
+ except ValueError:
+ self._print_invalid_arg(arg)
+ return
+ else:
+ self._print_invalid_arg(arg)
+ return
try:
bp = self.get_bpbynumber(args[0].strip())
- except IndexError:
- self.error('Breakpoint number expected')
except ValueError as err:
self.error(err)
else:
An arrow indicates the "current frame", which determines the
context of most commands. 'bt' is an alias for this command.
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
self.print_stack_trace()
do_w = do_where
do_bt = do_where
(either in a function that is called or in the current
function).
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
self.set_step()
return 1
do_s = do_step
Continue execution until the next line in the current function
is reached or it returns.
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
self.set_next(self.curframe)
return 1
do_n = do_next
Continue execution until the current function returns.
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
self.set_return(self.curframe)
return 1
do_r = do_return
Continue execution, only stop when a breakpoint is encountered.
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
if not self.nosigint:
try:
Pdb._previous_sigint_handler = \
Print the argument list of the current function.
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
co = self.curframe.f_code
dict = self.curframe_locals
n = co.co_argcount + co.co_kwonlyargcount
Print the return value for the last return of a function.
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
if '__return__' in self.curframe_locals:
self.message(repr(self.curframe_locals['__return__']))
else:
List the whole source code for the current function or frame.
"""
+ if arg:
+ self._print_invalid_arg(arg)
+ return
filename = self.curframe.f_code.co_filename
breaklist = self.get_file_breaks(filename)
try:
Delete the specified alias.
"""
args = arg.split()
- if len(args) == 0: return
+ if len(args) == 0:
+ self._print_invalid_arg(arg)
+ return
if args[0] in self.aliases:
del self.aliases[args[0]]
lineno = max(1, lineno)
return lines, lineno
- def _help_message_from_doc(self, doc):
+ def _help_message_from_doc(self, doc, usage_only=False):
lines = [line.strip() for line in doc.rstrip().splitlines()]
if not lines:
return "No help message found."
elif i < usage_end:
prefix = " "
else:
+ if usage_only:
+ break
prefix = ""
formatted.append(indent + prefix + line)
return "\n".join(formatted)
+ def _print_invalid_arg(self, arg):
+ """Return the usage string for a function."""
+
+ self.error(f"Invalid argument: {arg}")
+
+ # Yes it's a bit hacky. Get the caller name, get the method based on
+ # that name, and get the docstring from that method.
+ # This should NOT fail if the caller is a method of this class.
+ doc = inspect.getdoc(getattr(self, sys._getframe(1).f_code.co_name))
+ if doc is not None:
+ self.message(self._help_message_from_doc(doc, usage_only=True))
+
# Collect all command help into docstring, if not run with -OO
if __doc__ is not None:
(Pdb) commands 10
*** cannot set commands: Breakpoint number 10 out of range
(Pdb) commands a
- *** Usage: commands [bnum]
- ...
- end
+ *** Invalid argument: a
+ Usage: (Pdb) commands [bpnumber]
+ (com) ...
+ (com) end
+ (Pdb)
(Pdb) commands 4
*** cannot set commands: Breakpoint 4 already deleted
(Pdb) break 6, undefined
(Pdb) continue
"""
+def test_pdb_invalid_arg():
+ """This tests pdb commands that have invalid arguments
+
+ >>> def test_function():
+ ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
+ ... pass
+
+ >>> with PdbTestInput([
+ ... 'a = 3',
+ ... 'll 4',
+ ... 'step 1',
+ ... 'continue'
+ ... ]):
+ ... test_function()
+ > <doctest test.test_pdb.test_pdb_invalid_arg[0]>(3)test_function()
+ -> pass
+ (Pdb) a = 3
+ *** Invalid argument: = 3
+ Usage: a(rgs)
+ (Pdb) ll 4
+ *** Invalid argument: 4
+ Usage: ll | longlist
+ (Pdb) step 1
+ *** Invalid argument: 1
+ Usage: s(tep)
+ (Pdb) continue
+ """
+
# Module for testing skipping of module that makes a callback
mod = types.ModuleType('module_to_skip')