]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-40527: Fix command line argument parsing (GH-19955)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 6 May 2020 13:43:09 +0000 (06:43 -0700)
committerGitHub <noreply@github.com>
Wed, 6 May 2020 13:43:09 +0000 (06:43 -0700)
(cherry picked from commit 2668a9a5aa506a048aef7b4881c8dcf6b81c6870)

Co-authored-by: Victor Stinner <vstinner@python.org>
Lib/test/test_cmd_line.py
Misc/NEWS.d/next/Core and Builtins/2020-05-06-14-52-35.bpo-40527.gTNKuy.rst [new file with mode: 0644]
Python/getopt.c

index 497bfa9eb89de4eb2fbefd5008c64d32c10378c6..5fc5bff6603e22e757b0d0eb9816ed7da286a21c 100644 (file)
@@ -740,6 +740,17 @@ class CmdLineTest(unittest.TestCase):
         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 (file)
index 0000000..19b8888
--- /dev/null
@@ -0,0 +1,2 @@
+Fix command line argument parsing: no longer write errors multiple times
+into stderr.
index 1a7db3fce888ee5e9aa603411e097034203b1836..249ad1e8736075eedcf3331a4eb06493db75fd00 100644 (file)
@@ -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 '_';
             }