https://github.com/python/cpython/commit/9c2bb7d551a695f35db953a671a2ddca89426bef
commit: 9c2bb7d551a695f35db953a671a2ddca89426bef
branch: main
author: Tian Gao <[email protected]>
committer: gaogaotiantian <[email protected]>
date: 2024-10-15T15:30:28-04:00
summary:

gh-125115: Pass unknown pdb command line args to script instead of fail 
(#125424)

Co-authored-by: Irit Katriel <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-10-14-02-07-44.gh-issue-125115.IOf3ON.rst
M Lib/pdb.py
M Lib/test/test_pdb.py

diff --git a/Lib/pdb.py b/Lib/pdb.py
index 2b36b1e3fa7cbe..3e5e6088fdcc7e 100644
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -82,6 +82,7 @@
 import inspect
 import textwrap
 import tokenize
+import itertools
 import traceback
 import linecache
 import _colorize
@@ -2433,8 +2434,6 @@ 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.
@@ -2442,21 +2441,40 @@ def main():
         parser.print_help()
         sys.exit(2)
 
-    opts = parser.parse_args()
+    opts, args = parser.parse_known_args()
+
+    if opts.module:
+        # If a module is being debugged, we consider the arguments after "-m 
module" to
+        # be potential arguments to the module itself. We need to parse the 
arguments
+        # before "-m" to check if there is any invalid argument.
+        # e.g. "python -m pdb -m foo --spam" means passing "--spam" to "foo"
+        #      "python -m pdb --spam -m foo" means passing "--spam" to "pdb" 
and is invalid
+        idx = sys.argv.index('-m')
+        args_to_pdb = sys.argv[1:idx]
+        # This will raise an error if there are invalid arguments
+        parser.parse_args(args_to_pdb)
+    else:
+        # If a script is being debugged, then pdb expects the script name as 
the first argument.
+        # Anything before the script is considered an argument to pdb itself, 
which would
+        # be invalid because it's not parsed by argparse.
+        invalid_args = list(itertools.takewhile(lambda a: a.startswith('-'), 
args))
+        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
diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
index 084b7cd4cad219..456effc010954a 100644
--- a/Lib/test/test_pdb.py
+++ b/Lib/test/test_pdb.py
@@ -3089,6 +3089,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'."""
@@ -3106,7 +3107,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
@@ -3559,6 +3562,22 @@ def test_run_module_with_args(self):
         stdout, _ = self._run_pdb(["-m", "calendar", "1"], commands)
         self.assertIn("December", stdout)
 
+        stdout, _ = self._run_pdb(["-m", "calendar", "--type", "text"], 
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__':
diff --git 
a/Misc/NEWS.d/next/Library/2024-10-14-02-07-44.gh-issue-125115.IOf3ON.rst 
b/Misc/NEWS.d/next/Library/2024-10-14-02-07-44.gh-issue-125115.IOf3ON.rst
new file mode 100644
index 00000000000000..3583d537a6ec61
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-10-14-02-07-44.gh-issue-125115.IOf3ON.rst
@@ -0,0 +1 @@
+Fixed a bug in :mod:`pdb` where arguments starting with ``-`` can't be passed 
to the debugged script.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to