Coverage Report

Created: 2025-07-11 06:59

/src/Python-3.8.3/Modules/_weakref.c
Line
Count
Source (jump to first uncovered line)
1
#include "Python.h"
2
3
4
#define GET_WEAKREFS_LISTPTR(o) \
5
0
        ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
6
7
/*[clinic input]
8
module _weakref
9
[clinic start generated code]*/
10
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=ffec73b85846596d]*/
11
12
#include "clinic/_weakref.c.h"
13
14
/*[clinic input]
15
16
_weakref.getweakrefcount -> Py_ssize_t
17
18
  object: object
19
  /
20
21
Return the number of weak references to 'object'.
22
[clinic start generated code]*/
23
24
static Py_ssize_t
25
_weakref_getweakrefcount_impl(PyObject *module, PyObject *object)
26
/*[clinic end generated code: output=301806d59558ff3e input=cedb69711b6a2507]*/
27
0
{
28
0
    PyWeakReference **list;
29
30
0
    if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)))
31
0
        return 0;
32
33
0
    list = GET_WEAKREFS_LISTPTR(object);
34
0
    return _PyWeakref_GetWeakrefCount(*list);
35
0
}
36
37
38
static int
39
is_dead_weakref(PyObject *value)
40
0
{
41
0
    if (!PyWeakref_Check(value)) {
42
0
        PyErr_SetString(PyExc_TypeError, "not a weakref");
43
0
        return -1;
44
0
    }
45
0
    return PyWeakref_GET_OBJECT(value) == Py_None;
46
0
}
47
48
/*[clinic input]
49
50
_weakref._remove_dead_weakref -> object
51
52
  dct: object(subclass_of='&PyDict_Type')
53
  key: object
54
  /
55
56
Atomically remove key from dict if it points to a dead weakref.
57
[clinic start generated code]*/
58
59
static PyObject *
60
_weakref__remove_dead_weakref_impl(PyObject *module, PyObject *dct,
61
                                   PyObject *key)
62
/*[clinic end generated code: output=d9ff53061fcb875c input=19fc91f257f96a1d]*/
63
0
{
64
0
    if (_PyDict_DelItemIf(dct, key, is_dead_weakref) < 0) {
65
0
        if (PyErr_ExceptionMatches(PyExc_KeyError))
66
            /* This function is meant to allow safe weak-value dicts
67
               with GC in another thread (see issue #28427), so it's
68
               ok if the key doesn't exist anymore.
69
               */
70
0
            PyErr_Clear();
71
0
        else
72
0
            return NULL;
73
0
    }
74
0
    Py_RETURN_NONE;
75
0
}
76
77
78
PyDoc_STRVAR(weakref_getweakrefs__doc__,
79
"getweakrefs(object) -- return a list of all weak reference objects\n"
80
"that point to 'object'.");
81
82
static PyObject *
83
weakref_getweakrefs(PyObject *self, PyObject *object)
84
0
{
85
0
    PyObject *result = NULL;
86
87
0
    if (PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))) {
88
0
        PyWeakReference **list = GET_WEAKREFS_LISTPTR(object);
89
0
        Py_ssize_t count = _PyWeakref_GetWeakrefCount(*list);
90
91
0
        result = PyList_New(count);
92
0
        if (result != NULL) {
93
0
            PyWeakReference *current = *list;
94
0
            Py_ssize_t i;
95
0
            for (i = 0; i < count; ++i) {
96
0
                PyList_SET_ITEM(result, i, (PyObject *) current);
97
0
                Py_INCREF(current);
98
0
                current = current->wr_next;
99
0
            }
100
0
        }
101
0
    }
102
0
    else {
103
0
        result = PyList_New(0);
104
0
    }
105
0
    return result;
106
0
}
107
108
109
PyDoc_STRVAR(weakref_proxy__doc__,
110
"proxy(object[, callback]) -- create a proxy object that weakly\n"
111
"references 'object'.  'callback', if given, is called with a\n"
112
"reference to the proxy when 'object' is about to be finalized.");
113
114
static PyObject *
115
weakref_proxy(PyObject *self, PyObject *args)
116
0
{
117
0
    PyObject *object;
118
0
    PyObject *callback = NULL;
119
0
    PyObject *result = NULL;
120
121
0
    if (PyArg_UnpackTuple(args, "proxy", 1, 2, &object, &callback)) {
122
0
        result = PyWeakref_NewProxy(object, callback);
123
0
    }
124
0
    return result;
125
0
}
126
127
128
static PyMethodDef
129
weakref_functions[] =  {
130
    _WEAKREF_GETWEAKREFCOUNT_METHODDEF
131
    _WEAKREF__REMOVE_DEAD_WEAKREF_METHODDEF
132
    {"getweakrefs",     weakref_getweakrefs,            METH_O,
133
     weakref_getweakrefs__doc__},
134
    {"proxy",           weakref_proxy,                  METH_VARARGS,
135
     weakref_proxy__doc__},
136
    {NULL, NULL, 0, NULL}
137
};
138
139
140
static struct PyModuleDef weakrefmodule = {
141
    PyModuleDef_HEAD_INIT,
142
    "_weakref",
143
    "Weak-reference support module.",
144
    -1,
145
    weakref_functions,
146
    NULL,
147
    NULL,
148
    NULL,
149
    NULL
150
};
151
152
PyMODINIT_FUNC
153
PyInit__weakref(void)
154
14
{
155
14
    PyObject *m;
156
157
14
    m = PyModule_Create(&weakrefmodule);
158
159
14
    if (m != NULL) {
160
14
        Py_INCREF(&_PyWeakref_RefType);
161
14
        PyModule_AddObject(m, "ref",
162
14
                           (PyObject *) &_PyWeakref_RefType);
163
14
        Py_INCREF(&_PyWeakref_RefType);
164
14
        PyModule_AddObject(m, "ReferenceType",
165
14
                           (PyObject *) &_PyWeakref_RefType);
166
14
        Py_INCREF(&_PyWeakref_ProxyType);
167
14
        PyModule_AddObject(m, "ProxyType",
168
14
                           (PyObject *) &_PyWeakref_ProxyType);
169
14
        Py_INCREF(&_PyWeakref_CallableProxyType);
170
14
        PyModule_AddObject(m, "CallableProxyType",
171
14
                           (PyObject *) &_PyWeakref_CallableProxyType);
172
14
    }
173
14
    return m;
174
14
}