};
-/* WASI has limited call stack. Python's recursion limit depends on code
- layout, optimization, and WASI runtime. Wasmtime can handle about 700
- recursions, sometimes less. 500 is a more conservative limit. */
-#ifndef C_RECURSION_LIMIT
-# ifdef __wasi__
-# define C_RECURSION_LIMIT 500
-# else
- // This value is duplicated in Lib/test/support/__init__.py
-# define C_RECURSION_LIMIT 1500
-# endif
+#ifdef __wasi__
+ // WASI has limited call stack. Python's recursion limit depends on code
+ // layout, optimization, and WASI runtime. Wasmtime can handle about 700
+ // recursions, sometimes less. 500 is a more conservative limit.
+# define Py_C_RECURSION_LIMIT 500
+#else
+ // This value is duplicated in Lib/test/support/__init__.py
+# define Py_C_RECURSION_LIMIT 1500
#endif
+
/* other API */
/* Similar to PyThreadState_Get(), but don't issue a fatal error
from functools import cmp_to_key
from test import seq_tests
-from test.support import ALWAYS_EQ, NEVER_EQ, C_RECURSION_LIMIT
+from test.support import ALWAYS_EQ, NEVER_EQ, Py_C_RECURSION_LIMIT
class CommonTest(seq_tests.CommonTest):
def test_repr_deep(self):
a = self.type2test([])
- for i in range(C_RECURSION_LIMIT + 1):
+ for i in range(Py_C_RECURSION_LIMIT + 1):
a = self.type2test([a])
self.assertRaises(RecursionError, repr, a)
import unittest
import collections
import sys
-from test.support import C_RECURSION_LIMIT
+from test.support import Py_C_RECURSION_LIMIT
class BasicTestMappingProtocol(unittest.TestCase):
def test_repr_deep(self):
d = self._empty_mapping()
- for i in range(C_RECURSION_LIMIT + 1):
+ for i in range(Py_C_RECURSION_LIMIT + 1):
d0 = d
d = self._empty_mapping()
d[1] = d0
def collect_testcapi(info_add):
+ try:
+ import _testcapi
+ except ImportError:
+ return
+
+ for name in (
+ 'LONG_MAX', # always 32-bit on Windows, 64-bit on 64-bit Unix
+ 'PY_SSIZE_T_MAX',
+ 'Py_C_RECURSION_LIMIT',
+ 'SIZEOF_TIME_T', # 32-bit or 64-bit depending on the platform
+ 'SIZEOF_WCHAR_T', # 16-bit or 32-bit depending on the platform
+ ):
+ copy_attr(info_add, f'_testcapi.{name}', _testcapi, name)
+
+
+def collect_testinternalcapi(info_add):
try:
import _testinternalcapi
except ImportError:
call_func(info_add, 'pymem.allocator', _testinternalcapi, 'pymem_getallocatorsname')
+ for name in (
+ 'SIZEOF_PYGC_HEAD',
+ 'SIZEOF_PYOBJECT',
+ ):
+ copy_attr(info_add, f'_testinternalcapi.{name}', _testinternalcapi, name)
+
def collect_resource(info_add):
try:
collect_sys,
collect_sysconfig,
collect_testcapi,
+ collect_testinternalcapi,
collect_time,
collect_tkinter,
collect_windows,
"run_with_tz", "PGO", "missing_compiler_executable",
"ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST",
"LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT",
- "Py_DEBUG", "EXCEEDS_RECURSION_LIMIT", "C_RECURSION_LIMIT",
+ "Py_DEBUG", "EXCEEDS_RECURSION_LIMIT", "Py_C_RECURSION_LIMIT",
"skip_on_s390x",
]
EXCEEDS_RECURSION_LIMIT = 5000
# The default C recursion limit (from Include/cpython/pystate.h).
-C_RECURSION_LIMIT = 1500
+Py_C_RECURSION_LIMIT = 1500
#Windows doesn't have os.uname() but it doesn't support s390x.
skip_on_s390x = unittest.skipIf(hasattr(os, 'uname') and os.uname().machine == 's390x',
import warnings
from test import support
from test.support import (script_helper, requires_debug_ranges,
- requires_specialization, C_RECURSION_LIMIT)
+ requires_specialization, Py_C_RECURSION_LIMIT)
from test.support.os_helper import FakePath
class TestSpecifics(unittest.TestCase):
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
def test_extended_arg(self):
- repeat = int(C_RECURSION_LIMIT * 0.9)
+ repeat = int(Py_C_RECURSION_LIMIT * 0.9)
longexpr = 'x = x or ' + '-x' * repeat
g = {}
code = textwrap.dedent('''
@support.cpython_only
@unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI")
def test_compiler_recursion_limit(self):
- # Expected limit is C_RECURSION_LIMIT * 2
+ # Expected limit is Py_C_RECURSION_LIMIT * 2
# Duplicating the limit here is a little ugly.
# Perhaps it should be exposed somewhere...
- fail_depth = C_RECURSION_LIMIT * 2 + 1
- crash_depth = C_RECURSION_LIMIT * 100
- success_depth = int(C_RECURSION_LIMIT * 1.8)
+ fail_depth = Py_C_RECURSION_LIMIT * 2 + 1
+ crash_depth = Py_C_RECURSION_LIMIT * 100
+ success_depth = int(Py_C_RECURSION_LIMIT * 1.8)
def check_limit(prefix, repeated, mode="single"):
expect_ok = prefix + repeated * success_depth
import unittest
import weakref
from test import support
-from test.support import import_helper, C_RECURSION_LIMIT
+from test.support import import_helper, Py_C_RECURSION_LIMIT
class DictTest(unittest.TestCase):
def test_repr_deep(self):
d = {}
- for i in range(C_RECURSION_LIMIT + 1):
+ for i in range(Py_C_RECURSION_LIMIT + 1):
d = {1: d}
self.assertRaises(RecursionError, repr, d)
import pickle
import sys
import unittest
-from test.support import C_RECURSION_LIMIT
+from test.support import Py_C_RECURSION_LIMIT
class DictSetTest(unittest.TestCase):
def test_deeply_nested_repr(self):
d = {}
- for i in range(C_RECURSION_LIMIT//2 + 100):
+ for i in range(Py_C_RECURSION_LIMIT//2 + 100):
d = {42: d.values()}
self.assertRaises(RecursionError, repr, d)
import collections.abc
import types
import unittest
-from test.support import C_RECURSION_LIMIT
+from test.support import Py_C_RECURSION_LIMIT
class TestExceptionGroupTypeHierarchy(unittest.TestCase):
def test_exception_group_types(self):
class DeepRecursionInSplitAndSubgroup(unittest.TestCase):
def make_deep_eg(self):
e = TypeError(1)
- for i in range(C_RECURSION_LIMIT + 1):
+ for i in range(Py_C_RECURSION_LIMIT + 1):
e = ExceptionGroup('eg', [e])
return e
PyModule_AddObject(m, "instancemethod", (PyObject *)&PyInstanceMethod_Type);
PyModule_AddIntConstant(m, "the_number_three", 3);
+ PyModule_AddIntMacro(m, Py_C_RECURSION_LIMIT);
TestError = PyErr_NewException("_testcapi.error", NULL, NULL);
Py_INCREF(TestError);
return 1;
}
+ if (PyModule_Add(module, "SIZEOF_PYOBJECT",
+ PyLong_FromSsize_t(sizeof(PyObject))) < 0) {
+ return 1;
+ }
+
if (PyModule_Add(module, "SIZEOF_TIME_T",
PyLong_FromSsize_t(sizeof(time_t))) < 0) {
return 1;
if (!tstate) {
return 0;
}
- state->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
- int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
+ state->recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
+ int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
state->recursion_depth = starting_recursion_depth;
if (!tstate) {
return 0;
}
- state->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
- int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
+ state->recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
+ int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
state->recursion_depth = starting_recursion_depth;
return 0;
}
/* Be careful here to prevent overflow. */
- int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
+ int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
state.recursion_depth = starting_recursion_depth;
- state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
+ state.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
switch (mod->kind) {
case Module_kind:
return 0;
}
/* Be careful here to prevent overflow. */
- int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
+ int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
state.recursion_depth = starting_recursion_depth;
- state.recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
+ state.recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
int ret = astfold_mod(mod, arena, &state);
assert(ret || PyErr_Occurred());
tstate->py_recursion_limit = interp->ceval.recursion_limit,
tstate->py_recursion_remaining = interp->ceval.recursion_limit,
- tstate->c_recursion_remaining = C_RECURSION_LIMIT;
+ tstate->c_recursion_remaining = Py_C_RECURSION_LIMIT;
tstate->exc_info = &tstate->exc_state;
return NULL;
}
/* Be careful here to prevent overflow. */
- int recursion_depth = C_RECURSION_LIMIT - tstate->c_recursion_remaining;
+ int recursion_depth = Py_C_RECURSION_LIMIT - tstate->c_recursion_remaining;
starting_recursion_depth = recursion_depth * COMPILER_STACK_FRAME_SCALE;
st->recursion_depth = starting_recursion_depth;
- st->recursion_limit = C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
+ st->recursion_limit = Py_C_RECURSION_LIMIT * COMPILER_STACK_FRAME_SCALE;
/* Make the initial symbol information gathering pass */
if (!symtable_enter_block(st, &_Py_ID(top), ModuleBlock, (void *)mod, 0, 0, 0, 0)) {