mirror of
https://github.com/python/cpython.git
synced 2026-06-17 15:16:42 +00:00
[3.14] gh-151130: Add more tests for PyWeakref_* C API (GH-151131) (GH-151141)
(cherry picked from commit c3cd75afdf)
This commit is contained in:
parent
5c6402e6a5
commit
cb96d5ea4a
13 changed files with 277 additions and 2 deletions
136
Lib/test/test_capi/test_weakref.py
Normal file
136
Lib/test/test_capi/test_weakref.py
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
import weakref
|
||||
import unittest
|
||||
from test.support import import_helper
|
||||
|
||||
_testcapi = import_helper.import_module('_testcapi')
|
||||
_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
|
||||
NULL = None
|
||||
|
||||
class Object:
|
||||
pass
|
||||
|
||||
class Ref(weakref.ReferenceType):
|
||||
pass
|
||||
|
||||
|
||||
class CAPIWeakrefTest(unittest.TestCase):
|
||||
def test_pyweakref_check(self):
|
||||
# Test PyWeakref_Check()
|
||||
check = _testlimitedcapi.pyweakref_check
|
||||
obj = Object()
|
||||
self.assertEqual(check(obj), 0)
|
||||
self.assertEqual(check(weakref.ref(obj)), 1)
|
||||
self.assertEqual(check(Ref(obj)), 1)
|
||||
self.assertEqual(check(weakref.proxy(obj)), 1)
|
||||
|
||||
# CRASHES check(NULL)
|
||||
|
||||
def test_pyweakref_checkref(self):
|
||||
# Test PyWeakref_CheckRef()
|
||||
checkref = _testlimitedcapi.pyweakref_checkref
|
||||
obj = Object()
|
||||
self.assertEqual(checkref(obj), 0)
|
||||
self.assertEqual(checkref(weakref.ref(obj)), 1)
|
||||
self.assertEqual(checkref(Ref(obj)), 1)
|
||||
self.assertEqual(checkref(weakref.proxy(obj)), 0)
|
||||
|
||||
# CRASHES checkref(NULL)
|
||||
|
||||
def test_pyweakref_checkrefexact(self):
|
||||
# Test PyWeakref_CheckRefExact()
|
||||
checkrefexact = _testlimitedcapi.pyweakref_checkrefexact
|
||||
obj = Object()
|
||||
self.assertEqual(checkrefexact(obj), 0)
|
||||
self.assertEqual(checkrefexact(weakref.ref(obj)), 1)
|
||||
self.assertEqual(checkrefexact(Ref(obj)), 0)
|
||||
self.assertEqual(checkrefexact(weakref.proxy(obj)), 0)
|
||||
|
||||
# CRASHES checkrefexact(NULL)
|
||||
|
||||
def test_pyweakref_checkproxy(self):
|
||||
# Test PyWeakref_CheckProxy()
|
||||
checkproxy = _testlimitedcapi.pyweakref_checkproxy
|
||||
obj = Object()
|
||||
self.assertEqual(checkproxy(obj), 0)
|
||||
self.assertEqual(checkproxy(weakref.ref(obj)), 0)
|
||||
self.assertEqual(checkproxy(Ref(obj)), 0)
|
||||
self.assertEqual(checkproxy(weakref.proxy(obj)), 1)
|
||||
|
||||
# CRASHES checkproxy(NULL)
|
||||
|
||||
def test_pyweakref_getref(self):
|
||||
# Test PyWeakref_GetRef()
|
||||
getref = _testcapi.pyweakref_getref
|
||||
obj = Object()
|
||||
wr = weakref.ref(obj)
|
||||
wp = weakref.proxy(obj)
|
||||
self.assertEqual(getref(wr), (1, obj))
|
||||
self.assertEqual(getref(wp), (1, obj))
|
||||
del obj
|
||||
self.assertEqual(getref(wr), 0)
|
||||
self.assertEqual(getref(wp), 0)
|
||||
|
||||
self.assertRaises(TypeError, getref, 42)
|
||||
self.assertRaises(SystemError, getref, NULL)
|
||||
|
||||
def test_pyweakref_isdead(self):
|
||||
# Test PyWeakref_IsDead()
|
||||
isdead = _testcapi.pyweakref_isdead
|
||||
obj = Object()
|
||||
wr = weakref.ref(obj)
|
||||
wp = weakref.proxy(obj)
|
||||
self.assertEqual(isdead(wr), 0)
|
||||
self.assertEqual(isdead(wp), 0)
|
||||
del obj
|
||||
self.assertEqual(isdead(wr), 1)
|
||||
self.assertEqual(isdead(wp), 1)
|
||||
|
||||
self.assertRaises(TypeError, isdead, 42)
|
||||
self.assertRaises(SystemError, isdead, NULL)
|
||||
|
||||
def test_pyweakref_newref(self):
|
||||
# Test PyWeakref_NewRef()
|
||||
newref = _testlimitedcapi.pyweakref_newref
|
||||
obj = Object()
|
||||
wr = newref(obj)
|
||||
self.assertIs(type(wr), weakref.ReferenceType)
|
||||
# PyWeakref_NewRef() handles None callback as NULL callback
|
||||
wr = newref(obj, None)
|
||||
self.assertIs(type(wr), weakref.ReferenceType)
|
||||
log = []
|
||||
wr = newref(obj, log.append)
|
||||
self.assertIs(type(wr), weakref.ReferenceType)
|
||||
self.assertEqual(log, [])
|
||||
del obj
|
||||
self.assertEqual(log, [wr])
|
||||
|
||||
self.assertRaises(TypeError, newref, [])
|
||||
# CRASHES newref(NULL)
|
||||
|
||||
def test_pyweakref_newproxy(self):
|
||||
# Test PyWeakref_NewProxy()
|
||||
newproxy = _testlimitedcapi.pyweakref_newproxy
|
||||
obj = Object()
|
||||
wp = newproxy(obj)
|
||||
self.assertIs(type(wp), weakref.ProxyType)
|
||||
# PyWeakref_NewProxy() handles None callback as NULL callback
|
||||
wp = newproxy(obj, None)
|
||||
self.assertIs(type(wp), weakref.ProxyType)
|
||||
log = []
|
||||
wp = newproxy(obj, log.append)
|
||||
self.assertIs(type(wp), weakref.ProxyType)
|
||||
self.assertEqual(log, [])
|
||||
del obj
|
||||
self.assertEqual(log, [wp])
|
||||
|
||||
def func():
|
||||
pass
|
||||
wp = newproxy(func)
|
||||
self.assertIs(type(wp), weakref.CallableProxyType)
|
||||
|
||||
self.assertRaises(TypeError, newproxy, [])
|
||||
# CRASHES newproxy(NULL)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
@ -0,0 +1 @@
|
|||
Add more tests for ``PyWeakref_*`` C API.
|
||||
|
|
@ -175,8 +175,8 @@
|
|||
@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 _testinternalcapi/complex.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__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 _testcapi/weakref.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 _testlimitedcapi/weakref.c
|
||||
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
|
||||
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
|
||||
|
||||
|
|
|
|||
|
|
@ -65,5 +65,6 @@ int _PyTestCapi_Init_Import(PyObject *mod);
|
|||
int _PyTestCapi_Init_Frame(PyObject *mod);
|
||||
int _PyTestCapi_Init_Type(PyObject *mod);
|
||||
int _PyTestCapi_Init_Function(PyObject *mod);
|
||||
int _PyTestCapi_Init_Weakref(PyObject *mod);
|
||||
|
||||
#endif // Py_TESTCAPI_PARTS_H
|
||||
|
|
|
|||
46
Modules/_testcapi/weakref.c
Normal file
46
Modules/_testcapi/weakref.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#include "parts.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
static PyObject *
|
||||
pyweakref_getref(PyObject *module, PyObject *ref)
|
||||
{
|
||||
NULLABLE(ref);
|
||||
PyObject *obj = UNINITIALIZED_PTR;
|
||||
int rc = PyWeakref_GetRef(ref, &obj);
|
||||
if (rc == -1 && PyErr_Occurred()) {
|
||||
assert(obj == NULL);
|
||||
return NULL;
|
||||
}
|
||||
if (obj == NULL) {
|
||||
return Py_BuildValue("i", rc);
|
||||
}
|
||||
else {
|
||||
assert(obj != UNINITIALIZED_PTR);
|
||||
return Py_BuildValue("iN", rc, obj);
|
||||
}
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyweakref_isdead(PyObject *module, PyObject *obj)
|
||||
{
|
||||
NULLABLE(obj);
|
||||
int rc = PyWeakref_IsDead(obj);
|
||||
if (rc == -1 && PyErr_Occurred()) {
|
||||
return NULL;
|
||||
}
|
||||
return PyLong_FromLong(rc);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef test_methods[] = {
|
||||
{"pyweakref_getref", pyweakref_getref, METH_O},
|
||||
{"pyweakref_isdead", pyweakref_isdead, METH_O},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
int
|
||||
_PyTestCapi_Init_Weakref(PyObject *m)
|
||||
{
|
||||
return PyModule_AddFunctions(m, test_methods);
|
||||
}
|
||||
|
|
@ -3503,6 +3503,9 @@ PyInit__testcapi(void)
|
|||
if (_PyTestCapi_Init_Function(m) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (_PyTestCapi_Init_Weakref(m) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyState_AddModule(m, &_testcapimodule);
|
||||
return m;
|
||||
|
|
|
|||
|
|
@ -92,5 +92,8 @@ PyInit__testlimitedcapi(void)
|
|||
if (_PyTestLimitedCAPI_Init_File(mod) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (_PyTestLimitedCAPI_Init_Weakref(mod) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return mod;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,5 +43,6 @@ int _PyTestLimitedCAPI_Init_Unicode(PyObject *module);
|
|||
int _PyTestLimitedCAPI_Init_VectorcallLimited(PyObject *module);
|
||||
int _PyTestLimitedCAPI_Init_Version(PyObject *module);
|
||||
int _PyTestLimitedCAPI_Init_File(PyObject *module);
|
||||
int _PyTestLimitedCAPI_Init_Weakref(PyObject *module);
|
||||
|
||||
#endif // Py_TESTLIMITEDCAPI_PARTS_H
|
||||
|
|
|
|||
78
Modules/_testlimitedcapi/weakref.c
Normal file
78
Modules/_testlimitedcapi/weakref.c
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#include "pyconfig.h" // Py_GIL_DISABLED
|
||||
#ifndef Py_GIL_DISABLED
|
||||
// Need limited C API 3.5 for PyModule_AddFunctions()
|
||||
# define Py_LIMITED_API 0x03050000
|
||||
#endif
|
||||
|
||||
#include "parts.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
static PyObject *
|
||||
pyweakref_check(PyObject *module, PyObject *obj)
|
||||
{
|
||||
NULLABLE(obj);
|
||||
return PyLong_FromLong(PyWeakref_Check(obj));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyweakref_checkref(PyObject *module, PyObject *obj)
|
||||
{
|
||||
NULLABLE(obj);
|
||||
return PyLong_FromLong(PyWeakref_CheckRef(obj));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyweakref_checkrefexact(PyObject *module, PyObject *obj)
|
||||
{
|
||||
NULLABLE(obj);
|
||||
return PyLong_FromLong(PyWeakref_CheckRefExact(obj));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyweakref_checkproxy(PyObject *module, PyObject *obj)
|
||||
{
|
||||
NULLABLE(obj);
|
||||
return PyLong_FromLong(PyWeakref_CheckProxy(obj));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyweakref_newref(PyObject *module, PyObject *args)
|
||||
{
|
||||
PyObject *obj;
|
||||
PyObject *callback = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O|O", &obj, &callback)) {
|
||||
return NULL;
|
||||
}
|
||||
NULLABLE(obj);
|
||||
return PyWeakref_NewRef(obj, callback);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
pyweakref_newproxy(PyObject *module, PyObject *args)
|
||||
{
|
||||
PyObject *obj;
|
||||
PyObject *callback = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O|O", &obj, &callback)) {
|
||||
return NULL;
|
||||
}
|
||||
NULLABLE(obj);
|
||||
return PyWeakref_NewProxy(obj, callback);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef test_methods[] = {
|
||||
{"pyweakref_check", pyweakref_check, METH_O},
|
||||
{"pyweakref_checkref", pyweakref_checkref, METH_O},
|
||||
{"pyweakref_checkrefexact", pyweakref_checkrefexact, METH_O},
|
||||
{"pyweakref_checkproxy", pyweakref_checkproxy, METH_O},
|
||||
{"pyweakref_newref", pyweakref_newref, METH_VARARGS},
|
||||
{"pyweakref_newproxy", pyweakref_newproxy, METH_VARARGS},
|
||||
{NULL},
|
||||
};
|
||||
|
||||
int
|
||||
_PyTestLimitedCAPI_Init_Weakref(PyObject *m)
|
||||
{
|
||||
return PyModule_AddFunctions(m, test_methods);
|
||||
}
|
||||
|
|
@ -131,6 +131,7 @@
|
|||
<ClCompile Include="..\Modules\_testcapi\frame.c" />
|
||||
<ClCompile Include="..\Modules\_testcapi\type.c" />
|
||||
<ClCompile Include="..\Modules\_testcapi\function.c" />
|
||||
<ClCompile Include="..\Modules\_testcapi\weakref.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\PC\python_nt.rc" />
|
||||
|
|
|
|||
|
|
@ -126,6 +126,9 @@
|
|||
<ClCompile Include="..\Modules\_testcapi\function.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Modules\_testcapi\weakref.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\PC\python_nt.rc">
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@
|
|||
<ClCompile Include="..\Modules\_testlimitedcapi\vectorcall_limited.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\version.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\file.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\weakref.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="..\PC\python_nt.rc" />
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
<ClCompile Include="..\Modules\_testlimitedcapi\vectorcall_limited.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\version.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\file.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi\weakref.c" />
|
||||
<ClCompile Include="..\Modules\_testlimitedcapi.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue