Skip to content

Commit b0edf3b

Browse files
authored
GH-91079: Rename C_RECURSION_LIMIT to Py_C_RECURSION_LIMIT (#108507)
Symbols of the C API should be prefixed by "Py_" to avoid conflict with existing names in 3rd party C extensions on "#include <Python.h>". test.pythoninfo now logs Py_C_RECURSION_LIMIT constant and other _testcapi and _testinternalcapi constants.
1 parent 15d4c9f commit b0edf3b

17 files changed

+67
-39
lines changed

Include/cpython/pystate.h

+9-10
Original file line numberDiff line numberDiff line change
@@ -194,18 +194,17 @@ struct _ts {
194194

195195
};
196196

197-
/* WASI has limited call stack. Python's recursion limit depends on code
198-
layout, optimization, and WASI runtime. Wasmtime can handle about 700
199-
recursions, sometimes less. 500 is a more conservative limit. */
200-
#ifndef C_RECURSION_LIMIT
201-
# ifdef __wasi__
202-
# define C_RECURSION_LIMIT 500
203-
# else
204-
// This value is duplicated in Lib/test/support/__init__.py
205-
# define C_RECURSION_LIMIT 1500
206-
# endif
197+
#ifdef __wasi__
198+
// WASI has limited call stack. Python's recursion limit depends on code
199+
// layout, optimization, and WASI runtime. Wasmtime can handle about 700
200+
// recursions, sometimes less. 500 is a more conservative limit.
201+
# define Py_C_RECURSION_LIMIT 500
202+
#else
203+
// This value is duplicated in Lib/test/support/__init__.py
204+
# define Py_C_RECURSION_LIMIT 1500
207205
#endif
208206

207+
209208
/* other API */
210209

211210
/* Similar to PyThreadState_Get(), but don't issue a fatal error

Lib/test/list_tests.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from functools import cmp_to_key
77

88
from test import seq_tests
9-
from test.support import ALWAYS_EQ, NEVER_EQ, C_RECURSION_LIMIT
9+
from test.support import ALWAYS_EQ, NEVER_EQ, Py_C_RECURSION_LIMIT
1010

1111

1212
class CommonTest(seq_tests.CommonTest):
@@ -61,7 +61,7 @@ def test_repr(self):
6161

6262
def test_repr_deep(self):
6363
a = self.type2test([])
64-
for i in range(C_RECURSION_LIMIT + 1):
64+
for i in range(Py_C_RECURSION_LIMIT + 1):
6565
a = self.type2test([a])
6666
self.assertRaises(RecursionError, repr, a)
6767

Lib/test/mapping_tests.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import unittest
33
import collections
44
import sys
5-
from test.support import C_RECURSION_LIMIT
5+
from test.support import Py_C_RECURSION_LIMIT
66

77

88
class BasicTestMappingProtocol(unittest.TestCase):
@@ -625,7 +625,7 @@ def __repr__(self):
625625

626626
def test_repr_deep(self):
627627
d = self._empty_mapping()
628-
for i in range(C_RECURSION_LIMIT + 1):
628+
for i in range(Py_C_RECURSION_LIMIT + 1):
629629
d0 = d
630630
d = self._empty_mapping()
631631
d[1] = d0

Lib/test/pythoninfo.py

+23
Original file line numberDiff line numberDiff line change
@@ -665,13 +665,35 @@ def collect_decimal(info_add):
665665

666666

667667
def collect_testcapi(info_add):
668+
try:
669+
import _testcapi
670+
except ImportError:
671+
return
672+
673+
for name in (
674+
'LONG_MAX', # always 32-bit on Windows, 64-bit on 64-bit Unix
675+
'PY_SSIZE_T_MAX',
676+
'Py_C_RECURSION_LIMIT',
677+
'SIZEOF_TIME_T', # 32-bit or 64-bit depending on the platform
678+
'SIZEOF_WCHAR_T', # 16-bit or 32-bit depending on the platform
679+
):
680+
copy_attr(info_add, f'_testcapi.{name}', _testcapi, name)
681+
682+
683+
def collect_testinternalcapi(info_add):
668684
try:
669685
import _testinternalcapi
670686
except ImportError:
671687
return
672688

673689
call_func(info_add, 'pymem.allocator', _testinternalcapi, 'pymem_getallocatorsname')
674690

691+
for name in (
692+
'SIZEOF_PYGC_HEAD',
693+
'SIZEOF_PYOBJECT',
694+
):
695+
copy_attr(info_add, f'_testinternalcapi.{name}', _testinternalcapi, name)
696+
675697

676698
def collect_resource(info_add):
677699
try:
@@ -907,6 +929,7 @@ def collect_info(info):
907929
collect_sys,
908930
collect_sysconfig,
909931
collect_testcapi,
932+
collect_testinternalcapi,
910933
collect_time,
911934
collect_tkinter,
912935
collect_windows,

Lib/test/support/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"run_with_tz", "PGO", "missing_compiler_executable",
6161
"ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST",
6262
"LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT",
63-
"Py_DEBUG", "EXCEEDS_RECURSION_LIMIT", "C_RECURSION_LIMIT",
63+
"Py_DEBUG", "EXCEEDS_RECURSION_LIMIT", "Py_C_RECURSION_LIMIT",
6464
"skip_on_s390x",
6565
]
6666

@@ -2531,7 +2531,7 @@ def adjust_int_max_str_digits(max_digits):
25312531
EXCEEDS_RECURSION_LIMIT = 5000
25322532

25332533
# The default C recursion limit (from Include/cpython/pystate.h).
2534-
C_RECURSION_LIMIT = 1500
2534+
Py_C_RECURSION_LIMIT = 1500
25352535

25362536
#Windows doesn't have os.uname() but it doesn't support s390x.
25372537
skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x',

Lib/test/test_compile.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import warnings
1212
from test import support
1313
from test.support import (script_helper, requires_debug_ranges,
14-
requires_specialization, C_RECURSION_LIMIT)
14+
requires_specialization, Py_C_RECURSION_LIMIT)
1515
from test.support.os_helper import FakePath
1616

1717
class TestSpecifics(unittest.TestCase):
@@ -111,7 +111,7 @@ def __getitem__(self, key):
111111

112112
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
113113
def test_extended_arg(self):
114-
repeat = int(C_RECURSION_LIMIT * 0.9)
114+
repeat = int(Py_C_RECURSION_LIMIT * 0.9)
115115
longexpr = 'x = x or ' + '-x' * repeat
116116
g = {}
117117
code = textwrap.dedent('''
@@ -557,12 +557,12 @@ def test_yet_more_evil_still_undecodable(self):
557557
@support.cpython_only
558558
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
559559
def test_compiler_recursion_limit(self):
560-
# Expected limit is C_RECURSION_LIMIT * 2
560+
# Expected limit is Py_C_RECURSION_LIMIT * 2
561561
# Duplicating the limit here is a little ugly.
562562
# Perhaps it should be exposed somewhere...
563-
fail_depth = C_RECURSION_LIMIT * 2 + 1
564-
crash_depth = C_RECURSION_LIMIT * 100
565-
success_depth = int(C_RECURSION_LIMIT * 1.8)
563+
fail_depth = Py_C_RECURSION_LIMIT * 2 + 1
564+
crash_depth = Py_C_RECURSION_LIMIT * 100
565+
success_depth = int(Py_C_RECURSION_LIMIT * 1.8)
566566

567567
def check_limit(prefix, repeated, mode="single"):
568568
expect_ok = prefix + repeated * success_depth

Lib/test/test_dict.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import unittest
99
import weakref
1010
from test import support
11-
from test.support import import_helper, C_RECURSION_LIMIT
11+
from test.support import import_helper, Py_C_RECURSION_LIMIT
1212

1313

1414
class DictTest(unittest.TestCase):
@@ -596,7 +596,7 @@ def __repr__(self):
596596

597597
def test_repr_deep(self):
598598
d = {}
599-
for i in range(C_RECURSION_LIMIT + 1):
599+
for i in range(Py_C_RECURSION_LIMIT + 1):
600600
d = {1: d}
601601
self.assertRaises(RecursionError, repr, d)
602602

Lib/test/test_dictviews.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pickle
44
import sys
55
import unittest
6-
from test.support import C_RECURSION_LIMIT
6+
from test.support import Py_C_RECURSION_LIMIT
77

88
class DictSetTest(unittest.TestCase):
99

@@ -280,7 +280,7 @@ def test_recursive_repr(self):
280280

281281
def test_deeply_nested_repr(self):
282282
d = {}
283-
for i in range(C_RECURSION_LIMIT//2 + 100):
283+
for i in range(Py_C_RECURSION_LIMIT//2 + 100):
284284
d = {42: d.values()}
285285
self.assertRaises(RecursionError, repr, d)
286286

Lib/test/test_exception_group.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import collections.abc
22
import types
33
import unittest
4-
from test.support import C_RECURSION_LIMIT
4+
from test.support import Py_C_RECURSION_LIMIT
55

66
class TestExceptionGroupTypeHierarchy(unittest.TestCase):
77
def test_exception_group_types(self):
@@ -460,7 +460,7 @@ def test_basics_split_by_predicate__match(self):
460460
class DeepRecursionInSplitAndSubgroup(unittest.TestCase):
461461
def make_deep_eg(self):
462462
e = TypeError(1)
463-
for i in range(C_RECURSION_LIMIT + 1):
463+
for i in range(Py_C_RECURSION_LIMIT + 1):
464464
e = ExceptionGroup('eg', [e])
465465
return e
466466

Modules/_testcapimodule.c

+1
Original file line numberDiff line numberDiff line change
@@ -3922,6 +3922,7 @@ PyInit__testcapi(void)
39223922
PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type);
39233923

39243924
PyModule_AddIntConstant(m, "the_number_three", 3);
3925+
PyModule_AddIntMacro(m, Py_C_RECURSION_LIMIT);
39253926

39263927
TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
39273928
Py_INCREF(TestError);

Modules/_testinternalcapi.c

+5
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,11 @@ module_exec(PyObject *module)
15521552
return 1;
15531553
}
15541554

1555+
if (PyModule_Add(module, "SIZEOF_PYOBJECT",
1556+
PyLong_FromSsize_t(sizeof(PyObject))) < 0) {
1557+
return 1;
1558+
}
1559+
15551560
if (PyModule_Add(module, "SIZEOF_TIME_T",
15561561
PyLong_FromSsize_t(sizeof(time_t))) < 0) {
15571562
return 1;

Parser/asdl_c.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1401,8 +1401,8 @@ class PartingShots(StaticVisitor):
14011401
if (!tstate) {
14021402
return 0;
14031403
}
1404-
state->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
1405-
int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
1404+
state->recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
1405+
int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
14061406
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
14071407
state->recursion_depth = starting_recursion_depth;
14081408

Python/Python-ast.c

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/ast.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1046,10 +1046,10 @@ _PyAST_Validate(mod_ty mod)
10461046
return 0;
10471047
}
10481048
/* Be careful here to prevent overflow. */
1049-
int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
1049+
int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
10501050
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
10511051
state.recursion_depth = starting_recursion_depth;
1052-
state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
1052+
state.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
10531053

10541054
switch (mod->kind) {
10551055
case Module_kind:

Python/ast_opt.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1130,10 +1130,10 @@ _PyAST_Optimize(mod_ty mod, PyArena *arena, int optimize, int ff_features)
11301130
return 0;
11311131
}
11321132
/* Be careful here to prevent overflow. */
1133-
int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
1133+
int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
11341134
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
11351135
state.recursion_depth = starting_recursion_depth;
1136-
state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
1136+
state.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
11371137

11381138
int ret = astfold_mod(mod, arena, &state);
11391139
assert(ret || PyErr_Occurred());

Python/pystate.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1334,7 +1334,7 @@ init_threadstate(PyThreadState *tstate,
13341334

13351335
tstate->py_recursion_limit = interp->ceval.recursion_limit,
13361336
tstate->py_recursion_remaining = interp->ceval.recursion_limit,
1337-
tstate->c_recursion_remaining = C_RECURSION_LIMIT;
1337+
tstate->c_recursion_remaining = Py_C_RECURSION_LIMIT;
13381338

13391339
tstate->exc_info = &tstate->exc_state;
13401340

Python/symtable.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -312,10 +312,10 @@ _PySymtable_Build(mod_ty mod, PyObject *filename, PyFutureFeatures *future)
312312
return NULL;
313313
}
314314
/* Be careful here to prevent overflow. */
315-
int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
315+
int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
316316
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
317317
st->recursion_depth = starting_recursion_depth;
318-
st->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
318+
st->recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
319319

320320
/* Make the initial symbol information gathering pass */
321321
if (!symtable_enter_block(st, &_Py_ID(top), ModuleBlock, (void *)mod, 0, 0, 0, 0)) {

0 commit comments

Comments
 (0)