Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -3634,6 +3634,10 @@ def parse_args():
opt_module = parser.parse_args(args[:2])
opts.module = opt_module.module
args = args[2:]
elif args[0] == '--':
args.pop(0)
if not args:
parser.error("missing script or module to run")
elif args[0].startswith('-'):
# Invalid argument before the script name.
invalid_args = list(itertools.takewhile(lambda a: a.startswith('-'), args))
Expand Down
43 changes: 43 additions & 0 deletions Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4173,6 +4173,20 @@ def test_run_script_with_args(self):
stdout, stderr = self.run_pdb_script(script, commands, script_args=["--bar", "foo"])
self.assertIn("['--bar', 'foo']", stdout)

def test_run_script_with_double_dash(self):
script = "import sys; print(sys.argv)"
commands = "continue\nquit"
filename = 'main.py'
with open(filename, 'w') as f:
f.write(script)
self.addCleanup(os_helper.unlink, filename)
stdout, _ = self._run_pdb(["--", filename, "-c", "example"], commands)
self.assertIn(f"['{filename}', '-c', 'example']", stdout)
stdout, _ = self._run_pdb(["-c", "continue", "--", filename, "-c", "example"], "quit")
self.assertIn(f"['{filename}', '-c', 'example']", stdout)
stdout, stderr = self._run_pdb(["--"], "", expected_returncode=2)
self.assertIn("pdb: error: missing script or module to run", stderr)

def test_breakpoint(self):
script = """
if __name__ == '__main__':
Expand Down Expand Up @@ -5196,6 +5210,35 @@ def test_interact_completion(self):
self.assertIn(b'84', output)


class PdbCommandLineTestCase(unittest.TestCase):
def test_end_of_options_separator(self):
# gh-148615: Test parsing when '--' separator is used
from pdb import parse_args
with patch('sys.argv', ['pdb.py', '--', 'my_script.py', '-foo']):
opts, args = parse_args()
self.assertEqual(args, ['my_script.py', '-foo'])
with patch('sys.argv', ['pdb.py', '-c', 'continue', '--', 'my_script.py', '-c', 'foo']):
opts, args = parse_args()
self.assertEqual(opts.commands, ['continue'])
self.assertEqual(args, ['my_script.py', '-c', 'foo'])
with patch('sys.argv', ['pdb.py', '--']):
with support.captured_stderr() as stderr:
with self.assertRaises(SystemExit):
parse_args()
self.assertIn("missing script or module to run", stderr.getvalue())
with patch('sys.argv', ['pdb.py', '-x', '--', 'my_script.py']):
with support.captured_stderr() as stderr:
with self.assertRaises(SystemExit):
parse_args()
self.assertIn("unrecognized arguments: -x", stderr.getvalue())
with patch('sys.argv', ['pdb.py', 'foo', '--', 'my_script.py']):
opts, args = parse_args()
self.assertEqual(args, ['foo', '--', 'my_script.py'])
with patch('sys.argv', ['pdb.py', '-m', 'my_module', '--', 'foo']):
opts, args = parse_args()
self.assertEqual(opts.module, 'my_module')
self.assertEqual(args, ['--', 'foo'])

def load_tests(loader, tests, pattern):
from test import test_pdb

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix :mod:`pdb` to accept standard ``--`` end of options separator,
which was inadvertently rejected since the switch from :mod:`getopt` to
:mod:`argparse` in Python 3.13. Reported by haampie. Patched by Shrey Naithani.
Loading