Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -2435,30 +2435,38 @@ def main():
parser.add_argument('-c', '--command', action='append', default=[], metavar='command', dest='commands',
help='pdb commands to execute as if given in a .pdbrc file')
parser.add_argument('-m', metavar='module', dest='module')
parser.add_argument('args', nargs='*',
help="when -m is not specified, the first arg is the script to debug")

if len(sys.argv) == 1:
# If no arguments were given (python -m pdb), print the whole help message.
# Without this check, argparse would only complain about missing required arguments.
parser.print_help()
sys.exit(2)

opts = parser.parse_args()
opts, args = parser.parse_known_args()

invalid_args = []
for arg in args:
if not arg.startswith('-'):
break
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the logic here? Why are we breaking?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A pdb CLI usage could be python -m pdb script.py --bar or python -m pdb --bar script.py.

The unknown args would be ['script.py', '--bar'] and [--bar', 'script.py'] respectively. Notice that in the first case, the user is trying to pass --bar to script.py, but in the latter, they try to pass --bar to pdb. This logic is to differentiate this. As long as we got something that does not start with -, we consider that as the script.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm missing something here, for the module case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm missing something here, for the module case.

And a test for this case..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turns out dealing with modules is not super trivial. I added some comments in the parsing code and hopefully that's helpful. We can "change the rule" and require users to use -- to resolve all ambiguities, but I think it would be a better experience if we can be a bit smarter.

An existing test already covers the case where --spam -m module should fail, I added a new test for -m calendar --type text which works after the change.

invalid_args.append(arg)

if invalid_args:
parser.error(f"unrecognized arguments: {' '.join(invalid_args)}")
sys.exit(2)

if opts.module:
file = opts.module
target = _ModuleTarget(file)
else:
if not opts.args:
if not args:
parser.error("no module or script to run")
file = opts.args.pop(0)
file = args.pop(0)
if file.endswith('.pyz'):
target = _ZipTarget(file)
else:
target = _ScriptTarget(file)

sys.argv[:] = [file] + opts.args # Hide "pdb.py" and pdb options from argument list
sys.argv[:] = [file] + args # Hide "pdb.py" and pdb options from argument list

# Note on saving/restoring sys.argv: it's a good idea when sys.argv was
# modified by the script being debugged. It's a bad idea when it was
Expand Down
18 changes: 17 additions & 1 deletion Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -3052,6 +3052,7 @@ def _run_pdb(self, pdb_args, commands,
def run_pdb_script(self, script, commands,
expected_returncode=0,
extra_env=None,
script_args=None,
pdbrc=None,
remove_home=False):
"""Run 'script' lines with pdb and the pdb 'commands'."""
Expand All @@ -3069,7 +3070,9 @@ def run_pdb_script(self, script, commands,
if remove_home:
homesave = os.environ.pop('HOME', None)
try:
stdout, stderr = self._run_pdb([filename], commands, expected_returncode, extra_env)
if script_args is None:
script_args = []
stdout, stderr = self._run_pdb([filename] + script_args, commands, expected_returncode, extra_env)
finally:
if homesave is not None:
os.environ['HOME'] = homesave
Expand Down Expand Up @@ -3508,6 +3511,19 @@ def test_run_module_with_args(self):
stdout, _ = self._run_pdb(["-m", "calendar", "1"], commands)
self.assertIn("December", stdout)

def test_run_script_with_args(self):
script = """
import sys
print(sys.argv[1:])
"""
commands = """
continue
quit
"""

stdout, stderr = self.run_pdb_script(script, commands, script_args=["--bar", "foo"])
self.assertIn("['--bar', 'foo']", stdout)

def test_breakpoint(self):
script = """
if __name__ == '__main__':
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed a bug in :mod:`pdb` where arguments starting with ``-`` can't be passed to the debugged script.
Loading