mirror of https://github.com/python/cpython
bpo-45445: Revert "bpo-45445: Fail if an invalid X-option is provided in the command line (GH-28823)" (#94745)
This commit is contained in:
parent
50b2261bda
commit
aa37ffda29
|
@ -1780,13 +1780,13 @@ always available.
|
||||||
|
|
||||||
.. code-block:: shell-session
|
.. code-block:: shell-session
|
||||||
|
|
||||||
$ ./python -Xpycache_prefix=some_path -Xdev
|
$ ./python -Xa=b -Xc
|
||||||
Python 3.2a3+ (py3k, Oct 16 2010, 20:14:50)
|
Python 3.2a3+ (py3k, Oct 16 2010, 20:14:50)
|
||||||
[GCC 4.4.3] on linux2
|
[GCC 4.4.3] on linux2
|
||||||
Type "help", "copyright", "credits" or "license" for more information.
|
Type "help", "copyright", "credits" or "license" for more information.
|
||||||
>>> import sys
|
>>> import sys
|
||||||
>>> sys._xoptions
|
>>> sys._xoptions
|
||||||
{'pycache_prefix': 'some_path', 'dev': True}
|
{'a': 'b', 'c': True}
|
||||||
|
|
||||||
.. impl-detail::
|
.. impl-detail::
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ class AuditTest(unittest.TestCase):
|
||||||
@support.requires_subprocess()
|
@support.requires_subprocess()
|
||||||
def do_test(self, *args):
|
def do_test(self, *args):
|
||||||
with subprocess.Popen(
|
with subprocess.Popen(
|
||||||
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
|
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
|
@ -35,7 +35,7 @@ class AuditTest(unittest.TestCase):
|
||||||
def run_python(self, *args):
|
def run_python(self, *args):
|
||||||
events = []
|
events = []
|
||||||
with subprocess.Popen(
|
with subprocess.Popen(
|
||||||
[sys.executable, "-Xutf8", AUDIT_TESTS_PY, *args],
|
[sys.executable, "-X utf8", AUDIT_TESTS_PY, *args],
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
|
|
|
@ -105,17 +105,8 @@ class CmdLineTest(unittest.TestCase):
|
||||||
opts = get_xoptions()
|
opts = get_xoptions()
|
||||||
self.assertEqual(opts, {})
|
self.assertEqual(opts, {})
|
||||||
|
|
||||||
opts = get_xoptions('-Xno_debug_ranges', '-Xdev=1234')
|
opts = get_xoptions('-Xa', '-Xb=c,d=e')
|
||||||
self.assertEqual(opts, {'no_debug_ranges': True, 'dev': '1234'})
|
self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
|
||||||
|
|
||||||
@unittest.skipIf(interpreter_requires_environment(),
|
|
||||||
'Cannot run -E tests when PYTHON env vars are required.')
|
|
||||||
def test_unknown_xoptions(self):
|
|
||||||
rc, out, err = assert_python_failure('-X', 'blech')
|
|
||||||
self.assertIn(b'Unknown value for option -X', err)
|
|
||||||
msg = b'Fatal Python error: Unknown value for option -X (see --help-xoptions)'
|
|
||||||
self.assertEqual(err.splitlines().count(msg), 1)
|
|
||||||
self.assertEqual(b'', out)
|
|
||||||
|
|
||||||
def test_showrefcount(self):
|
def test_showrefcount(self):
|
||||||
def run_python(*args):
|
def run_python(*args):
|
||||||
|
|
|
@ -283,7 +283,7 @@ class EmbeddingTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
"test_pre_initialization_sys_options", env=env)
|
"test_pre_initialization_sys_options", env=env)
|
||||||
expected_output = (
|
expected_output = (
|
||||||
"sys.warnoptions: ['once', 'module', 'default']\n"
|
"sys.warnoptions: ['once', 'module', 'default']\n"
|
||||||
"sys._xoptions: {'dev': '2', 'utf8': '1'}\n"
|
"sys._xoptions: {'not_an_option': '1', 'also_not_an_option': '2'}\n"
|
||||||
"warnings.filters[:3]: ['default', 'module', 'once']\n"
|
"warnings.filters[:3]: ['default', 'module', 'once']\n"
|
||||||
)
|
)
|
||||||
self.assertIn(expected_output, out)
|
self.assertIn(expected_output, out)
|
||||||
|
@ -841,14 +841,15 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
'argv': ['-c', 'arg2'],
|
'argv': ['-c', 'arg2'],
|
||||||
'orig_argv': ['python3',
|
'orig_argv': ['python3',
|
||||||
'-W', 'cmdline_warnoption',
|
'-W', 'cmdline_warnoption',
|
||||||
'-X', 'dev',
|
'-X', 'cmdline_xoption',
|
||||||
'-c', 'pass',
|
'-c', 'pass',
|
||||||
'arg2'],
|
'arg2'],
|
||||||
'parse_argv': 2,
|
'parse_argv': 2,
|
||||||
'xoptions': [
|
'xoptions': [
|
||||||
'dev=3',
|
'config_xoption1=3',
|
||||||
'utf8',
|
'config_xoption2=',
|
||||||
'dev',
|
'config_xoption3',
|
||||||
|
'cmdline_xoption',
|
||||||
],
|
],
|
||||||
'warnoptions': [
|
'warnoptions': [
|
||||||
'cmdline_warnoption',
|
'cmdline_warnoption',
|
||||||
|
@ -1076,8 +1077,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
config = {
|
config = {
|
||||||
'faulthandler': 1,
|
'faulthandler': 1,
|
||||||
'xoptions': [
|
'xoptions': [
|
||||||
'dev',
|
'config_xoption',
|
||||||
'utf8',
|
'cmdline_xoption',
|
||||||
|
'sysadd_xoption',
|
||||||
'faulthandler',
|
'faulthandler',
|
||||||
],
|
],
|
||||||
'warnoptions': [
|
'warnoptions': [
|
||||||
|
@ -1087,12 +1089,9 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
],
|
],
|
||||||
'orig_argv': ['python3',
|
'orig_argv': ['python3',
|
||||||
'-W', 'ignore:::cmdline_warnoption',
|
'-W', 'ignore:::cmdline_warnoption',
|
||||||
'-X', 'utf8'],
|
'-X', 'cmdline_xoption'],
|
||||||
}
|
}
|
||||||
preconfig = {'utf8_mode': 1}
|
self.check_all_configs("test_init_sys_add", config, api=API_PYTHON)
|
||||||
self.check_all_configs("test_init_sys_add", config,
|
|
||||||
expected_preconfig=preconfig,
|
|
||||||
api=API_PYTHON)
|
|
||||||
|
|
||||||
def test_init_run_main(self):
|
def test_init_run_main(self):
|
||||||
code = ('import _testinternalcapi, json; '
|
code = ('import _testinternalcapi, json; '
|
||||||
|
|
|
@ -279,7 +279,7 @@ static int test_pre_initialization_sys_options(void)
|
||||||
* relying on the caller to keep the passed in strings alive.
|
* relying on the caller to keep the passed in strings alive.
|
||||||
*/
|
*/
|
||||||
const wchar_t *static_warnoption = L"once";
|
const wchar_t *static_warnoption = L"once";
|
||||||
const wchar_t *static_xoption = L"utf8=1";
|
const wchar_t *static_xoption = L"also_not_an_option=2";
|
||||||
size_t warnoption_len = wcslen(static_warnoption);
|
size_t warnoption_len = wcslen(static_warnoption);
|
||||||
size_t xoption_len = wcslen(static_xoption);
|
size_t xoption_len = wcslen(static_xoption);
|
||||||
wchar_t *dynamic_once_warnoption = \
|
wchar_t *dynamic_once_warnoption = \
|
||||||
|
@ -298,7 +298,7 @@ static int test_pre_initialization_sys_options(void)
|
||||||
PySys_AddWarnOption(L"module");
|
PySys_AddWarnOption(L"module");
|
||||||
PySys_AddWarnOption(L"default");
|
PySys_AddWarnOption(L"default");
|
||||||
_Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
|
_Py_EMBED_PREINIT_CHECK("Checking PySys_AddXOption\n");
|
||||||
PySys_AddXOption(L"dev=2");
|
PySys_AddXOption(L"not_an_option=1");
|
||||||
PySys_AddXOption(dynamic_xoption);
|
PySys_AddXOption(dynamic_xoption);
|
||||||
|
|
||||||
/* Delete the dynamic options early */
|
/* Delete the dynamic options early */
|
||||||
|
@ -591,7 +591,7 @@ static int test_init_from_config(void)
|
||||||
L"-W",
|
L"-W",
|
||||||
L"cmdline_warnoption",
|
L"cmdline_warnoption",
|
||||||
L"-X",
|
L"-X",
|
||||||
L"dev",
|
L"cmdline_xoption",
|
||||||
L"-c",
|
L"-c",
|
||||||
L"pass",
|
L"pass",
|
||||||
L"arg2",
|
L"arg2",
|
||||||
|
@ -599,9 +599,10 @@ static int test_init_from_config(void)
|
||||||
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
|
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
|
||||||
config.parse_argv = 1;
|
config.parse_argv = 1;
|
||||||
|
|
||||||
wchar_t* xoptions[2] = {
|
wchar_t* xoptions[3] = {
|
||||||
L"dev=3",
|
L"config_xoption1=3",
|
||||||
L"utf8",
|
L"config_xoption2=",
|
||||||
|
L"config_xoption3",
|
||||||
};
|
};
|
||||||
config_set_wide_string_list(&config, &config.xoptions,
|
config_set_wide_string_list(&config, &config.xoptions,
|
||||||
Py_ARRAY_LENGTH(xoptions), xoptions);
|
Py_ARRAY_LENGTH(xoptions), xoptions);
|
||||||
|
@ -1425,6 +1426,7 @@ fail:
|
||||||
|
|
||||||
static int test_init_sys_add(void)
|
static int test_init_sys_add(void)
|
||||||
{
|
{
|
||||||
|
PySys_AddXOption(L"sysadd_xoption");
|
||||||
PySys_AddXOption(L"faulthandler");
|
PySys_AddXOption(L"faulthandler");
|
||||||
PySys_AddWarnOption(L"ignore:::sysadd_warnoption");
|
PySys_AddWarnOption(L"ignore:::sysadd_warnoption");
|
||||||
|
|
||||||
|
@ -1436,14 +1438,14 @@ static int test_init_sys_add(void)
|
||||||
L"-W",
|
L"-W",
|
||||||
L"ignore:::cmdline_warnoption",
|
L"ignore:::cmdline_warnoption",
|
||||||
L"-X",
|
L"-X",
|
||||||
L"utf8",
|
L"cmdline_xoption",
|
||||||
};
|
};
|
||||||
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
|
config_set_argv(&config, Py_ARRAY_LENGTH(argv), argv);
|
||||||
config.parse_argv = 1;
|
config.parse_argv = 1;
|
||||||
|
|
||||||
PyStatus status;
|
PyStatus status;
|
||||||
status = PyWideStringList_Append(&config.xoptions,
|
status = PyWideStringList_Append(&config.xoptions,
|
||||||
L"dev");
|
L"config_xoption");
|
||||||
if (PyStatus_Exception(status)) {
|
if (PyStatus_Exception(status)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2061,49 +2061,6 @@ _PyConfig_InitImportConfig(PyConfig *config)
|
||||||
return config_init_import(config, 1);
|
return config_init_import(config, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// List of known xoptions to validate against the provided ones. Note that all
|
|
||||||
// options are listed, even if they are only available if a specific macro is
|
|
||||||
// set, like -X showrefcount which requires a debug build. In this case unknown
|
|
||||||
// options are silently ignored.
|
|
||||||
const wchar_t* known_xoptions[] = {
|
|
||||||
L"faulthandler",
|
|
||||||
L"showrefcount",
|
|
||||||
L"tracemalloc",
|
|
||||||
L"importtime",
|
|
||||||
L"dev",
|
|
||||||
L"utf8",
|
|
||||||
L"pycache_prefix",
|
|
||||||
L"warn_default_encoding",
|
|
||||||
L"no_debug_ranges",
|
|
||||||
L"frozen_modules",
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const wchar_t*
|
|
||||||
_Py_check_xoptions(const PyWideStringList *xoptions, const wchar_t **names)
|
|
||||||
{
|
|
||||||
for (Py_ssize_t i=0; i < xoptions->length; i++) {
|
|
||||||
const wchar_t *option = xoptions->items[i];
|
|
||||||
size_t len;
|
|
||||||
wchar_t *sep = wcschr(option, L'=');
|
|
||||||
if (sep != NULL) {
|
|
||||||
len = (sep - option);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
len = wcslen(option);
|
|
||||||
}
|
|
||||||
int found = 0;
|
|
||||||
for (const wchar_t** name = names; *name != NULL; name++) {
|
|
||||||
if (wcsncmp(option, *name, len) == 0 && (*name)[len] == L'\0') {
|
|
||||||
found = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found == 0) {
|
|
||||||
return option;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyStatus
|
static PyStatus
|
||||||
config_read(PyConfig *config, int compute_path_config)
|
config_read(PyConfig *config, int compute_path_config)
|
||||||
|
@ -2119,11 +2076,6 @@ config_read(PyConfig *config, int compute_path_config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -X options */
|
/* -X options */
|
||||||
const wchar_t* option = _Py_check_xoptions(&config->xoptions, known_xoptions);
|
|
||||||
if (option != NULL) {
|
|
||||||
return PyStatus_Error("Unknown value for option -X (see --help-xoptions)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_get_xoption(config, L"showrefcount")) {
|
if (config_get_xoption(config, L"showrefcount")) {
|
||||||
config->show_ref_count = 1;
|
config->show_ref_count = 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue