From 1f5a6565e009eaaa79e458ba37a6cee2b53756d0 Mon Sep 17 00:00:00 2001 From: Nikita Sobolev Date: Sun, 16 Oct 2022 07:18:59 +0300 Subject: [PATCH] [3.11] gh-94808: Cover `PyFunction_GetCode`, `PyFunction_GetGlobals`, `PyFunction_GetModule` (GH-98158). (cherry picked from commit 7b48d02933639c91ebd957b2326d8c352d8eddec) Co-authored-by: Nikita Sobolev --- Lib/test/test_capi.py | 35 ++++++++++++++++++++++++++++++++++ Modules/_testcapimodule.c | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py index 6e56016a47cc0a..d5012a76a600f1 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -739,6 +739,41 @@ def method_example(self): ... self.assertEqual(_testcapi.eval_get_func_name(sum), "sum") # c function self.assertEqual(_testcapi.eval_get_func_name(A), "type") + def test_function_get_code(self): + import types + + def some(): + pass + + code = _testcapi.function_get_code(some) + self.assertIsInstance(code, types.CodeType) + self.assertEqual(code, some.__code__) + + with self.assertRaises(SystemError): + _testcapi.function_get_code(None) # not a function + + def test_function_get_globals(self): + def some(): + pass + + globals_ = _testcapi.function_get_globals(some) + self.assertIsInstance(globals_, dict) + self.assertEqual(globals_, some.__globals__) + + with self.assertRaises(SystemError): + _testcapi.function_get_globals(None) # not a function + + def test_function_get_module(self): + def some(): + pass + + module = _testcapi.function_get_module(some) + self.assertIsInstance(module, str) + self.assertEqual(module, some.__module__) + + with self.assertRaises(SystemError): + _testcapi.function_get_module(None) # not a function + class TestPendingCalls(unittest.TestCase): diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 69703be186d11f..bab8d6027cfe28 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -6081,6 +6081,43 @@ settrace_to_record(PyObject *self, PyObject *list) } static PyObject *negative_dictoffset(PyObject *, PyObject *); + +static PyObject * +function_get_code(PyObject *self, PyObject *func) +{ + PyObject *code = PyFunction_GetCode(func); + if (code != NULL) { + Py_INCREF(code); + return code; + } else { + return NULL; + } +} + +static PyObject * +function_get_globals(PyObject *self, PyObject *func) +{ + PyObject *globals = PyFunction_GetGlobals(func); + if (globals != NULL) { + Py_INCREF(globals); + return globals; + } else { + return NULL; + } +} + +static PyObject * +function_get_module(PyObject *self, PyObject *func) +{ + PyObject *module = PyFunction_GetModule(func); + if (module != NULL) { + Py_INCREF(module); + return module; + } else { + return NULL; + } +} + static PyObject *test_buildvalue_issue38913(PyObject *, PyObject *); static PyObject *getargs_s_hash_int(PyObject *, PyObject *, PyObject*); static PyObject *getargs_s_hash_int2(PyObject *, PyObject *, PyObject*); @@ -6382,6 +6419,9 @@ static PyMethodDef TestMethods[] = { {"get_feature_macros", get_feature_macros, METH_NOARGS, NULL}, {"test_code_api", test_code_api, METH_NOARGS, NULL}, {"settrace_to_record", settrace_to_record, METH_O, NULL}, + {"function_get_code", function_get_code, METH_O, NULL}, + {"function_get_globals", function_get_globals, METH_O, NULL}, + {"function_get_module", function_get_module, METH_O, NULL}, {NULL, NULL} /* sentinel */ };