Skip to content

Commit aa37ffd

Browse files
authored
bpo-45445: Revert "bpo-45445: Fail if an invalid X-option is provided in the command line (GH-28823)" (#94745)
1 parent 50b2261 commit aa37ffd

File tree

6 files changed

+27
-83
lines changed

6 files changed

+27
-83
lines changed

Doc/library/sys.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,13 +1780,13 @@ always available.
17801780

17811781
.. code-block:: shell-session
17821782
1783-
$ ./python -Xpycache_prefix=some_path -Xdev
1783+
$ ./python -Xa=b -Xc
17841784
Python 3.2a3+ (py3k, Oct 16 2010, 20:14:50)
17851785
[GCC 4.4.3] on linux2
17861786
Type "help", "copyright", "credits" or "license" for more information.
17871787
>>> import sys
17881788
>>> sys._xoptions
1789-
{'pycache_prefix': 'some_path', 'dev': True}
1789+
{'a': 'b', 'c': True}
17901790
17911791
.. impl-detail::
17921792

Lib/test/test_audit.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class AuditTest(unittest.TestCase):
2020
@support.requires_subprocess()
2121
def do_test(self, *args):
2222
with subprocess.Popen(
23-
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
23+
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
2424
encoding="utf-8",
2525
stdout=subprocess.PIPE,
2626
stderr=subprocess.PIPE,
@@ -35,7 +35,7 @@ def do_test(self, *args):
3535
def run_python(self, *args):
3636
events = []
3737
with subprocess.Popen(
38-
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
38+
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
3939
encoding="utf-8",
4040
stdout=subprocess.PIPE,
4141
stderr=subprocess.PIPE,

Lib/test/test_cmd_line.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,8 @@ def get_xoptions(*args):
105105
opts = get_xoptions()
106106
self.assertEqual(opts, {})
107107

108-
opts = get_xoptions('-Xno_debug_ranges', '-Xdev=1234')
109-
self.assertEqual(opts, {'no_debug_ranges': True, 'dev': '1234'})
110-
111-
@unittest.skipIf(interpreter_requires_environment(),
112-
'Cannot run -E tests when PYTHON env vars are required.')
113-
def test_unknown_xoptions(self):
114-
rc, out, err = assert_python_failure('-X', 'blech')
115-
self.assertIn(b'Unknown value for option -X', err)
116-
msg = b'Fatal Python error: Unknown value for option -X (see --help-xoptions)'
117-
self.assertEqual(err.splitlines().count(msg), 1)
118-
self.assertEqual(b'', out)
108+
opts = get_xoptions('-Xa', '-Xb=c,d=e')
109+
self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
119110

120111
def test_showrefcount(self):
121112
def run_python(*args):

Lib/test/test_embed.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ def test_pre_initialization_sys_options(self):
283283
"test_pre_initialization_sys_options", env=env)
284284
expected_output = (
285285
"sys.warnoptions: ['once', 'module', 'default']\n"
286-
"sys._xoptions: {'dev': '2', 'utf8': '1'}\n"
286+
"sys._xoptions: {'not_an_option': '1', 'also_not_an_option': '2'}\n"
287287
"warnings.filters[:3]: ['default', 'module', 'once']\n"
288288
)
289289
self.assertIn(expected_output, out)
@@ -841,14 +841,15 @@ def test_init_from_config(self):
841841
'argv': ['-c', 'arg2'],
842842
'orig_argv': ['python3',
843843
'-W', 'cmdline_warnoption',
844-
'-X', 'dev',
844+
'-X', 'cmdline_xoption',
845845
'-c', 'pass',
846846
'arg2'],
847847
'parse_argv': 2,
848848
'xoptions': [
849-
'dev=3',
850-
'utf8',
851-
'dev',
849+
'config_xoption1=3',
850+
'config_xoption2=',
851+
'config_xoption3',
852+
'cmdline_xoption',
852853
],
853854
'warnoptions': [
854855
'cmdline_warnoption',
@@ -1076,8 +1077,9 @@ def test_init_sys_add(self):
10761077
config = {
10771078
'faulthandler': 1,
10781079
'xoptions': [
1079-
'dev',
1080-
'utf8',
1080+
'config_xoption',
1081+
'cmdline_xoption',
1082+
'sysadd_xoption',
10811083
'faulthandler',
10821084
],
10831085
'warnoptions': [
@@ -1087,12 +1089,9 @@ def test_init_sys_add(self):
10871089
],
10881090
'orig_argv': ['python3',
10891091
'-W', 'ignore:::cmdline_warnoption',
1090-
'-X', 'utf8'],
1092+
'-X', 'cmdline_xoption'],
10911093
}
1092-
preconfig = {'utf8_mode': 1}
1093-
self.check_all_configs("test_init_sys_add", config,
1094-
expected_preconfig=preconfig,
1095-
api=API_PYTHON)
1094+
self.check_all_configs("test_init_sys_add", config, api=API_PYTHON)
10961095

10971096
def test_init_run_main(self):
10981097
code = ('import _testinternalcapi, json; '

Programs/_testembed.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ static int test_pre_initialization_sys_options(void)
279279
* relying on the caller to keep the passed in strings alive.
280280
*/
281281
const wchar_t *static_warnoption = L"once";
282-
const wchar_t *static_xoption = L"utf8=1";
282+
const wchar_t *static_xoption = L"also_not_an_option=2";
283283
size_t warnoption_len = wcslen(static_warnoption);
284284
size_t xoption_len = wcslen(static_xoption);
285285
wchar_t *dynamic_once_warnoption = \
@@ -298,7 +298,7 @@ static int test_pre_initialization_sys_options(void)
298298
PySys_AddWarnOption(L"module");
299299
PySys_AddWarnOption(L"default");
300300
_Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
301-
PySys_AddXOption(L"dev=2");
301+
PySys_AddXOption(L"not_an_option=1");
302302
PySys_AddXOption(dynamic_xoption);
303303

304304
/* Delete the dynamic options early */
@@ -591,17 +591,18 @@ static int test_init_from_config(void)
591591
L"-W",
592592
L"cmdline_warnoption",
593593
L"-X",
594-
L"dev",
594+
L"cmdline_xoption",
595595
L"-c",
596596
L"pass",
597597
L"arg2",
598598
};
599599
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
600600
config.parse_argv = 1;
601601

602-
wchar_t* xoptions[2] = {
603-
L"dev=3",
604-
L"utf8",
602+
wchar_t* xoptions[3] = {
603+
L"config_xoption1=3",
604+
L"config_xoption2=",
605+
L"config_xoption3",
605606
};
606607
config_set_wide_string_list(&config, &config.xoptions,
607608
Py_ARRAY_LENGTH(xoptions), xoptions);
@@ -1425,6 +1426,7 @@ static int test_init_read_set(void)
14251426

14261427
static int test_init_sys_add(void)
14271428
{
1429+
PySys_AddXOption(L"sysadd_xoption");
14281430
PySys_AddXOption(L"faulthandler");
14291431
PySys_AddWarnOption(L"ignore:::sysadd_warnoption");
14301432

@@ -1436,14 +1438,14 @@ static int test_init_sys_add(void)
14361438
L"-W",
14371439
L"ignore:::cmdline_warnoption",
14381440
L"-X",
1439-
L"utf8",
1441+
L"cmdline_xoption",
14401442
};
14411443
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
14421444
config.parse_argv = 1;
14431445

14441446
PyStatus status;
14451447
status = PyWideStringList_Append(&config.xoptions,
1446-
L"dev");
1448+
L"config_xoption");
14471449
if (PyStatus_Exception(status)) {
14481450
goto fail;
14491451
}

Python/initconfig.c

Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2061,49 +2061,6 @@ _PyConfig_InitImportConfig(PyConfig *config)
20612061
return config_init_import(config, 1);
20622062
}
20632063

2064-
// List of known xoptions to validate against the provided ones. Note that all
2065-
// options are listed, even if they are only available if a specific macro is
2066-
// set, like -X showrefcount which requires a debug build. In this case unknown
2067-
// options are silently ignored.
2068-
const wchar_t* known_xoptions[] = {
2069-
L"faulthandler",
2070-
L"showrefcount",
2071-
L"tracemalloc",
2072-
L"importtime",
2073-
L"dev",
2074-
L"utf8",
2075-
L"pycache_prefix",
2076-
L"warn_default_encoding",
2077-
L"no_debug_ranges",
2078-
L"frozen_modules",
2079-
NULL,
2080-
};
2081-
2082-
static const wchar_t*
2083-
_Py_check_xoptions(const PyWideStringList *xoptions, const wchar_t **names)
2084-
{
2085-
for (Py_ssize_t i=0; i < xoptions->length; i++) {
2086-
const wchar_t *option = xoptions->items[i];
2087-
size_t len;
2088-
wchar_t *sep = wcschr(option, L'=');
2089-
if (sep != NULL) {
2090-
len = (sep - option);
2091-
}
2092-
else {
2093-
len = wcslen(option);
2094-
}
2095-
int found = 0;
2096-
for (const wchar_t** name = names; *name != NULL; name++) {
2097-
if (wcsncmp(option, *name, len) == 0 && (*name)[len] == L'\0') {
2098-
found = 1;
2099-
}
2100-
}
2101-
if (found == 0) {
2102-
return option;
2103-
}
2104-
}
2105-
return NULL;
2106-
}
21072064

21082065
static PyStatus
21092066
config_read(PyConfig *config, int compute_path_config)
@@ -2119,11 +2076,6 @@ config_read(PyConfig *config, int compute_path_config)
21192076
}
21202077

21212078
/* -X options */
2122-
const wchar_t* option = _Py_check_xoptions(&config->xoptions, known_xoptions);
2123-
if (option != NULL) {
2124-
return PyStatus_Error("Unknown value for option -X (see --help-xoptions)");
2125-
}
2126-
21272079
if (config_get_xoption(config, L"showrefcount")) {
21282080
config->show_ref_count = 1;
21292081
}

0 commit comments

Comments
 (0)