https://github.com/python/cpython/commit/fceb8c31ddf8db2fddd92c8c6437094081c91ac8
commit: fceb8c31ddf8db2fddd92c8c6437094081c91ac8
branch: 3.12
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2025-01-19T13:51:53Z
summary:

[3.12] gh-111495: Add more tests on PyEval C APIs (#122789) (#128987) (#129023)

* Add Lib/test/test_capi/test_eval.py
* Add Modules/_testlimitedcapi/eval.c

(cherry picked from commit bf8b3746398ea756c97e3cf263d63ca3ce3a544e)

* gh-111495: Fix refleaks in test_capi.test_eval tests (#122851)

(cherry picked from commit b4a316087c32d83e375087fd35fc511bc430ee8b)
(cherry picked from commit 430ccbc009aa7a2da92b85d7aeadd39e1666e875)

files:
A Lib/test/test_capi/test_eval.py
A Modules/_testcapi/eval.c
M Lib/test/test_capi/test_misc.py
M Modules/Setup.stdlib.in
M Modules/_testcapi/parts.h
M Modules/_testcapimodule.c
M PCbuild/_testcapi.vcxproj
M PCbuild/_testcapi.vcxproj.filters

diff --git a/Lib/test/test_capi/test_eval.py b/Lib/test/test_capi/test_eval.py
new file mode 100644
index 00000000000000..1fedf2f2b4b23b
--- /dev/null
+++ b/Lib/test/test_capi/test_eval.py
@@ -0,0 +1,88 @@
+import sys
+import unittest
+from test.support import import_helper
+
+_testcapi = import_helper.import_module('_testcapi')
+
+
+class Tests(unittest.TestCase):
+    def test_eval_get_func_name(self):
+        eval_get_func_name = _testcapi.eval_get_func_name
+
+        def function_example(): ...
+
+        class A:
+            def method_example(self): ...
+
+        self.assertEqual(eval_get_func_name(function_example),
+                         "function_example")
+        self.assertEqual(eval_get_func_name(A.method_example),
+                         "method_example")
+        self.assertEqual(eval_get_func_name(A().method_example),
+                         "method_example")
+        self.assertEqual(eval_get_func_name(sum), "sum")  # c function
+        self.assertEqual(eval_get_func_name(A), "type")
+
+    def test_eval_get_func_desc(self):
+        eval_get_func_desc = _testcapi.eval_get_func_desc
+
+        def function_example(): ...
+
+        class A:
+            def method_example(self): ...
+
+        self.assertEqual(eval_get_func_desc(function_example),
+                         "()")
+        self.assertEqual(eval_get_func_desc(A.method_example),
+                         "()")
+        self.assertEqual(eval_get_func_desc(A().method_example),
+                         "()")
+        self.assertEqual(eval_get_func_desc(sum), "()")  # c function
+        self.assertEqual(eval_get_func_desc(A), " object")
+
+    def test_eval_getlocals(self):
+        # Test PyEval_GetLocals()
+        x = 1
+        self.assertEqual(_testcapi.eval_getlocals(),
+            {'self': self,
+             'x': 1})
+
+        y = 2
+        self.assertEqual(_testcapi.eval_getlocals(),
+            {'self': self,
+             'x': 1,
+             'y': 2})
+
+    def test_eval_getglobals(self):
+        # Test PyEval_GetGlobals()
+        self.assertEqual(_testcapi.eval_getglobals(),
+                         globals())
+
+    def test_eval_getbuiltins(self):
+        # Test PyEval_GetBuiltins()
+        self.assertEqual(_testcapi.eval_getbuiltins(),
+                         globals()['__builtins__'])
+
+    def test_eval_getframe(self):
+        # Test PyEval_GetFrame()
+        self.assertEqual(_testcapi.eval_getframe(),
+                         sys._getframe())
+
+    def test_eval_get_recursion_limit(self):
+        # Test Py_GetRecursionLimit()
+        self.assertEqual(_testcapi.eval_get_recursion_limit(),
+                         sys.getrecursionlimit())
+
+    def test_eval_set_recursion_limit(self):
+        # Test Py_SetRecursionLimit()
+        old_limit = sys.getrecursionlimit()
+        try:
+            limit = old_limit + 123
+            _testcapi.eval_set_recursion_limit(limit)
+            self.assertEqual(sys.getrecursionlimit(), limit)
+        finally:
+            sys.setrecursionlimit(old_limit)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py
index 98c74a44e4cb27..f284e665d6fde0 100644
--- a/Lib/test/test_capi/test_misc.py
+++ b/Lib/test/test_capi/test_misc.py
@@ -879,36 +879,6 @@ def __init__(self):
         _testcapi.clear_managed_dict(c)
         self.assertEqual(c.__dict__, {})
 
-    def test_eval_get_func_name(self):
-        def function_example(): ...
-
-        class A:
-            def method_example(self): ...
-
-        self.assertEqual(_testcapi.eval_get_func_name(function_example),
-                         "function_example")
-        self.assertEqual(_testcapi.eval_get_func_name(A.method_example),
-                         "method_example")
-        self.assertEqual(_testcapi.eval_get_func_name(A().method_example),
-                         "method_example")
-        self.assertEqual(_testcapi.eval_get_func_name(sum), "sum")  # c 
function
-        self.assertEqual(_testcapi.eval_get_func_name(A), "type")
-
-    def test_eval_get_func_desc(self):
-        def function_example(): ...
-
-        class A:
-            def method_example(self): ...
-
-        self.assertEqual(_testcapi.eval_get_func_desc(function_example),
-                         "()")
-        self.assertEqual(_testcapi.eval_get_func_desc(A.method_example),
-                         "()")
-        self.assertEqual(_testcapi.eval_get_func_desc(A().method_example),
-                         "()")
-        self.assertEqual(_testcapi.eval_get_func_desc(sum), "()")  # c function
-        self.assertEqual(_testcapi.eval_get_func_desc(A), " object")
-
     def test_function_get_code(self):
         import types
 
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index d60afcf55dba4a..5e587dd3a5a397 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -168,7 +168,7 @@
 @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c 
_xxtestfuzz/fuzzer.c
 @MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
 @MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
-@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c 
_testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c 
_testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c 
_testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c 
_testcapi/pytime.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c 
_testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c 
_testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c 
_testcapi/code.c _testcapi/buffer.c _testcapi/pyos.c _testcapi/run.c 
_testcapi/file.c _testcapi/codec.c _testcapi/immortal.c 
_testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c _testcapi/import.c
+@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c 
_testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/abstract.c 
_testcapi/bytearray.c _testcapi/bytes.c _testcapi/unicode.c _testcapi/dict.c 
_testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c 
_testcapi/pytime.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c 
_testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c 
_testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c 
_testcapi/code.c _testcapi/buffer.c _testcapi/pyos.c _testcapi/run.c 
_testcapi/file.c _testcapi/codec.c _testcapi/immortal.c 
_testcapi/heaptype_relative.c _testcapi/gc.c _testcapi/sys.c _testcapi/import.c 
_testcapi/eval.c
 @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
 
 # Some testing modules MUST be built as shared libraries.
diff --git a/Modules/_testcapi/eval.c b/Modules/_testcapi/eval.c
new file mode 100644
index 00000000000000..581b5579178910
--- /dev/null
+++ b/Modules/_testcapi/eval.c
@@ -0,0 +1,74 @@
+#include "parts.h"
+#include "util.h"
+
+static PyObject *
+eval_get_func_name(PyObject *self, PyObject *func)
+{
+    return PyUnicode_FromString(PyEval_GetFuncName(func));
+}
+
+static PyObject *
+eval_get_func_desc(PyObject *self, PyObject *func)
+{
+    return PyUnicode_FromString(PyEval_GetFuncDesc(func));
+}
+
+static PyObject *
+eval_getlocals(PyObject *module, PyObject *Py_UNUSED(args))
+{
+    return Py_XNewRef(PyEval_GetLocals());
+}
+
+static PyObject *
+eval_getglobals(PyObject *module, PyObject *Py_UNUSED(args))
+{
+    return Py_XNewRef(PyEval_GetGlobals());
+}
+
+static PyObject *
+eval_getbuiltins(PyObject *module, PyObject *Py_UNUSED(args))
+{
+    return Py_XNewRef(PyEval_GetBuiltins());
+}
+
+static PyObject *
+eval_getframe(PyObject *module, PyObject *Py_UNUSED(args))
+{
+    return Py_XNewRef(PyEval_GetFrame());
+}
+
+static PyObject *
+eval_get_recursion_limit(PyObject *module, PyObject *Py_UNUSED(args))
+{
+    int limit = Py_GetRecursionLimit();
+    return PyLong_FromLong(limit);
+}
+
+static PyObject *
+eval_set_recursion_limit(PyObject *module, PyObject *args)
+{
+    int limit;
+    if (!PyArg_ParseTuple(args, "i", &limit)) {
+        return NULL;
+    }
+    Py_SetRecursionLimit(limit);
+    Py_RETURN_NONE;
+}
+
+static PyMethodDef test_methods[] = {
+    {"eval_get_func_name", eval_get_func_name, METH_O, NULL},
+    {"eval_get_func_desc", eval_get_func_desc, METH_O, NULL},
+    {"eval_getlocals", eval_getlocals, METH_NOARGS},
+    {"eval_getglobals", eval_getglobals, METH_NOARGS},
+    {"eval_getbuiltins", eval_getbuiltins, METH_NOARGS},
+    {"eval_getframe", eval_getframe, METH_NOARGS},
+    {"eval_get_recursion_limit", eval_get_recursion_limit, METH_NOARGS},
+    {"eval_set_recursion_limit", eval_set_recursion_limit, METH_VARARGS},
+    {NULL},
+};
+
+int
+_PyTestCapi_Init_Eval(PyObject *m)
+{
+    return PyModule_AddFunctions(m, test_methods);
+}
diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h
index bc348dc122c525..4ca46c800aa9eb 100644
--- a/Modules/_testcapi/parts.h
+++ b/Modules/_testcapi/parts.h
@@ -56,6 +56,7 @@ int _PyTestCapi_Init_Immortal(PyObject *module);
 int _PyTestCapi_Init_GC(PyObject *module);
 int _PyTestCapi_Init_Sys(PyObject *module);
 int _PyTestCapi_Init_Import(PyObject *module);
+int _PyTestCapi_Init_Eval(PyObject *module);
 
 #ifdef LIMITED_API_AVAILABLE
 int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 21d1228d79fe44..1fbeb58e3d404b 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -2797,18 +2797,6 @@ test_frame_getvarstring(PyObject *self, PyObject *args)
 }
 
 
-static PyObject *
-eval_get_func_name(PyObject *self, PyObject *func)
-{
-    return PyUnicode_FromString(PyEval_GetFuncName(func));
-}
-
-static PyObject *
-eval_get_func_desc(PyObject *self, PyObject *func)
-{
-    return PyUnicode_FromString(PyEval_GetFuncDesc(func));
-}
-
 static PyObject *
 gen_get_code(PyObject *self, PyObject *gen)
 {
@@ -3460,8 +3448,6 @@ static PyMethodDef TestMethods[] = {
     {"frame_new", frame_new, METH_VARARGS, NULL},
     {"frame_getvar", test_frame_getvar, METH_VARARGS, NULL},
     {"frame_getvarstring", test_frame_getvarstring, METH_VARARGS, NULL},
-    {"eval_get_func_name", eval_get_func_name, METH_O, NULL},
-    {"eval_get_func_desc", eval_get_func_desc, METH_O, NULL},
     {"gen_get_code", gen_get_code, METH_O, NULL},
     {"get_feature_macros", get_feature_macros, METH_NOARGS, NULL},
     {"test_code_api", test_code_api, METH_NOARGS, NULL},
@@ -4174,6 +4160,9 @@ PyInit__testcapi(void)
     if (_PyTestCapi_Init_Import(m) < 0) {
         return NULL;
     }
+    if (_PyTestCapi_Init_Eval(m) < 0) {
+        return NULL;
+    }
 
 #ifndef LIMITED_API_AVAILABLE
     PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);
diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj
index ec24c62903af90..06be7d291b17f3 100644
--- a/PCbuild/_testcapi.vcxproj
+++ b/PCbuild/_testcapi.vcxproj
@@ -128,6 +128,7 @@
     <ClCompile Include="..\Modules\_testcapi\immortal.c" />
     <ClCompile Include="..\Modules\_testcapi\gc.c" />
     <ClCompile Include="..\Modules\_testcapi\run.c" />
+    <ClCompile Include="..\Modules\_testcapi\eval.c" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\PC\python_nt.rc" />
diff --git a/PCbuild/_testcapi.vcxproj.filters 
b/PCbuild/_testcapi.vcxproj.filters
index 99eefb7b565393..309a016da2d587 100644
--- a/PCbuild/_testcapi.vcxproj.filters
+++ b/PCbuild/_testcapi.vcxproj.filters
@@ -111,6 +111,9 @@
     <ClCompile Include="..\Modules\_testcapi\import.c">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\Modules\_testcapi\eval.c">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="..\PC\python_nt.rc">

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to