diff --git a/Lib/test/test_capi/test_function.py b/Lib/test/test_capi/test_function.py new file mode 100644 index 00000000000000..9dca377e28ba42 --- /dev/null +++ b/Lib/test/test_capi/test_function.py @@ -0,0 +1,323 @@ +import unittest +from test.support import import_helper + + +_testcapi = import_helper.import_module('_testcapi') + + +class FunctionTest(unittest.TestCase): + def test_function_get_code(self): + # Test PyFunction_GetCode() + 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): + # Test PyFunction_GetGlobals() + 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): + # Test PyFunction_GetModule() + 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 + + def test_function_get_defaults(self): + # Test PyFunction_GetDefaults() + def some( + pos_only1, pos_only2='p', + /, + zero=0, optional=None, + *, + kw1, + kw2=True, + ): + pass + + defaults = _testcapi.function_get_defaults(some) + self.assertEqual(defaults, ('p', 0, None)) + self.assertEqual(defaults, some.__defaults__) + + with self.assertRaises(SystemError): + _testcapi.function_get_defaults(None) # not a function + + def test_function_set_defaults(self): + # Test PyFunction_SetDefaults() + def some( + pos_only1, pos_only2='p', + /, + zero=0, optional=None, + *, + kw1, + kw2=True, + ): + pass + + old_defaults = ('p', 0, None) + self.assertEqual(_testcapi.function_get_defaults(some), old_defaults) + self.assertEqual(some.__defaults__, old_defaults) + + with self.assertRaises(SystemError): + _testcapi.function_set_defaults(some, 1) # not tuple or None + self.assertEqual(_testcapi.function_get_defaults(some), old_defaults) + self.assertEqual(some.__defaults__, old_defaults) + + with self.assertRaises(SystemError): + _testcapi.function_set_defaults(1, ()) # not a function + self.assertEqual(_testcapi.function_get_defaults(some), old_defaults) + self.assertEqual(some.__defaults__, old_defaults) + + new_defaults = ('q', 1, None) + _testcapi.function_set_defaults(some, new_defaults) + self.assertEqual(_testcapi.function_get_defaults(some), new_defaults) + self.assertEqual(some.__defaults__, new_defaults) + + # Empty tuple is fine: + new_defaults = () + _testcapi.function_set_defaults(some, new_defaults) + self.assertEqual(_testcapi.function_get_defaults(some), new_defaults) + self.assertEqual(some.__defaults__, new_defaults) + + class tuplesub(tuple): ... # tuple subclasses must work + + new_defaults = tuplesub(((1, 2), ['a', 'b'], None)) + _testcapi.function_set_defaults(some, new_defaults) + self.assertEqual(_testcapi.function_get_defaults(some), new_defaults) + self.assertEqual(some.__defaults__, new_defaults) + + # `None` is special, it sets `defaults` to `NULL`, + # it needs special handling in `_testcapi`: + _testcapi.function_set_defaults(some, None) + self.assertEqual(_testcapi.function_get_defaults(some), None) + self.assertEqual(some.__defaults__, None) + + def test_function_get_kw_defaults(self): + # Test PyFunction_GetKwDefaults() + def some( + pos_only1, pos_only2='p', + /, + zero=0, optional=None, + *, + kw1, + kw2=True, + ): + pass + + defaults = _testcapi.function_get_kw_defaults(some) + self.assertEqual(defaults, {'kw2': True}) + self.assertEqual(defaults, some.__kwdefaults__) + + with self.assertRaises(SystemError): + _testcapi.function_get_kw_defaults(None) # not a function + + def test_function_set_kw_defaults(self): + # Test PyFunction_SetKwDefaults() + def some( + pos_only1, pos_only2='p', + /, + zero=0, optional=None, + *, + kw1, + kw2=True, + ): + pass + + old_defaults = {'kw2': True} + self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults) + self.assertEqual(some.__kwdefaults__, old_defaults) + + with self.assertRaises(SystemError): + _testcapi.function_set_kw_defaults(some, 1) # not dict or None + self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults) + self.assertEqual(some.__kwdefaults__, old_defaults) + + with self.assertRaises(SystemError): + _testcapi.function_set_kw_defaults(1, {}) # not a function + self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults) + self.assertEqual(some.__kwdefaults__, old_defaults) + + new_defaults = {'kw2': (1, 2, 3)} + _testcapi.function_set_kw_defaults(some, new_defaults) + self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults) + self.assertEqual(some.__kwdefaults__, new_defaults) + + # Empty dict is fine: + new_defaults = {} + _testcapi.function_set_kw_defaults(some, new_defaults) + self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults) + self.assertEqual(some.__kwdefaults__, new_defaults) + + class dictsub(dict): ... # dict subclasses must work + + new_defaults = dictsub({'kw2': None}) + _testcapi.function_set_kw_defaults(some, new_defaults) + self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults) + self.assertEqual(some.__kwdefaults__, new_defaults) + + # `None` is special, it sets `kwdefaults` to `NULL`, + # it needs special handling in `_testcapi`: + _testcapi.function_set_kw_defaults(some, None) + self.assertEqual(_testcapi.function_get_kw_defaults(some), None) + self.assertEqual(some.__kwdefaults__, None) + + def test_function_get_closure(self): + # Test PyFunction_GetClosure() + from types import CellType + + def regular_function(): ... + def unused_one_level(arg1): + def inner(arg2, arg3): ... + return inner + def unused_two_levels(arg1, arg2): + def decorator(arg3, arg4): + def inner(arg5, arg6): ... + return inner + return decorator + def with_one_level(arg1): + def inner(arg2, arg3): + return arg1 + arg2 + arg3 + return inner + def with_two_levels(arg1, arg2): + def decorator(arg3, arg4): + def inner(arg5, arg6): + return arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + return inner + return decorator + + # Functions without closures: + self.assertIsNone(_testcapi.function_get_closure(regular_function)) + self.assertIsNone(regular_function.__closure__) + + func = unused_one_level(1) + closure = _testcapi.function_get_closure(func) + self.assertIsNone(closure) + self.assertIsNone(func.__closure__) + + func = unused_two_levels(1, 2)(3, 4) + closure = _testcapi.function_get_closure(func) + self.assertIsNone(closure) + self.assertIsNone(func.__closure__) + + # Functions with closures: + func = with_one_level(5) + closure = _testcapi.function_get_closure(func) + self.assertEqual(closure, func.__closure__) + self.assertIsInstance(closure, tuple) + self.assertEqual(len(closure), 1) + self.assertEqual(len(closure), len(func.__code__.co_freevars)) + for cell in closure: + self.assertIsInstance(cell, CellType) + self.assertTrue(closure[0].cell_contents, 5) + + func = with_two_levels(1, 2)(3, 4) + closure = _testcapi.function_get_closure(func) + self.assertEqual(closure, func.__closure__) + self.assertIsInstance(closure, tuple) + self.assertEqual(len(closure), 4) + self.assertEqual(len(closure), len(func.__code__.co_freevars)) + for cell in closure: + self.assertIsInstance(cell, CellType) + self.assertEqual([cell.cell_contents for cell in closure], + [1, 2, 3, 4]) + + def test_function_get_closure_error(self): + # Test PyFunction_GetClosure() + with self.assertRaises(SystemError): + _testcapi.function_get_closure(1) + with self.assertRaises(SystemError): + _testcapi.function_get_closure(None) + + def test_function_set_closure(self): + # Test PyFunction_SetClosure() + from types import CellType + + def function_without_closure(): ... + def function_with_closure(arg): + def inner(): + return arg + return inner + + func = function_without_closure + _testcapi.function_set_closure(func, (CellType(1), CellType(1))) + closure = _testcapi.function_get_closure(func) + self.assertEqual([c.cell_contents for c in closure], [1, 1]) + self.assertEqual([c.cell_contents for c in func.__closure__], [1, 1]) + + func = function_with_closure(1) + _testcapi.function_set_closure(func, + (CellType(1), CellType(2), CellType(3))) + closure = _testcapi.function_get_closure(func) + self.assertEqual([c.cell_contents for c in closure], [1, 2, 3]) + self.assertEqual([c.cell_contents for c in func.__closure__], [1, 2, 3]) + + def test_function_set_closure_none(self): + # Test PyFunction_SetClosure() + def function_without_closure(): ... + def function_with_closure(arg): + def inner(): + return arg + return inner + + _testcapi.function_set_closure(function_without_closure, None) + self.assertIsNone( + _testcapi.function_get_closure(function_without_closure)) + self.assertIsNone(function_without_closure.__closure__) + + _testcapi.function_set_closure(function_with_closure, None) + self.assertIsNone( + _testcapi.function_get_closure(function_with_closure)) + self.assertIsNone(function_with_closure.__closure__) + + def test_function_set_closure_errors(self): + # Test PyFunction_SetClosure() + def function_without_closure(): ... + + with self.assertRaises(SystemError): + _testcapi.function_set_closure(None, ()) # not a function + + with self.assertRaises(SystemError): + _testcapi.function_set_closure(function_without_closure, 1) + self.assertIsNone(function_without_closure.__closure__) # no change + + # NOTE: this works, but goes against the docs: + _testcapi.function_set_closure(function_without_closure, (1, 2)) + self.assertEqual( + _testcapi.function_get_closure(function_without_closure), (1, 2)) + self.assertEqual(function_without_closure.__closure__, (1, 2)) + + # TODO: test PyFunction_New() + # TODO: test PyFunction_NewWithQualName() + # TODO: test PyFunction_SetVectorcall() + # TODO: test PyFunction_GetAnnotations() + # TODO: test PyFunction_SetAnnotations() + # TODO: test PyClassMethod_New() + # TODO: test PyStaticMethod_New() + # + # PyFunction_AddWatcher() and PyFunction_ClearWatcher() are tested by + # test_capi.test_watchers. + + +if __name__ == "__main__": + unittest.main() diff --git a/Lib/test/test_capi/test_misc.py b/Lib/test/test_capi/test_misc.py index efa01a84167002..acc4803d785366 100644 --- a/Lib/test/test_capi/test_misc.py +++ b/Lib/test/test_capi/test_misc.py @@ -928,175 +928,6 @@ def __init__(self): _testcapi.clear_managed_dict(c) self.assertEqual(c.__dict__, {}) - 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 - - def test_function_get_defaults(self): - def some( - pos_only1, pos_only2='p', - /, - zero=0, optional=None, - *, - kw1, - kw2=True, - ): - pass - - defaults = _testcapi.function_get_defaults(some) - self.assertEqual(defaults, ('p', 0, None)) - self.assertEqual(defaults, some.__defaults__) - - with self.assertRaises(SystemError): - _testcapi.function_get_defaults(None) # not a function - - def test_function_set_defaults(self): - def some( - pos_only1, pos_only2='p', - /, - zero=0, optional=None, - *, - kw1, - kw2=True, - ): - pass - - old_defaults = ('p', 0, None) - self.assertEqual(_testcapi.function_get_defaults(some), old_defaults) - self.assertEqual(some.__defaults__, old_defaults) - - with self.assertRaises(SystemError): - _testcapi.function_set_defaults(some, 1) # not tuple or None - self.assertEqual(_testcapi.function_get_defaults(some), old_defaults) - self.assertEqual(some.__defaults__, old_defaults) - - with self.assertRaises(SystemError): - _testcapi.function_set_defaults(1, ()) # not a function - self.assertEqual(_testcapi.function_get_defaults(some), old_defaults) - self.assertEqual(some.__defaults__, old_defaults) - - new_defaults = ('q', 1, None) - _testcapi.function_set_defaults(some, new_defaults) - self.assertEqual(_testcapi.function_get_defaults(some), new_defaults) - self.assertEqual(some.__defaults__, new_defaults) - - # Empty tuple is fine: - new_defaults = () - _testcapi.function_set_defaults(some, new_defaults) - self.assertEqual(_testcapi.function_get_defaults(some), new_defaults) - self.assertEqual(some.__defaults__, new_defaults) - - class tuplesub(tuple): ... # tuple subclasses must work - - new_defaults = tuplesub(((1, 2), ['a', 'b'], None)) - _testcapi.function_set_defaults(some, new_defaults) - self.assertEqual(_testcapi.function_get_defaults(some), new_defaults) - self.assertEqual(some.__defaults__, new_defaults) - - # `None` is special, it sets `defaults` to `NULL`, - # it needs special handling in `_testcapi`: - _testcapi.function_set_defaults(some, None) - self.assertEqual(_testcapi.function_get_defaults(some), None) - self.assertEqual(some.__defaults__, None) - - def test_function_get_kw_defaults(self): - def some( - pos_only1, pos_only2='p', - /, - zero=0, optional=None, - *, - kw1, - kw2=True, - ): - pass - - defaults = _testcapi.function_get_kw_defaults(some) - self.assertEqual(defaults, {'kw2': True}) - self.assertEqual(defaults, some.__kwdefaults__) - - with self.assertRaises(SystemError): - _testcapi.function_get_kw_defaults(None) # not a function - - def test_function_set_kw_defaults(self): - def some( - pos_only1, pos_only2='p', - /, - zero=0, optional=None, - *, - kw1, - kw2=True, - ): - pass - - old_defaults = {'kw2': True} - self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults) - self.assertEqual(some.__kwdefaults__, old_defaults) - - with self.assertRaises(SystemError): - _testcapi.function_set_kw_defaults(some, 1) # not dict or None - self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults) - self.assertEqual(some.__kwdefaults__, old_defaults) - - with self.assertRaises(SystemError): - _testcapi.function_set_kw_defaults(1, {}) # not a function - self.assertEqual(_testcapi.function_get_kw_defaults(some), old_defaults) - self.assertEqual(some.__kwdefaults__, old_defaults) - - new_defaults = {'kw2': (1, 2, 3)} - _testcapi.function_set_kw_defaults(some, new_defaults) - self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults) - self.assertEqual(some.__kwdefaults__, new_defaults) - - # Empty dict is fine: - new_defaults = {} - _testcapi.function_set_kw_defaults(some, new_defaults) - self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults) - self.assertEqual(some.__kwdefaults__, new_defaults) - - class dictsub(dict): ... # dict subclasses must work - - new_defaults = dictsub({'kw2': None}) - _testcapi.function_set_kw_defaults(some, new_defaults) - self.assertEqual(_testcapi.function_get_kw_defaults(some), new_defaults) - self.assertEqual(some.__kwdefaults__, new_defaults) - - # `None` is special, it sets `kwdefaults` to `NULL`, - # it needs special handling in `_testcapi`: - _testcapi.function_set_kw_defaults(some, None) - self.assertEqual(_testcapi.function_get_kw_defaults(some), None) - self.assertEqual(some.__kwdefaults__, None) - def test_unstable_gc_new_with_extra_data(self): class Data(_testcapi.ObjExtraData): __slots__ = ('x', 'y') @@ -1319,127 +1150,6 @@ def test_pyobject_getitemdata_error(self): _testcapi.pyobject_getitemdata(0) - def test_function_get_closure(self): - from types import CellType - - def regular_function(): ... - def unused_one_level(arg1): - def inner(arg2, arg3): ... - return inner - def unused_two_levels(arg1, arg2): - def decorator(arg3, arg4): - def inner(arg5, arg6): ... - return inner - return decorator - def with_one_level(arg1): - def inner(arg2, arg3): - return arg1 + arg2 + arg3 - return inner - def with_two_levels(arg1, arg2): - def decorator(arg3, arg4): - def inner(arg5, arg6): - return arg1 + arg2 + arg3 + arg4 + arg5 + arg6 - return inner - return decorator - - # Functions without closures: - self.assertIsNone(_testcapi.function_get_closure(regular_function)) - self.assertIsNone(regular_function.__closure__) - - func = unused_one_level(1) - closure = _testcapi.function_get_closure(func) - self.assertIsNone(closure) - self.assertIsNone(func.__closure__) - - func = unused_two_levels(1, 2)(3, 4) - closure = _testcapi.function_get_closure(func) - self.assertIsNone(closure) - self.assertIsNone(func.__closure__) - - # Functions with closures: - func = with_one_level(5) - closure = _testcapi.function_get_closure(func) - self.assertEqual(closure, func.__closure__) - self.assertIsInstance(closure, tuple) - self.assertEqual(len(closure), 1) - self.assertEqual(len(closure), len(func.__code__.co_freevars)) - for cell in closure: - self.assertIsInstance(cell, CellType) - self.assertTrue(closure[0].cell_contents, 5) - - func = with_two_levels(1, 2)(3, 4) - closure = _testcapi.function_get_closure(func) - self.assertEqual(closure, func.__closure__) - self.assertIsInstance(closure, tuple) - self.assertEqual(len(closure), 4) - self.assertEqual(len(closure), len(func.__code__.co_freevars)) - for cell in closure: - self.assertIsInstance(cell, CellType) - self.assertEqual([cell.cell_contents for cell in closure], - [1, 2, 3, 4]) - - def test_function_get_closure_error(self): - with self.assertRaises(SystemError): - _testcapi.function_get_closure(1) - with self.assertRaises(SystemError): - _testcapi.function_get_closure(None) - - def test_function_set_closure(self): - from types import CellType - - def function_without_closure(): ... - def function_with_closure(arg): - def inner(): - return arg - return inner - - func = function_without_closure - _testcapi.function_set_closure(func, (CellType(1), CellType(1))) - closure = _testcapi.function_get_closure(func) - self.assertEqual([c.cell_contents for c in closure], [1, 1]) - self.assertEqual([c.cell_contents for c in func.__closure__], [1, 1]) - - func = function_with_closure(1) - _testcapi.function_set_closure(func, - (CellType(1), CellType(2), CellType(3))) - closure = _testcapi.function_get_closure(func) - self.assertEqual([c.cell_contents for c in closure], [1, 2, 3]) - self.assertEqual([c.cell_contents for c in func.__closure__], [1, 2, 3]) - - def test_function_set_closure_none(self): - def function_without_closure(): ... - def function_with_closure(arg): - def inner(): - return arg - return inner - - _testcapi.function_set_closure(function_without_closure, None) - self.assertIsNone( - _testcapi.function_get_closure(function_without_closure)) - self.assertIsNone(function_without_closure.__closure__) - - _testcapi.function_set_closure(function_with_closure, None) - self.assertIsNone( - _testcapi.function_get_closure(function_with_closure)) - self.assertIsNone(function_with_closure.__closure__) - - def test_function_set_closure_errors(self): - def function_without_closure(): ... - - with self.assertRaises(SystemError): - _testcapi.function_set_closure(None, ()) # not a function - - with self.assertRaises(SystemError): - _testcapi.function_set_closure(function_without_closure, 1) - self.assertIsNone(function_without_closure.__closure__) # no change - - # NOTE: this works, but goes against the docs: - _testcapi.function_set_closure(function_without_closure, (1, 2)) - self.assertEqual( - _testcapi.function_get_closure(function_without_closure), (1, 2)) - self.assertEqual(function_without_closure.__closure__, (1, 2)) - - class TestPendingCalls(unittest.TestCase): # See the comment in ceval.c (at the "handle_eval_breaker" label) @@ -3209,5 +2919,6 @@ def test_pack_version_ctypes(self): result = ctypes_func(*args) self.assertEqual(result, expected) + if __name__ == "__main__": unittest.main() diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in index a276fa642de42e..6bb05a06a3465d 100644 --- a/Modules/Setup.stdlib.in +++ b/Modules/Setup.stdlib.in @@ -162,7 +162,7 @@ @MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c @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 _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.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 _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c @MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c @MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c @MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c diff --git a/Modules/_testcapi/function.c b/Modules/_testcapi/function.c new file mode 100644 index 00000000000000..ec1ba508df2ce9 --- /dev/null +++ b/Modules/_testcapi/function.c @@ -0,0 +1,143 @@ +#include "parts.h" +#include "util.h" + + +static PyObject * +function_get_code(PyObject *self, PyObject *func) +{ + PyObject *code = PyFunction_GetCode(func); + if (code != NULL) { + return Py_NewRef(code); + } else { + return NULL; + } +} + + +static PyObject * +function_get_globals(PyObject *self, PyObject *func) +{ + PyObject *globals = PyFunction_GetGlobals(func); + if (globals != NULL) { + return Py_NewRef(globals); + } else { + return NULL; + } +} + + +static PyObject * +function_get_module(PyObject *self, PyObject *func) +{ + PyObject *module = PyFunction_GetModule(func); + if (module != NULL) { + return Py_NewRef(module); + } else { + return NULL; + } +} + + +static PyObject * +function_get_defaults(PyObject *self, PyObject *func) +{ + PyObject *defaults = PyFunction_GetDefaults(func); + if (defaults != NULL) { + return Py_NewRef(defaults); + } else if (PyErr_Occurred()) { + return NULL; + } else { + Py_RETURN_NONE; // This can happen when `defaults` are set to `None` + } +} + + +static PyObject * +function_set_defaults(PyObject *self, PyObject *args) +{ + PyObject *func = NULL, *defaults = NULL; + if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) { + return NULL; + } + int result = PyFunction_SetDefaults(func, defaults); + if (result == -1) + return NULL; + Py_RETURN_NONE; +} + + +static PyObject * +function_get_kw_defaults(PyObject *self, PyObject *func) +{ + PyObject *defaults = PyFunction_GetKwDefaults(func); + if (defaults != NULL) { + return Py_NewRef(defaults); + } else if (PyErr_Occurred()) { + return NULL; + } else { + Py_RETURN_NONE; // This can happen when `kwdefaults` are set to `None` + } +} + + +static PyObject * +function_set_kw_defaults(PyObject *self, PyObject *args) +{ + PyObject *func = NULL, *defaults = NULL; + if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) { + return NULL; + } + int result = PyFunction_SetKwDefaults(func, defaults); + if (result == -1) + return NULL; + Py_RETURN_NONE; +} + + +static PyObject * +function_get_closure(PyObject *self, PyObject *func) +{ + PyObject *closure = PyFunction_GetClosure(func); + if (closure != NULL) { + return Py_NewRef(closure); + } else if (PyErr_Occurred()) { + return NULL; + } else { + Py_RETURN_NONE; // This can happen when `closure` is set to `None` + } +} + + +static PyObject * +function_set_closure(PyObject *self, PyObject *args) +{ + PyObject *func = NULL, *closure = NULL; + if (!PyArg_ParseTuple(args, "OO", &func, &closure)) { + return NULL; + } + int result = PyFunction_SetClosure(func, closure); + if (result == -1) { + return NULL; + } + Py_RETURN_NONE; +} + + +static PyMethodDef test_methods[] = { + {"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}, + {"function_get_defaults", function_get_defaults, METH_O, NULL}, + {"function_set_defaults", function_set_defaults, METH_VARARGS, NULL}, + {"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL}, + {"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL}, + {"function_get_closure", function_get_closure, METH_O, NULL}, + {"function_set_closure", function_set_closure, METH_VARARGS, NULL}, + {NULL}, +}; + +int +_PyTestCapi_Init_Function(PyObject *m) +{ + return PyModule_AddFunctions(m, test_methods); +} diff --git a/Modules/_testcapi/parts.h b/Modules/_testcapi/parts.h index c4b73459b3712b..af6400162daf2b 100644 --- a/Modules/_testcapi/parts.h +++ b/Modules/_testcapi/parts.h @@ -64,5 +64,6 @@ int _PyTestCapi_Init_Config(PyObject *mod); int _PyTestCapi_Init_Import(PyObject *mod); int _PyTestCapi_Init_Frame(PyObject *mod); int _PyTestCapi_Init_Type(PyObject *mod); +int _PyTestCapi_Init_Function(PyObject *mod); #endif // Py_TESTCAPI_PARTS_H diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index ad9d836120b506..5b5b630e7e7581 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2652,119 +2652,6 @@ test_macros(PyObject *self, PyObject *Py_UNUSED(args)) Py_RETURN_NONE; } -static PyObject * -function_get_code(PyObject *self, PyObject *func) -{ - PyObject *code = PyFunction_GetCode(func); - if (code != NULL) { - return Py_NewRef(code); - } else { - return NULL; - } -} - -static PyObject * -function_get_globals(PyObject *self, PyObject *func) -{ - PyObject *globals = PyFunction_GetGlobals(func); - if (globals != NULL) { - return Py_NewRef(globals); - } else { - return NULL; - } -} - -static PyObject * -function_get_module(PyObject *self, PyObject *func) -{ - PyObject *module = PyFunction_GetModule(func); - if (module != NULL) { - return Py_NewRef(module); - } else { - return NULL; - } -} - -static PyObject * -function_get_defaults(PyObject *self, PyObject *func) -{ - PyObject *defaults = PyFunction_GetDefaults(func); - if (defaults != NULL) { - return Py_NewRef(defaults); - } else if (PyErr_Occurred()) { - return NULL; - } else { - Py_RETURN_NONE; // This can happen when `defaults` are set to `None` - } -} - -static PyObject * -function_set_defaults(PyObject *self, PyObject *args) -{ - PyObject *func = NULL, *defaults = NULL; - if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) { - return NULL; - } - int result = PyFunction_SetDefaults(func, defaults); - if (result == -1) - return NULL; - Py_RETURN_NONE; -} - -static PyObject * -function_get_kw_defaults(PyObject *self, PyObject *func) -{ - PyObject *defaults = PyFunction_GetKwDefaults(func); - if (defaults != NULL) { - return Py_NewRef(defaults); - } else if (PyErr_Occurred()) { - return NULL; - } else { - Py_RETURN_NONE; // This can happen when `kwdefaults` are set to `None` - } -} - -static PyObject * -function_set_kw_defaults(PyObject *self, PyObject *args) -{ - PyObject *func = NULL, *defaults = NULL; - if (!PyArg_ParseTuple(args, "OO", &func, &defaults)) { - return NULL; - } - int result = PyFunction_SetKwDefaults(func, defaults); - if (result == -1) - return NULL; - Py_RETURN_NONE; -} - -static PyObject * -function_get_closure(PyObject *self, PyObject *func) -{ - PyObject *closure = PyFunction_GetClosure(func); - if (closure != NULL) { - return Py_NewRef(closure); - } else if (PyErr_Occurred()) { - return NULL; - } else { - Py_RETURN_NONE; // This can happen when `closure` is set to `None` - } -} - -static PyObject * -function_set_closure(PyObject *self, PyObject *args) -{ - PyObject *func = NULL, *closure = NULL; - if (!PyArg_ParseTuple(args, "OO", &func, &closure)) { - return NULL; - } - int result = PyFunction_SetClosure(func, closure); - if (result == -1) { - return NULL; - } - Py_RETURN_NONE; -} - - static PyObject * test_weakref_capi(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args)) { @@ -3286,15 +3173,6 @@ static PyMethodDef TestMethods[] = { {"settrace_to_record", settrace_to_record, METH_O, NULL}, {"test_macros", test_macros, METH_NOARGS, NULL}, {"clear_managed_dict", clear_managed_dict, 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}, - {"function_get_defaults", function_get_defaults, METH_O, NULL}, - {"function_set_defaults", function_set_defaults, METH_VARARGS, NULL}, - {"function_get_kw_defaults", function_get_kw_defaults, METH_O, NULL}, - {"function_set_kw_defaults", function_set_kw_defaults, METH_VARARGS, NULL}, - {"function_get_closure", function_get_closure, METH_O, NULL}, - {"function_set_closure", function_set_closure, METH_VARARGS, NULL}, {"test_weakref_capi", test_weakref_capi, METH_NOARGS}, {"function_set_warning", function_set_warning, METH_NOARGS}, {"test_critical_sections", test_critical_sections, METH_NOARGS}, @@ -4081,6 +3959,9 @@ PyInit__testcapi(void) if (_PyTestCapi_Init_Type(m) < 0) { return NULL; } + if (_PyTestCapi_Init_Function(m) < 0) { + return NULL; + } PyState_AddModule(m, &_testcapimodule); return m; diff --git a/PCbuild/_testcapi.vcxproj b/PCbuild/_testcapi.vcxproj index 09969331c6edd4..a68f15d25aabb7 100644 --- a/PCbuild/_testcapi.vcxproj +++ b/PCbuild/_testcapi.vcxproj @@ -130,6 +130,7 @@ + diff --git a/PCbuild/_testcapi.vcxproj.filters b/PCbuild/_testcapi.vcxproj.filters index 52491643ad842f..21091e9dc1aa16 100644 --- a/PCbuild/_testcapi.vcxproj.filters +++ b/PCbuild/_testcapi.vcxproj.filters @@ -123,6 +123,9 @@ Source Files + + Source Files + pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy