Visitar URL original
gh-98417: Stop modifying PyConfig in sys.set_int_max_str_digits() · gpshead/cpython@3b1997a · GitHub
Skip to content

Commit 3b1997a

Browse files
committed
pythongh-98417: Stop modifying PyConfig in sys.set_int_max_str_digits()
PyConfig is an input to interpreter initialization; the copy stored on PyInterpreterState records how the interpreter was initialized and must be treated as read-only afterwards. The runtime int<->str digit limit already lives in PyInterpreterState.long_state.max_str_digits and that is what all readers use, so drop the write-back into interp->config.int_max_str_digits from _PySys_SetIntMaxStrDigits(). As a consequence, interpreters created after a runtime limit change now start from the initially-configured limit instead of inheriting the current runtime value, restoring the Python 3.11 behavior. Also document the read-only-after-init constraint on the PyConfig declaration itself, per discussion on the issue. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UTM742RWwqsDkF5JGSsGWX
1 parent 384abb7 commit 3b1997a

4 files changed

Lines changed: 35 additions & 4 deletions

File tree

‎Include/cpython/initconfig.h‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,16 @@ PyAPI_FUNC(void) PyPreConfig_InitIsolatedConfig(PyPreConfig *config);
129129

130130
/* --- PyConfig ---------------------------------------------- */
131131

132-
/* This structure is best documented in the Doc/c-api/init_config.rst file. */
132+
/* This structure is best documented in the Doc/c-api/init_config.rst file.
133+
134+
PyConfig is an *input* to interpreter initialization. The copy kept
135+
on the interpreter state records how the interpreter was initialized.
136+
Do not use it to store mutable runtime state: a setting that can
137+
change at runtime belongs on the interpreter state itself, as is done
138+
for int_max_str_digits (gh-98417). Note that PyConfig_Set() still
139+
writes some members of the interpreter's copy; no new post-init
140+
writes should be added. Use the PyConfig_Get()/PyConfig_Set() API to
141+
access settings at runtime. */
133142
typedef struct PyConfig {
134143
int _config_init; /* _PyConfigInitEnum value */
135144

‎Lib/test/test_int.py‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,24 @@ def test_int_max_str_digits_is_per_interpreter(self):
732732
after_value = sys.get_int_max_str_digits()
733733
self.assertEqual(before_value, after_value)
734734

735+
def test_int_max_str_digits_not_inherited_by_subinterpreter(self):
736+
# gh-98417: sys.set_int_max_str_digits() changes runtime state
737+
# only; it must not be written back into the interpreter's
738+
# initialization config. Interpreters created afterwards start
739+
# from the initial config, not the current runtime value.
740+
sentinel = 99_999
741+
if sys.get_int_max_str_digits() == sentinel:
742+
sentinel = 88_888
743+
code = f"""if 1:
744+
import sys
745+
if sys.get_int_max_str_digits() == {sentinel}:
746+
raise AssertionError(
747+
'subinterpreter inherited a runtime limit change')
748+
"""
749+
with support.adjust_int_max_str_digits(sentinel):
750+
self.assertEqual(support.run_in_subinterp(code), 0,
751+
'subinterp code failure, check stderr.')
752+
735753

736754
class IntSubclassStrDigitLimitsTests(IntStrDigitLimitsTests):
737755
int_class = IntSubclass
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
:func:`sys.set_int_max_str_digits` no longer writes the new limit back into
2+
the interpreter's initialization configuration (:c:type:`PyConfig`); the
3+
runtime limit is stored only on the interpreter state and the configuration
4+
is treated as read-only after initialization. As a consequence,
5+
interpreters created after changing the limit at runtime now start with the
6+
initial configured limit rather than inheriting the runtime value, matching
7+
the behavior of Python 3.11 and earlier.

‎Python/sysmodule.c‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4701,10 +4701,7 @@ _PySys_SetIntMaxStrDigits(int maxdigits)
47014701
return -1;
47024702
}
47034703

4704-
// Set PyInterpreterState.long_state.max_str_digits
4705-
// and PyInterpreterState.config.int_max_str_digits.
47064704
PyInterpreterState *interp = _PyInterpreterState_GET();
47074705
_Py_atomic_store_int(&interp->long_state.max_str_digits, maxdigits);
4708-
_Py_atomic_store_int(&interp->config.int_max_str_digits, maxdigits);
47094706
return 0;
47104707
}

0 commit comments

Comments
 (0)