mirror of
https://github.com/python/cpython.git
synced 2025-10-10 00:43:41 +00:00
gh-96512: Move int_max_str_digits setting to PyConfig (#96944)
It had to live as a global outside of PyConfig for stable ABI reasons in the pre-3.12 backports. This removes the `_Py_global_config_int_max_str_digits` and gets rid of the equivalent field in the internal `struct _is PyInterpreterState` as code can just use the existing nested config struct within that. Adds tests to verify unique settings and configs in subinterpreters.
This commit is contained in:
parent
cfbc7dd910
commit
b0f89cb431
13 changed files with 111 additions and 24 deletions
|
@ -828,6 +828,24 @@ PyConfig
|
||||||
|
|
||||||
Default: ``0``.
|
Default: ``0``.
|
||||||
|
|
||||||
|
.. c:member:: int int_max_str_digits
|
||||||
|
|
||||||
|
Configures the :ref:`integer string conversion length limitation
|
||||||
|
<int_max_str_digits>`. An initial value of ``-1`` means the value will
|
||||||
|
be taken from the command line or environment or otherwise default to
|
||||||
|
4300 (:data:`sys.int_info.default_max_str_digits`). A value of ``0``
|
||||||
|
disables the limitation. Values greater than zero but less than 640
|
||||||
|
(:data:`sys.int_info.str_digits_check_threshold`) are unsupported and
|
||||||
|
will produce an error.
|
||||||
|
|
||||||
|
Configured by the :option:`-X int_max_str_digits <-X>` command line
|
||||||
|
flag or the :envvar:`PYTHONINTMAXSTRDIGITS` environment varable.
|
||||||
|
|
||||||
|
Default: ``-1`` in Python mode. 4300
|
||||||
|
(:data:`sys.int_info.default_max_str_digits`) in isolated mode.
|
||||||
|
|
||||||
|
.. versionadded:: 3.12
|
||||||
|
|
||||||
.. c:member:: int isolated
|
.. c:member:: int isolated
|
||||||
|
|
||||||
If greater than ``0``, enable isolated mode:
|
If greater than ``0``, enable isolated mode:
|
||||||
|
|
|
@ -178,6 +178,7 @@ typedef struct PyConfig {
|
||||||
wchar_t *check_hash_pycs_mode;
|
wchar_t *check_hash_pycs_mode;
|
||||||
int use_frozen_modules;
|
int use_frozen_modules;
|
||||||
int safe_path;
|
int safe_path;
|
||||||
|
int int_max_str_digits;
|
||||||
|
|
||||||
/* --- Path configuration inputs ------------ */
|
/* --- Path configuration inputs ------------ */
|
||||||
int pathconfig_warnings;
|
int pathconfig_warnings;
|
||||||
|
|
|
@ -170,8 +170,6 @@ extern void _Py_DumpPathConfig(PyThreadState *tstate);
|
||||||
|
|
||||||
PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(void);
|
PyAPI_FUNC(PyObject*) _Py_Get_Getpath_CodeObject(void);
|
||||||
|
|
||||||
extern int _Py_global_config_int_max_str_digits; // TODO(gpshead): move this into PyConfig in 3.12 after the backports ship.
|
|
||||||
|
|
||||||
|
|
||||||
/* --- Function used for testing ---------------------------------- */
|
/* --- Function used for testing ---------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -175,8 +175,6 @@ struct _is {
|
||||||
struct types_state types;
|
struct types_state types;
|
||||||
struct callable_cache callable_cache;
|
struct callable_cache callable_cache;
|
||||||
|
|
||||||
int int_max_str_digits;
|
|
||||||
|
|
||||||
/* The following fields are here to avoid allocation during init.
|
/* The following fields are here to avoid allocation during init.
|
||||||
The data is exposed through PyInterpreterState pointer fields.
|
The data is exposed through PyInterpreterState pointer fields.
|
||||||
These fields should not be accessed directly outside of init.
|
These fields should not be accessed directly outside of init.
|
||||||
|
|
|
@ -999,6 +999,39 @@ class SubinterpreterTest(unittest.TestCase):
|
||||||
self.assertEqual(ret, 0)
|
self.assertEqual(ret, 0)
|
||||||
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
|
self.assertEqual(pickle.load(f), {'a': '123x', 'b': '123'})
|
||||||
|
|
||||||
|
def test_py_config_isoloated_per_interpreter(self):
|
||||||
|
# A config change in one interpreter must not leak to out to others.
|
||||||
|
#
|
||||||
|
# This test could verify ANY config value, it just happens to have been
|
||||||
|
# written around the time of int_max_str_digits. Refactoring is okay.
|
||||||
|
code = """if 1:
|
||||||
|
import sys, _testinternalcapi
|
||||||
|
|
||||||
|
# Any config value would do, this happens to be the one being
|
||||||
|
# double checked at the time this test was written.
|
||||||
|
config = _testinternalcapi.get_config()
|
||||||
|
config['int_max_str_digits'] = 55555
|
||||||
|
_testinternalcapi.set_config(config)
|
||||||
|
sub_value = _testinternalcapi.get_config()['int_max_str_digits']
|
||||||
|
assert sub_value == 55555, sub_value
|
||||||
|
"""
|
||||||
|
before_config = _testinternalcapi.get_config()
|
||||||
|
assert before_config['int_max_str_digits'] != 55555
|
||||||
|
self.assertEqual(support.run_in_subinterp(code), 0,
|
||||||
|
'subinterp code failure, check stderr.')
|
||||||
|
after_config = _testinternalcapi.get_config()
|
||||||
|
self.assertIsNot(
|
||||||
|
before_config, after_config,
|
||||||
|
"Expected get_config() to return a new dict on each call")
|
||||||
|
self.assertEqual(before_config, after_config,
|
||||||
|
"CAUTION: Tests executed after this may be "
|
||||||
|
"running under an altered config.")
|
||||||
|
# try:...finally: calling set_config(before_config) not done
|
||||||
|
# as that results in sys.argv, sys.path, and sys.warnoptions
|
||||||
|
# "being modified by test_capi" per test.regrtest. So if this
|
||||||
|
# test fails, assume that the environment in this process may
|
||||||
|
# be altered and suspect.
|
||||||
|
|
||||||
def test_mutate_exception(self):
|
def test_mutate_exception(self):
|
||||||
"""
|
"""
|
||||||
Exceptions saved in global module state get shared between
|
Exceptions saved in global module state get shared between
|
||||||
|
|
|
@ -882,7 +882,8 @@ class CmdLineTest(unittest.TestCase):
|
||||||
return tuple(int(i) for i in out.split())
|
return tuple(int(i) for i in out.split())
|
||||||
|
|
||||||
res = assert_python_ok('-c', code)
|
res = assert_python_ok('-c', code)
|
||||||
self.assertEqual(res2int(res), (-1, sys.get_int_max_str_digits()))
|
current_max = sys.get_int_max_str_digits()
|
||||||
|
self.assertEqual(res2int(res), (current_max, current_max))
|
||||||
res = assert_python_ok('-X', 'int_max_str_digits=0', '-c', code)
|
res = assert_python_ok('-X', 'int_max_str_digits=0', '-c', code)
|
||||||
self.assertEqual(res2int(res), (0, 0))
|
self.assertEqual(res2int(res), (0, 0))
|
||||||
res = assert_python_ok('-X', 'int_max_str_digits=4000', '-c', code)
|
res = assert_python_ok('-X', 'int_max_str_digits=4000', '-c', code)
|
||||||
|
|
|
@ -434,6 +434,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
'install_signal_handlers': 1,
|
'install_signal_handlers': 1,
|
||||||
'use_hash_seed': 0,
|
'use_hash_seed': 0,
|
||||||
'hash_seed': 0,
|
'hash_seed': 0,
|
||||||
|
'int_max_str_digits': sys.int_info.default_max_str_digits,
|
||||||
'faulthandler': 0,
|
'faulthandler': 0,
|
||||||
'tracemalloc': 0,
|
'tracemalloc': 0,
|
||||||
'perf_profiling': 0,
|
'perf_profiling': 0,
|
||||||
|
@ -876,6 +877,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
'platlibdir': 'my_platlibdir',
|
'platlibdir': 'my_platlibdir',
|
||||||
'module_search_paths': self.IGNORE_CONFIG,
|
'module_search_paths': self.IGNORE_CONFIG,
|
||||||
'safe_path': 1,
|
'safe_path': 1,
|
||||||
|
'int_max_str_digits': 31337,
|
||||||
|
|
||||||
'check_hash_pycs_mode': 'always',
|
'check_hash_pycs_mode': 'always',
|
||||||
'pathconfig_warnings': 0,
|
'pathconfig_warnings': 0,
|
||||||
|
@ -912,6 +914,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
'platlibdir': 'env_platlibdir',
|
'platlibdir': 'env_platlibdir',
|
||||||
'module_search_paths': self.IGNORE_CONFIG,
|
'module_search_paths': self.IGNORE_CONFIG,
|
||||||
'safe_path': 1,
|
'safe_path': 1,
|
||||||
|
'int_max_str_digits': 4567,
|
||||||
}
|
}
|
||||||
self.check_all_configs("test_init_compat_env", config, preconfig,
|
self.check_all_configs("test_init_compat_env", config, preconfig,
|
||||||
api=API_COMPAT)
|
api=API_COMPAT)
|
||||||
|
@ -944,6 +947,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
|
||||||
'platlibdir': 'env_platlibdir',
|
'platlibdir': 'env_platlibdir',
|
||||||
'module_search_paths': self.IGNORE_CONFIG,
|
'module_search_paths': self.IGNORE_CONFIG,
|
||||||
'safe_path': 1,
|
'safe_path': 1,
|
||||||
|
'int_max_str_digits': 4567,
|
||||||
}
|
}
|
||||||
self.check_all_configs("test_init_python_env", config, preconfig,
|
self.check_all_configs("test_init_python_env", config, preconfig,
|
||||||
api=API_PYTHON)
|
api=API_PYTHON)
|
||||||
|
|
|
@ -770,6 +770,26 @@ class IntStrDigitLimitsTests(unittest.TestCase):
|
||||||
with self.subTest(base=base):
|
with self.subTest(base=base):
|
||||||
self._other_base_helper(base)
|
self._other_base_helper(base)
|
||||||
|
|
||||||
|
def test_int_max_str_digits_is_per_interpreter(self):
|
||||||
|
# Changing the limit in one interpreter does not change others.
|
||||||
|
code = """if 1:
|
||||||
|
# Subinterpreters maintain and enforce their own limit
|
||||||
|
import sys
|
||||||
|
sys.set_int_max_str_digits(2323)
|
||||||
|
try:
|
||||||
|
int('3'*3333)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise AssertionError('Expected a int max str digits ValueError.')
|
||||||
|
"""
|
||||||
|
with support.adjust_int_max_str_digits(4000):
|
||||||
|
before_value = sys.get_int_max_str_digits()
|
||||||
|
self.assertEqual(support.run_in_subinterp(code), 0,
|
||||||
|
'subinterp code failure, check stderr.')
|
||||||
|
after_value = sys.get_int_max_str_digits()
|
||||||
|
self.assertEqual(before_value, after_value)
|
||||||
|
|
||||||
|
|
||||||
class IntSubclassStrDigitLimitsTests(IntStrDigitLimitsTests):
|
class IntSubclassStrDigitLimitsTests(IntStrDigitLimitsTests):
|
||||||
int_class = IntSubclass
|
int_class = IntSubclass
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Configuration for the :ref:`integer string conversion length limitation
|
||||||
|
<int_max_str_digits>` now lives in the PyConfig C API struct.
|
|
@ -1767,7 +1767,7 @@ long_to_decimal_string_internal(PyObject *aa,
|
||||||
if (size_a >= 10 * _PY_LONG_MAX_STR_DIGITS_THRESHOLD
|
if (size_a >= 10 * _PY_LONG_MAX_STR_DIGITS_THRESHOLD
|
||||||
/ (3 * PyLong_SHIFT) + 2) {
|
/ (3 * PyLong_SHIFT) + 2) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
int max_str_digits = interp->int_max_str_digits;
|
int max_str_digits = interp->config.int_max_str_digits;
|
||||||
if ((max_str_digits > 0) &&
|
if ((max_str_digits > 0) &&
|
||||||
(max_str_digits / (3 * PyLong_SHIFT) <= (size_a - 11) / 10)) {
|
(max_str_digits / (3 * PyLong_SHIFT) <= (size_a - 11) / 10)) {
|
||||||
PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_STR,
|
PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_STR,
|
||||||
|
@ -1837,7 +1837,7 @@ long_to_decimal_string_internal(PyObject *aa,
|
||||||
}
|
}
|
||||||
if (strlen > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) {
|
if (strlen > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
int max_str_digits = interp->int_max_str_digits;
|
int max_str_digits = interp->config.int_max_str_digits;
|
||||||
Py_ssize_t strlen_nosign = strlen - negative;
|
Py_ssize_t strlen_nosign = strlen - negative;
|
||||||
if ((max_str_digits > 0) && (strlen_nosign > max_str_digits)) {
|
if ((max_str_digits > 0) && (strlen_nosign > max_str_digits)) {
|
||||||
Py_DECREF(scratch);
|
Py_DECREF(scratch);
|
||||||
|
@ -2578,7 +2578,7 @@ long_from_string_base(const char **str, int base, PyLongObject **res)
|
||||||
* quadratic algorithm. */
|
* quadratic algorithm. */
|
||||||
if (digits > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) {
|
if (digits > _PY_LONG_MAX_STR_DIGITS_THRESHOLD) {
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
int max_str_digits = interp->int_max_str_digits;
|
int max_str_digits = interp->config.int_max_str_digits;
|
||||||
if ((max_str_digits > 0) && (digits > max_str_digits)) {
|
if ((max_str_digits > 0) && (digits > max_str_digits)) {
|
||||||
PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_INT,
|
PyErr_Format(PyExc_ValueError, _MAX_STR_DIGITS_ERROR_FMT_TO_INT,
|
||||||
max_str_digits, digits);
|
max_str_digits, digits);
|
||||||
|
@ -6235,10 +6235,6 @@ _PyLong_InitTypes(PyInterpreterState *interp)
|
||||||
return _PyStatus_ERR("can't init int info type");
|
return _PyStatus_ERR("can't init int info type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
interp->int_max_str_digits = _Py_global_config_int_max_str_digits;
|
|
||||||
if (interp->int_max_str_digits == -1) {
|
|
||||||
interp->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _PyStatus_OK();
|
return _PyStatus_OK();
|
||||||
}
|
}
|
||||||
|
|
|
@ -683,6 +683,9 @@ static int test_init_from_config(void)
|
||||||
|
|
||||||
config._isolated_interpreter = 1;
|
config._isolated_interpreter = 1;
|
||||||
|
|
||||||
|
putenv("PYTHONINTMAXSTRDIGITS=6666");
|
||||||
|
config.int_max_str_digits = 31337;
|
||||||
|
|
||||||
init_from_config_clear(&config);
|
init_from_config_clear(&config);
|
||||||
|
|
||||||
dump_config();
|
dump_config();
|
||||||
|
@ -748,6 +751,7 @@ static void set_most_env_vars(void)
|
||||||
putenv("PYTHONIOENCODING=iso8859-1:replace");
|
putenv("PYTHONIOENCODING=iso8859-1:replace");
|
||||||
putenv("PYTHONPLATLIBDIR=env_platlibdir");
|
putenv("PYTHONPLATLIBDIR=env_platlibdir");
|
||||||
putenv("PYTHONSAFEPATH=1");
|
putenv("PYTHONSAFEPATH=1");
|
||||||
|
putenv("PYTHONINTMAXSTRDIGITS=4567");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -695,6 +695,7 @@ config_check_consistency(const PyConfig *config)
|
||||||
assert(config->pathconfig_warnings >= 0);
|
assert(config->pathconfig_warnings >= 0);
|
||||||
assert(config->_is_python_build >= 0);
|
assert(config->_is_python_build >= 0);
|
||||||
assert(config->safe_path >= 0);
|
assert(config->safe_path >= 0);
|
||||||
|
assert(config->int_max_str_digits >= 0);
|
||||||
// config->use_frozen_modules is initialized later
|
// config->use_frozen_modules is initialized later
|
||||||
// by _PyConfig_InitImportConfig().
|
// by _PyConfig_InitImportConfig().
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -789,14 +790,11 @@ _PyConfig_InitCompatConfig(PyConfig *config)
|
||||||
config->use_frozen_modules = 1;
|
config->use_frozen_modules = 1;
|
||||||
#endif
|
#endif
|
||||||
config->safe_path = 0;
|
config->safe_path = 0;
|
||||||
|
config->int_max_str_digits = -1;
|
||||||
config->_is_python_build = 0;
|
config->_is_python_build = 0;
|
||||||
config->code_debug_ranges = 1;
|
config->code_debug_ranges = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Excluded from public struct PyConfig for backporting reasons. */
|
|
||||||
/* default to unconfigured, _PyLong_InitTypes() does the rest */
|
|
||||||
int _Py_global_config_int_max_str_digits = -1;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
config_init_defaults(PyConfig *config)
|
config_init_defaults(PyConfig *config)
|
||||||
|
@ -849,6 +847,7 @@ PyConfig_InitIsolatedConfig(PyConfig *config)
|
||||||
config->faulthandler = 0;
|
config->faulthandler = 0;
|
||||||
config->tracemalloc = 0;
|
config->tracemalloc = 0;
|
||||||
config->perf_profiling = 0;
|
config->perf_profiling = 0;
|
||||||
|
config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
|
||||||
config->safe_path = 1;
|
config->safe_path = 1;
|
||||||
config->pathconfig_warnings = 0;
|
config->pathconfig_warnings = 0;
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -1021,6 +1020,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2)
|
||||||
COPY_ATTR(safe_path);
|
COPY_ATTR(safe_path);
|
||||||
COPY_WSTRLIST(orig_argv);
|
COPY_WSTRLIST(orig_argv);
|
||||||
COPY_ATTR(_is_python_build);
|
COPY_ATTR(_is_python_build);
|
||||||
|
COPY_ATTR(int_max_str_digits);
|
||||||
|
|
||||||
#undef COPY_ATTR
|
#undef COPY_ATTR
|
||||||
#undef COPY_WSTR_ATTR
|
#undef COPY_WSTR_ATTR
|
||||||
|
@ -1128,6 +1128,7 @@ _PyConfig_AsDict(const PyConfig *config)
|
||||||
SET_ITEM_INT(use_frozen_modules);
|
SET_ITEM_INT(use_frozen_modules);
|
||||||
SET_ITEM_INT(safe_path);
|
SET_ITEM_INT(safe_path);
|
||||||
SET_ITEM_INT(_is_python_build);
|
SET_ITEM_INT(_is_python_build);
|
||||||
|
SET_ITEM_INT(int_max_str_digits);
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
|
|
||||||
|
@ -1317,6 +1318,12 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict)
|
||||||
} \
|
} \
|
||||||
CHECK_VALUE(#KEY, config->KEY >= 0); \
|
CHECK_VALUE(#KEY, config->KEY >= 0); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
#define GET_INT(KEY) \
|
||||||
|
do { \
|
||||||
|
if (config_dict_get_int(dict, #KEY, &config->KEY) < 0) { \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
#define GET_WSTR(KEY) \
|
#define GET_WSTR(KEY) \
|
||||||
do { \
|
do { \
|
||||||
if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \
|
if (config_dict_get_wstr(dict, #KEY, config, &config->KEY) < 0) { \
|
||||||
|
@ -1415,9 +1422,11 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict)
|
||||||
GET_UINT(use_frozen_modules);
|
GET_UINT(use_frozen_modules);
|
||||||
GET_UINT(safe_path);
|
GET_UINT(safe_path);
|
||||||
GET_UINT(_is_python_build);
|
GET_UINT(_is_python_build);
|
||||||
|
GET_INT(int_max_str_digits);
|
||||||
|
|
||||||
#undef CHECK_VALUE
|
#undef CHECK_VALUE
|
||||||
#undef GET_UINT
|
#undef GET_UINT
|
||||||
|
#undef GET_INT
|
||||||
#undef GET_WSTR
|
#undef GET_WSTR
|
||||||
#undef GET_WSTR_OPT
|
#undef GET_WSTR_OPT
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1782,7 +1791,7 @@ config_init_int_max_str_digits(PyConfig *config)
|
||||||
|
|
||||||
const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS");
|
const char *env = config_get_env(config, "PYTHONINTMAXSTRDIGITS");
|
||||||
if (env) {
|
if (env) {
|
||||||
int valid = 0;
|
bool valid = 0;
|
||||||
if (!_Py_str_to_int(env, &maxdigits)) {
|
if (!_Py_str_to_int(env, &maxdigits)) {
|
||||||
valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
|
valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
|
||||||
}
|
}
|
||||||
|
@ -1794,13 +1803,13 @@ config_init_int_max_str_digits(PyConfig *config)
|
||||||
STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
|
STRINGIFY(_PY_LONG_MAX_STR_DIGITS_THRESHOLD)
|
||||||
" or 0 for unlimited.");
|
" or 0 for unlimited.");
|
||||||
}
|
}
|
||||||
_Py_global_config_int_max_str_digits = maxdigits;
|
config->int_max_str_digits = maxdigits;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits");
|
const wchar_t *xoption = config_get_xoption(config, L"int_max_str_digits");
|
||||||
if (xoption) {
|
if (xoption) {
|
||||||
const wchar_t *sep = wcschr(xoption, L'=');
|
const wchar_t *sep = wcschr(xoption, L'=');
|
||||||
int valid = 0;
|
bool valid = 0;
|
||||||
if (sep) {
|
if (sep) {
|
||||||
if (!config_wstr_to_int(sep + 1, &maxdigits)) {
|
if (!config_wstr_to_int(sep + 1, &maxdigits)) {
|
||||||
valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
|
valid = ((maxdigits == 0) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD));
|
||||||
|
@ -1814,7 +1823,10 @@ config_init_int_max_str_digits(PyConfig *config)
|
||||||
#undef _STRINGIFY
|
#undef _STRINGIFY
|
||||||
#undef STRINGIFY
|
#undef STRINGIFY
|
||||||
}
|
}
|
||||||
_Py_global_config_int_max_str_digits = maxdigits;
|
config->int_max_str_digits = maxdigits;
|
||||||
|
}
|
||||||
|
if (config->int_max_str_digits < 0) {
|
||||||
|
config->int_max_str_digits = _PY_LONG_DEFAULT_MAX_STR_DIGITS;
|
||||||
}
|
}
|
||||||
return _PyStatus_OK();
|
return _PyStatus_OK();
|
||||||
}
|
}
|
||||||
|
@ -1882,7 +1894,7 @@ config_read_complex_options(PyConfig *config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_Py_global_config_int_max_str_digits < 0) {
|
if (config->int_max_str_digits < 0) {
|
||||||
status = config_init_int_max_str_digits(config);
|
status = config_init_int_max_str_digits(config);
|
||||||
if (_PyStatus_EXCEPTION(status)) {
|
if (_PyStatus_EXCEPTION(status)) {
|
||||||
return status;
|
return status;
|
||||||
|
|
|
@ -1717,7 +1717,7 @@ sys_get_int_max_str_digits_impl(PyObject *module)
|
||||||
/*[clinic end generated code: output=0042f5e8ae0e8631 input=8dab13e2023e60d5]*/
|
/*[clinic end generated code: output=0042f5e8ae0e8631 input=8dab13e2023e60d5]*/
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _PyInterpreterState_GET();
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
||||||
return PyLong_FromSsize_t(interp->int_max_str_digits);
|
return PyLong_FromLong(interp->config.int_max_str_digits);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*[clinic input]
|
/*[clinic input]
|
||||||
|
@ -1734,7 +1734,7 @@ sys_set_int_max_str_digits_impl(PyObject *module, int maxdigits)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
if ((!maxdigits) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) {
|
if ((!maxdigits) || (maxdigits >= _PY_LONG_MAX_STR_DIGITS_THRESHOLD)) {
|
||||||
tstate->interp->int_max_str_digits = maxdigits;
|
tstate->interp->config.int_max_str_digits = maxdigits;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
} else {
|
} else {
|
||||||
PyErr_Format(
|
PyErr_Format(
|
||||||
|
@ -2810,7 +2810,7 @@ set_flags_from_config(PyInterpreterState *interp, PyObject *flags)
|
||||||
SetFlag(preconfig->utf8_mode);
|
SetFlag(preconfig->utf8_mode);
|
||||||
SetFlag(config->warn_default_encoding);
|
SetFlag(config->warn_default_encoding);
|
||||||
SetFlagObj(PyBool_FromLong(config->safe_path));
|
SetFlagObj(PyBool_FromLong(config->safe_path));
|
||||||
SetFlag(_Py_global_config_int_max_str_digits);
|
SetFlag(config->int_max_str_digits);
|
||||||
#undef SetFlagObj
|
#undef SetFlagObj
|
||||||
#undef SetFlag
|
#undef SetFlag
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue