Skip to content

Commit c5bad75

Browse files
miss-islingtongaogaotiantianiritkatriel
authored
[3.13] gh-125115: Pass unknown pdb command line args to script instead of fail (GH-125424) (#125547)
gh-125115: Pass unknown pdb command line args to script instead of fail (GH-125424) (cherry picked from commit 9c2bb7d) Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com> Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
1 parent 4d83f6d commit c5bad75

File tree

3 files changed

+45
-7
lines changed

3 files changed

+45
-7
lines changed

Lib/pdb.py

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import inspect
8585
import textwrap
8686
import tokenize
87+
import itertools
8788
import traceback
8889
import linecache
8990
import _colorize
@@ -2414,30 +2415,47 @@ def main():
24142415
parser.add_argument('-c', '--command', action='append', default=[], metavar='command', dest='commands',
24152416
help='pdb commands to execute as if given in a .pdbrc file')
24162417
parser.add_argument('-m', metavar='module', dest='module')
2417-
parser.add_argument('args', nargs='*',
2418-
help="when -m is not specified, the first arg is the script to debug")
24192418

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

2426-
opts = parser.parse_args()
2425+
opts, args = parser.parse_known_args()
2426+
2427+
if opts.module:
2428+
# If a module is being debugged, we consider the arguments after "-m module" to
2429+
# be potential arguments to the module itself. We need to parse the arguments
2430+
# before "-m" to check if there is any invalid argument.
2431+
# e.g. "python -m pdb -m foo --spam" means passing "--spam" to "foo"
2432+
# "python -m pdb --spam -m foo" means passing "--spam" to "pdb" and is invalid
2433+
idx = sys.argv.index('-m')
2434+
args_to_pdb = sys.argv[1:idx]
2435+
# This will raise an error if there are invalid arguments
2436+
parser.parse_args(args_to_pdb)
2437+
else:
2438+
# If a script is being debugged, then pdb expects the script name as the first argument.
2439+
# Anything before the script is considered an argument to pdb itself, which would
2440+
# be invalid because it's not parsed by argparse.
2441+
invalid_args = list(itertools.takewhile(lambda a: a.startswith('-'), args))
2442+
if invalid_args:
2443+
parser.error(f"unrecognized arguments: {' '.join(invalid_args)}")
2444+
sys.exit(2)
24272445

24282446
if opts.module:
24292447
file = opts.module
24302448
target = _ModuleTarget(file)
24312449
else:
2432-
if not opts.args:
2450+
if not args:
24332451
parser.error("no module or script to run")
2434-
file = opts.args.pop(0)
2452+
file = args.pop(0)
24352453
if file.endswith('.pyz'):
24362454
target = _ZipTarget(file)
24372455
else:
24382456
target = _ScriptTarget(file)
24392457

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

24422460
# Note on saving/restoring sys.argv: it's a good idea when sys.argv was
24432461
# modified by the script being debugged. It's a bad idea when it was

Lib/test/test_pdb.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2877,6 +2877,7 @@ def _run_pdb(self, pdb_args, commands,
28772877
def run_pdb_script(self, script, commands,
28782878
expected_returncode=0,
28792879
extra_env=None,
2880+
script_args=None,
28802881
pdbrc=None,
28812882
remove_home=False):
28822883
"""Run 'script' lines with pdb and the pdb 'commands'."""
@@ -2894,7 +2895,9 @@ def run_pdb_script(self, script, commands,
28942895
if remove_home:
28952896
homesave = os.environ.pop('HOME', None)
28962897
try:
2897-
stdout, stderr = self._run_pdb([filename], commands, expected_returncode, extra_env)
2898+
if script_args is None:
2899+
script_args = []
2900+
stdout, stderr = self._run_pdb([filename] + script_args, commands, expected_returncode, extra_env)
28982901
finally:
28992902
if homesave is not None:
29002903
os.environ['HOME'] = homesave
@@ -3341,6 +3344,22 @@ def test_run_module_with_args(self):
33413344
stdout, _ = self._run_pdb(["-m", "calendar", "1"], commands)
33423345
self.assertIn("December", stdout)
33433346

3347+
stdout, _ = self._run_pdb(["-m", "calendar", "--type", "text"], commands)
3348+
self.assertIn("December", stdout)
3349+
3350+
def test_run_script_with_args(self):
3351+
script = """
3352+
import sys
3353+
print(sys.argv[1:])
3354+
"""
3355+
commands = """
3356+
continue
3357+
quit
3358+
"""
3359+
3360+
stdout, stderr = self.run_pdb_script(script, commands, script_args=["--bar", "foo"])
3361+
self.assertIn("['--bar', 'foo']", stdout)
3362+
33443363
def test_breakpoint(self):
33453364
script = """
33463365
if __name__ == '__main__':
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed a bug in :mod:`pdb` where arguments starting with ``-`` can't be passed to the debugged script.

0 commit comments

Comments
 (0)