bpo-40527: Fix command line argument parsing (GH-19955)

This commit is contained in:
Victor Stinner 2020-05-06 15:22:17 +02:00 committed by GitHub
parent eff870b618
commit 2668a9a5aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 7 deletions

View File

@ -756,6 +756,17 @@ class CmdLineTest(unittest.TestCase):
self.assertEqual(proc.returncode, 0, proc) self.assertEqual(proc.returncode, 0, proc)
self.assertEqual(proc.stdout.strip(), b'0') 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(), @unittest.skipIf(interpreter_requires_environment(),
'Cannot run -I tests when PYTHON env vars are required.') 'Cannot run -I tests when PYTHON env vars are required.')
class IgnoreEnvironmentTest(unittest.TestCase): class IgnoreEnvironmentTest(unittest.TestCase):

View File

@ -0,0 +1,2 @@
Fix command line argument parsing: no longer write errors multiple times
into stderr.

View File

@ -101,7 +101,9 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
if (option == L'-') { if (option == L'-') {
// Parse long option. // Parse long option.
if (*opt_ptr == L'\0') { if (*opt_ptr == L'\0') {
if (_PyOS_opterr) {
fprintf(stderr, "expected long option\n"); fprintf(stderr, "expected long option\n");
}
return -1; return -1;
} }
*longindex = 0; *longindex = 0;
@ -111,7 +113,9 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
break; break;
} }
if (!opt->name) { if (!opt->name) {
if (_PyOS_opterr) {
fprintf(stderr, "unknown option %ls\n", argv[_PyOS_optind - 1]); fprintf(stderr, "unknown option %ls\n", argv[_PyOS_optind - 1]);
}
return '_'; return '_';
} }
opt_ptr = L""; opt_ptr = L"";
@ -119,8 +123,10 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
return opt->val; return opt->val;
} }
if (_PyOS_optind >= argc) { if (_PyOS_optind >= argc) {
if (_PyOS_opterr) {
fprintf(stderr, "Argument expected for the %ls options\n", fprintf(stderr, "Argument expected for the %ls options\n",
argv[_PyOS_optind - 1]); argv[_PyOS_optind - 1]);
}
return '_'; return '_';
} }
_PyOS_optarg = argv[_PyOS_optind++]; _PyOS_optarg = argv[_PyOS_optind++];
@ -128,14 +134,16 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
} }
if (option == 'J') { if (option == 'J') {
if (_PyOS_opterr) if (_PyOS_opterr) {
fprintf(stderr, "-J is reserved for Jython\n"); fprintf(stderr, "-J is reserved for Jython\n");
}
return '_'; return '_';
} }
if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) { if ((ptr = wcschr(SHORT_OPTS, option)) == NULL) {
if (_PyOS_opterr) if (_PyOS_opterr) {
fprintf(stderr, "Unknown option: -%c\n", (char)option); fprintf(stderr, "Unknown option: -%c\n", (char)option);
}
return '_'; return '_';
} }
@ -147,9 +155,10 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
else { else {
if (_PyOS_optind >= argc) { if (_PyOS_optind >= argc) {
if (_PyOS_opterr) if (_PyOS_opterr) {
fprintf(stderr, fprintf(stderr,
"Argument expected for the -%c option\n", (char)option); "Argument expected for the -%c option\n", (char)option);
}
return '_'; return '_';
} }