Skip to content

Commit 1bc0ed1

Browse files
authored
gh-132414: Make invalid command-line options visible in the error message (GH-157921)
1 parent 7c87319 commit 1bc0ed1

3 files changed

Lines changed: 19 additions & 9 deletions

File tree

‎Lib/test/test_cmd_line.py‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -677,23 +677,29 @@ def test_unknown_options(self):
677677
for option in ('-z', '--long-option', '---'):
678678
with self.subTest(option=option):
679679
rc, out, err = assert_python_failure('-E', option)
680-
errmsg = f'Unknown option: {option}'.encode()
680+
errmsg = f"Invalid option '{option}'".encode()
681681
self.assertIn(errmsg, err)
682682
self.assertEqual(err.splitlines().count(errmsg), 1)
683683
self.assertEqual(b'', out)
684684

685685
# Add "without='-E'" to prevent _assert_python to append -E
686686
# to env_vars and change the output of stderr
687687
rc, out, err = assert_python_failure('-z', without='-E')
688-
self.assertIn(b'Unknown option: -z', err)
689-
self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
688+
self.assertIn(b"Invalid option '-z'", err)
689+
self.assertEqual(err.splitlines().count(b"Invalid option '-z'"), 1)
690690
self.assertEqual(b'', out)
691691

692692
rc, out, err = assert_python_failure('-a', '-z', without='-E')
693-
self.assertIn(b'Unknown option: -a', err)
693+
self.assertIn(b"Invalid option '-a'", err)
694694
# only the first unknown option is reported
695-
self.assertNotIn(b'Unknown option: -z', err)
696-
self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1)
695+
self.assertNotIn(b"Invalid option '-z'", err)
696+
self.assertEqual(err.splitlines().count(b"Invalid option '-a'"), 1)
697+
self.assertEqual(b'', out)
698+
699+
# gh-132414: a quoted "-q -i" arrives as one argument; the space
700+
# after -q must be visible in the error message
701+
rc, out, err = assert_python_failure('-q -i', without='-E')
702+
self.assertIn(b"Invalid option '- '", err)
697703
self.assertEqual(b'', out)
698704

699705
@unittest.skipIf(interpreter_requires_environment(),
@@ -1162,7 +1168,7 @@ def test_parsing_error(self):
11621168
stdout=subprocess.PIPE,
11631169
stderr=subprocess.PIPE,
11641170
text=True)
1165-
err_msg = "Unknown option: --unknown-option\nusage: "
1171+
err_msg = "Invalid option '--unknown-option'\nusage: "
11661172
self.assertStartsWith(proc.stderr, err_msg)
11671173
self.assertNotEqual(proc.returncode, 0)
11681174

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Quote the invalid option in the error message for an unknown command-line
2+
option: ``Invalid option '-z'`` instead of ``Unknown option: -z``. A stray
3+
space, as passed by a shebang line like ``#!/usr/bin/python3 -q -i``, is now
4+
reported as ``Invalid option '- '``.

‎Python/getopt.c‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ _PyOS_GetOpt(struct _PyOS_GetOpt *getopt)
137137

138138
if (!opt->name) {
139139
if (error) {
140-
fprintf(stderr, "Unknown option: %ls\n", argv[getopt->index - 1]);
140+
fprintf(stderr, "Invalid option '%ls'\n", argv[getopt->index - 1]);
141141
}
142142
return '_';
143143
}
@@ -160,7 +160,7 @@ _PyOS_GetOpt(struct _PyOS_GetOpt *getopt)
160160
wchar_t *ptr = wcschr(SHORT_OPTS, option);
161161
if (ptr == NULL) {
162162
if (error) {
163-
fprintf(stderr, "Unknown option: -%lc\n", option);
163+
fprintf(stderr, "Invalid option '-%lc'\n", option);
164164
}
165165
return '_';
166166
}

0 commit comments

Comments
 (0)