[Python-checkins] bpo-40527: Fix command line argument parsing (GH-19955)
Miss Islington (bot)
webhook-mailer at python.org
Wed May 6 09:43:14 EDT 2020
https://github.com/python/cpython/commit/bce4ddafdd188cc6deb1584728b67b9e149ca6a4
commit: bce4ddafdd188cc6deb1584728b67b9e149ca6a4
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2020-05-06T06:43:09-07:00
summary:
bpo-40527: Fix command line argument parsing (GH-19955)
(cherry picked from commit 2668a9a5aa506a048aef7b4881c8dcf6b81c6870)
Co-authored-by: Victor Stinner <vstinner at python.org>
files:
A Misc/NEWS.d/next/Core and Builtins/2020-05-06-14-52-35.bpo-40527.gTNKuy.rst
M Lib/test/test_cmd_line.py
M Python/getopt.c
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
index 497bfa9eb89de..5fc5bff6603e2 100644
--- a/Lib/test/test_cmd_line.py
+++ b/Lib/test/test_cmd_line.py
@@ -740,6 +740,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):
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-05-06-14-52-35.bpo-40527.gTNKuy.rst b/Misc/NEWS.d/next/Core and Builtins/2020-05-06-14-52-35.bpo-40527.gTNKuy.rst
new file mode 100644
index 0000000000000..19b8888230c65
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-05-06-14-52-35.bpo-40527.gTNKuy.rst
@@ -0,0 +1,2 @@
+Fix command line argument parsing: no longer write errors multiple times
+into stderr.
diff --git a/Python/getopt.c b/Python/getopt.c
index 1a7db3fce888e..249ad1e873607 100644
--- a/Python/getopt.c
+++ b/Python/getopt.c
@@ -105,7 +105,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;
@@ -115,7 +117,9 @@ 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"";
@@ -123,8 +127,10 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
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++];
@@ -132,14 +138,16 @@ int _PyOS_GetOpt(Py_ssize_t argc, wchar_t * const *argv, int *longindex)
}
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 '_';
}
@@ -151,9 +159,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 '_';
}
More information about the Python-checkins
mailing list