summaryrefslogtreecommitdiffstats
path: root/Lib/test/support
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2023-09-06 15:34:31 (GMT)
committerGitHub <noreply@github.com>2023-09-06 15:34:31 (GMT)
commit8ff11425783806f8cb78e99f667546b1f7f3428e (patch)
tree0c4d2006d833d74a59a809fd2447fc6a91ceabd7 /Lib/test/support
parent2cd170db40ffba357848672ff3d2f8c1e0e74f2c (diff)
downloadcpython-8ff11425783806f8cb78e99f667546b1f7f3428e.zip
cpython-8ff11425783806f8cb78e99f667546b1f7f3428e.tar.gz
cpython-8ff11425783806f8cb78e99f667546b1f7f3428e.tar.bz2
gh-108851: Fix tomllib recursion tests (#108853)
* Add get_recursion_available() and get_recursion_depth() functions to the test.support module. * Change infinite_recursion() default max_depth from 75 to 100. * Fix test_tomllib recursion tests for WASI buildbots: reduce the recursion limit and compute the maximum nested array/dict depending on the current available recursion limit. * test.pythoninfo logs sys.getrecursionlimit(). * Enhance test_sys tests on sys.getrecursionlimit() and sys.setrecursionlimit().
Diffstat (limited to 'Lib/test/support')
-rw-r--r--Lib/test/support/__init__.py43
1 files changed, 40 insertions, 3 deletions
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 7bac116..d39f529 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -2241,6 +2241,39 @@ def check_disallow_instantiation(testcase, tp, *args, **kwds):
msg = f"cannot create '{re.escape(qualname)}' instances"
testcase.assertRaisesRegex(TypeError, msg, tp, *args, **kwds)
+def get_recursion_depth():
+ """Get the recursion depth of the caller function.
+
+ In the __main__ module, at the module level, it should be 1.
+ """
+ try:
+ import _testinternalcapi
+ depth = _testinternalcapi.get_recursion_depth()
+ except (ImportError, RecursionError) as exc:
+ # sys._getframe() + frame.f_back implementation.
+ try:
+ depth = 0
+ frame = sys._getframe()
+ while frame is not None:
+ depth += 1
+ frame = frame.f_back
+ finally:
+ # Break any reference cycles.
+ frame = None
+
+ # Ignore get_recursion_depth() frame.
+ return max(depth - 1, 1)
+
+def get_recursion_available():
+ """Get the number of available frames before RecursionError.
+
+ It depends on the current recursion depth of the caller function and
+ sys.getrecursionlimit().
+ """
+ limit = sys.getrecursionlimit()
+ depth = get_recursion_depth()
+ return limit - depth
+
@contextlib.contextmanager
def set_recursion_limit(limit):
"""Temporarily change the recursion limit."""
@@ -2251,14 +2284,18 @@ def set_recursion_limit(limit):
finally:
sys.setrecursionlimit(original_limit)
-def infinite_recursion(max_depth=75):
+def infinite_recursion(max_depth=100):
"""Set a lower limit for tests that interact with infinite recursions
(e.g test_ast.ASTHelpers_Test.test_recursion_direct) since on some
debug windows builds, due to not enough functions being inlined the
stack size might not handle the default recursion limit (1000). See
bpo-11105 for details."""
- return set_recursion_limit(max_depth)
-
+ if max_depth < 3:
+ raise ValueError("max_depth must be at least 3, got {max_depth}")
+ depth = get_recursion_depth()
+ depth = max(depth - 1, 1) # Ignore infinite_recursion() frame.
+ limit = depth + max_depth
+ return set_recursion_limit(limit)
def ignore_deprecations_from(module: str, *, like: str) -> object:
token = object()