[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