/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 | } |