Skip to content

Commit

Permalink
bpo-40527: Fix command line argument parsing (pythonGH-19955)
Browse files Browse the repository at this point in the history
  • Loading branch information
vstinner authored May 6, 2020
1 parent eff870b commit 2668a9a
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 7 deletions.
11 changes: 11 additions & 0 deletions Lib/test/test_cmd_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,17 @@ def test_argv0_normalization(self):
self.assertEqual(proc.returncode, 0, proc)
self.assertEqual(proc.stdout.strip(), b'0')

def test_parsing_error(self):
args = [sys.executable, '-I', '--unknown-option']
proc = subprocess.run(args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True)
err_msg = "unknown option --unknown-option\nusage: "
self.assertTrue(proc.stderr.startswith(err_msg), proc.stderr)
self.assertNotEqual(proc.returncode, 0)


@unittest.skipIf(interpreter_requires_environment(),
'Cannot run -I tests when PYTHON env vars are required.')
class IgnoreEnvironmentTest(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix command line argument parsing: no longer write errors multiple times
into stderr.
23 changes: 16 additions & 7 deletions Python/getopt.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
if (option == L'-') {
// Parse long option.
if (*opt_ptr == L'\0') {
fprintf(stderr, "expected long option\n");
if (_PyOS_opterr) {
fprintf(stderr, "expected long option\n");
}
return -1;
}
*longindex = 0;
Expand All @@ -111,31 +113,37 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
break;
}
if (!opt->name) {
fprintf(stderr, "unknown option %ls\n", argv[_PyOS_optind - 1]);
if (_PyOS_opterr) {
fprintf(stderr, "unknown option %ls\n", argv[_PyOS_optind - 1]);
}
return '_';
}
opt_ptr = L"";
if (!opt->has_arg) {
return opt->val;
}
if (_PyOS_optind >= argc) {
fprintf(stderr, "Argument expected for the %ls options\n",
argv[_PyOS_optind - 1]);
if (_PyOS_opterr) {
fprintf(stderr, "Argument expected for the %ls options\n",
argv[_PyOS_optind - 1]);
}
return '_';
}
_PyOS_optarg = argv[_PyOS_optind++];
return opt->val;
}

if (option == 'J') {
if (_PyOS_opterr)
if (_PyOS_opterr) {
fprintf(stderr, "-J is reserved for Jython\n");
}
return '_';
}

if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) {
if (_PyOS_opterr)
if (_PyOS_opterr) {
fprintf(stderr, "Unknown option: -%c\n", (char)option);
}
return '_';
}

Expand All @@ -147,9 +155,10 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)

else {
if (_PyOS_optind >= argc) {
if (_PyOS_opterr)
if (_PyOS_opterr) {
fprintf(stderr,
"Argument expected for the -%c option\n", (char)option);
}
return '_';
}

Expand Down

0 comments on commit 2668a9a

Please sign in to comment.