From 78df8b353b91215187c8635fc350b420a2f76bc2 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 May 2020 14:50:26 +0200 Subject: [PATCH] bpo-40527: Fix command line argument parsing Fix command line argument parsing: no longer write errors multiple times into stderr. _PyPreConfig_Read() no longer writes command line errors into stderr: PyConfig_Read() is responsible to writes these errors. --- Lib/test/test_cmd_line.py | 11 +++++++++ .../2020-05-06-14-52-35.bpo-40527.gTNKuy.rst | 2 ++ Python/getopt.c | 23 +++++++++++++------ 3 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2020-05-06-14-52-35.bpo-40527.gTNKuy.rst diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py index ee96473322dba0..724402533038d4 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -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): 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 00000000000000..19b8888230c659 --- /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 708d9ce496287c..2e3891aae2d16a 100644 --- a/Python/getopt.c +++ b/Python/getopt.c @@ -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; @@ -111,7 +113,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""; @@ -119,8 +123,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++]; @@ -128,14 +134,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 '_'; } @@ -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 '_'; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy