Skip to content

gh-111495: Add more tests on PyEval C APIs #122789

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions Lib/test/test_capi/test_eval.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import sys
import unittest
from test.support import import_helper

_testlimitedcapi = import_helper.import_module('_testlimitedcapi')


class Tests(unittest.TestCase):
def test_eval_get_func_name(self):
eval_get_func_name = _testlimitedcapi.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 = _testlimitedcapi.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(_testlimitedcapi.eval_getlocals(),
{'self': self,
'x': 1})

y = 2
self.assertEqual(_testlimitedcapi.eval_getlocals(),
{'self': self,
'x': 1,
'y': 2})

def test_eval_getglobals(self):
# Test PyEval_GetGlobals()
self.assertEqual(_testlimitedcapi.eval_getglobals(),
globals())

def test_eval_getbuiltins(self):
# Test PyEval_GetBuiltins()
self.assertEqual(_testlimitedcapi.eval_getbuiltins(),
globals()['__builtins__'])

def test_eval_getframe(self):
# Test PyEval_GetFrame()
self.assertEqual(_testlimitedcapi.eval_getframe(),
sys._getframe())

def test_eval_getframe_builtins(self):
# Test PyEval_GetFrameBuiltins()
self.assertEqual(_testlimitedcapi.eval_getframe_builtins(),
sys._getframe().f_builtins)

def test_eval_getframe_globals(self):
# Test PyEval_GetFrameGlobals()
self.assertEqual(_testlimitedcapi.eval_getframe_globals(),
sys._getframe().f_globals)

def test_eval_getframe_locals(self):
# Test PyEval_GetFrameLocals()
self.assertEqual(_testlimitedcapi.eval_getframe_locals(),
sys._getframe().f_locals)

def test_eval_get_recursion_limit(self):
# Test Py_GetRecursionLimit()
self.assertEqual(_testlimitedcapi.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
_testlimitedcapi.eval_set_recursion_limit(limit)
self.assertEqual(sys.getrecursionlimit(), limit)
finally:
sys.setrecursionlimit(old_limit)


if __name__ == "__main__":
unittest.main()
43 changes: 0 additions & 43 deletions Lib/test/test_capi/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -869,36 +869,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

Expand Down Expand Up @@ -1157,19 +1127,6 @@ def genf(): yield
gen = genf()
self.assertEqual(_testcapi.gen_get_code(gen), gen.gi_code)

def test_pyeval_getlocals(self):
# Test PyEval_GetLocals()
x = 1
self.assertEqual(_testcapi.pyeval_getlocals(),
{'self': self,
'x': 1})

y = 2
self.assertEqual(_testcapi.pyeval_getlocals(),
{'self': self,
'x': 1,
'y': 2})


@requires_limited_api
class TestHeapTypeRelative(unittest.TestCase):
Expand Down
2 changes: 1 addition & 1 deletion Modules/Setup.stdlib.in
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.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/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/monitoring.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c

Expand Down
21 changes: 0 additions & 21 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2655,18 +2655,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)
{
Expand Down Expand Up @@ -3341,12 +3329,6 @@ test_critical_sections(PyObject *module, PyObject *Py_UNUSED(args))
Py_RETURN_NONE;
}

static PyObject *
pyeval_getlocals(PyObject *module, PyObject *Py_UNUSED(args))
{
return Py_XNewRef(PyEval_GetLocals());
}

static PyMethodDef TestMethods[] = {
{"set_errno", set_errno, METH_VARARGS},
{"test_config", test_config, METH_NOARGS},
Expand Down Expand Up @@ -3467,8 +3449,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},
Expand All @@ -3489,7 +3469,6 @@ static PyMethodDef TestMethods[] = {
{"test_weakref_capi", test_weakref_capi, METH_NOARGS},
{"function_set_warning", function_set_warning, METH_NOARGS},
{"test_critical_sections", test_critical_sections, METH_NOARGS},
{"pyeval_getlocals", pyeval_getlocals, METH_NOARGS},
{NULL, NULL} /* sentinel */
};

Expand Down
3 changes: 3 additions & 0 deletions Modules/_testlimitedcapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ PyInit__testlimitedcapi(void)
if (_PyTestLimitedCAPI_Init_Dict(mod) < 0) {
return NULL;
}
if (_PyTestLimitedCAPI_Init_Eval(mod) < 0) {
return NULL;
}
if (_PyTestLimitedCAPI_Init_Float(mod) < 0) {
return NULL;
}
Expand Down
95 changes: 95 additions & 0 deletions Modules/_testlimitedcapi/eval.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#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_getframe_builtins(PyObject *module, PyObject *Py_UNUSED(args))
{
return Py_XNewRef(PyEval_GetFrameBuiltins());
}

static PyObject *
eval_getframe_globals(PyObject *module, PyObject *Py_UNUSED(args))
{
return Py_XNewRef(PyEval_GetFrameGlobals());
}

static PyObject *
eval_getframe_locals(PyObject *module, PyObject *Py_UNUSED(args))
{
return Py_XNewRef(PyEval_GetFrameLocals());
}

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_getframe_builtins", eval_getframe_builtins, METH_NOARGS},
{"eval_getframe_globals", eval_getframe_globals, METH_NOARGS},
{"eval_getframe_locals", eval_getframe_locals, METH_NOARGS},
{"eval_get_recursion_limit", eval_get_recursion_limit, METH_NOARGS},
{"eval_set_recursion_limit", eval_set_recursion_limit, METH_VARARGS},
{NULL},
};

int
_PyTestLimitedCAPI_Init_Eval(PyObject *m)
{
return PyModule_AddFunctions(m, test_methods);
}
1 change: 1 addition & 0 deletions Modules/_testlimitedcapi/parts.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ int _PyTestLimitedCAPI_Init_ByteArray(PyObject *module);
int _PyTestLimitedCAPI_Init_Bytes(PyObject *module);
int _PyTestLimitedCAPI_Init_Complex(PyObject *module);
int _PyTestLimitedCAPI_Init_Dict(PyObject *module);
int _PyTestLimitedCAPI_Init_Eval(PyObject *module);
int _PyTestLimitedCAPI_Init_Float(PyObject *module);
int _PyTestLimitedCAPI_Init_HeaptypeRelative(PyObject *module);
int _PyTestLimitedCAPI_Init_Object(PyObject *module);
Expand Down
1 change: 1 addition & 0 deletions PCbuild/_testlimitedcapi.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
<ClCompile Include="..\Modules\_testlimitedcapi\bytes.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\complex.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\dict.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\eval.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\float.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\list.c" />
Expand Down
1 change: 1 addition & 0 deletions PCbuild/_testlimitedcapi.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<ClCompile Include="..\Modules\_testlimitedcapi\bytes.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\complex.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\dict.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\eval.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\float.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\heaptype_relative.c" />
<ClCompile Include="..\Modules\_testlimitedcapi\list.c" />
Expand Down
Loading