]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-125115: Pass unknown pdb command line args to script instead of fail (#125424)
authorTian Gao <gaogaotiantian@hotmail.com>
Tue, 15 Oct 2024 19:30:28 +0000 (12:30 -0700)
committerGitHub <noreply@github.com>
Tue, 15 Oct 2024 19:30:28 +0000 (15:30 -0400)
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 2b36b1e3fa7cbe2fec3bed6b443d75948302afc1..3e5e6088fdcc7e4fa6830647a9728df5375cb856 100644 (file)
@@ -82,6 +82,7 @@ import signal
 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
index 084b7cd4cad219eedc5b685d1d84396d72c7521d..456effc010954a9330e31d0e2e4aac84ab5a51da 100644 (file)
@@ -3089,6 +3089,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'."""
@@ -3106,7 +3107,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
@@ -3559,6 +3562,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.