]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-125115: Pass unknown pdb command line args to script instead of fail (GH...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 15 Oct 2024 19:55:38 +0000 (21:55 +0200)
committerGitHub <noreply@github.com>
Tue, 15 Oct 2024 19:55:38 +0000 (19:55 +0000)
gh-125115: Pass unknown pdb command line args to script instead of fail (GH-125424)
(cherry picked from commit 9c2bb7d551a695f35db953a671a2ddca89426bef)

Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
Lib/pdb.py
Lib/test/test_pdb.py
Misc/NEWS.d/next/Library/2024-10-14-02-07-44.gh-issue-125115.IOf3ON.rst [new file with mode: 0644]

index 169eb0e49c4a31a970e608b1a90fc56cb9a3eaa8..a987ea7afebfa7608377ddd02643690a75717c02 100755 (executable)
@@ -84,6 +84,7 @@ import signal
 import inspect
 import textwrap
 import tokenize
+import itertools
 import traceback
 import linecache
 import _colorize
@@ -2414,8 +2415,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.
@@ -2423,21 +2422,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
index 266141e566a1ed09aa97de1be6bf5a9351739104..5fe03cc33f34be9e0464bc3ce03808c37065b565 100644 (file)
@@ -2877,6 +2877,7 @@ class PdbTestCase(unittest.TestCase):
     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'."""
@@ -2894,7 +2895,9 @@ class PdbTestCase(unittest.TestCase):
         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
@@ -3341,6 +3344,22 @@ def bœr():
         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 (file)
index 0000000..3583d53
--- /dev/null
@@ -0,0 +1 @@
+Fixed a bug in :mod:`pdb` where arguments starting with ``-`` can't be passed to the debugged script.