blob: 99bf42bfece828ff6b0c37f5d104e21988a17640 [file] [log] [blame]
Fred Drake8844d522001-10-05 21:52:26 +00001#include "Python.h"
2#include "structmember.h"
3
4
5#define GET_WEAKREFS_LISTPTR(o) \
6 ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o))
7
Fred Drake8844d522001-10-05 21:52:26 +00008
Neal Norwitzc5e060d2006-08-02 06:14:22 +00009Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000010_PyWeakref_GetWeakrefCount(PyWeakReference *head)
11{
Neal Norwitzc5e060d2006-08-02 06:14:22 +000012 Py_ssize_t count = 0;
Fred Drake8844d522001-10-05 21:52:26 +000013
14 while (head != NULL) {
15 ++count;
16 head = head->wr_next;
17 }
18 return count;
19}
20
21
Fred Drake0a4dd392004-07-02 18:57:45 +000022static void
23init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
24{
25 self->hash = -1;
26 self->wr_object = ob;
27 Py_XINCREF(callback);
28 self->wr_callback = callback;
29}
30
Fred Drake8844d522001-10-05 21:52:26 +000031static PyWeakReference *
Neil Schemenauer38a89162002-03-27 15:18:21 +000032new_weakref(PyObject *ob, PyObject *callback)
Fred Drake8844d522001-10-05 21:52:26 +000033{
34 PyWeakReference *result;
35
Neil Schemenauer38a89162002-03-27 15:18:21 +000036 result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType);
37 if (result) {
Fred Drake0a4dd392004-07-02 18:57:45 +000038 init_weakref(result, ob, callback);
Neil Schemenauer38a89162002-03-27 15:18:21 +000039 PyObject_GC_Track(result);
40 }
Fred Drake8844d522001-10-05 21:52:26 +000041 return result;
42}
43
44
45/* This function clears the passed-in reference and removes it from the
46 * list of weak references for the referent. This is the only code that
47 * removes an item from the doubly-linked list of weak references for an
48 * object; it is also responsible for clearing the callback slot.
49 */
50static void
51clear_weakref(PyWeakReference *self)
52{
53 PyObject *callback = self->wr_callback;
54
Antoine Pitroud38c9902012-12-08 21:15:26 +010055 if (self->wr_object != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(self->wr_object);
Fred Drake8844d522001-10-05 21:52:26 +000057
58 if (*list == self)
Antoine Pitrouc83ea132010-05-09 14:46:46 +000059 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
60 then the weakref list itself (and thus the value of *list) will
61 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000062 *list = self->wr_next;
63 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000064 if (self->wr_prev != NULL)
65 self->wr_prev->wr_next = self->wr_next;
66 if (self->wr_next != NULL)
67 self->wr_next->wr_prev = self->wr_prev;
68 self->wr_prev = NULL;
69 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000070 }
71 if (callback != NULL) {
72 Py_DECREF(callback);
73 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000074 }
75}
76
Tim Peters403a2032003-11-20 21:21:46 +000077/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
78 * the callback intact and uncalled. It must be possible to call self's
79 * tp_dealloc() after calling this, so self has to be left in a sane enough
80 * state for that to work. We expect tp_dealloc to decref the callback
81 * then. The reason for not letting clear_weakref() decref the callback
82 * right now is that if the callback goes away, that may in turn trigger
83 * another callback (if a weak reference to the callback exists) -- running
84 * arbitrary Python code in the middle of gc is a disaster. The convolution
85 * here allows gc to delay triggering such callbacks until the world is in
86 * a sane state again.
87 */
88void
89_PyWeakref_ClearRef(PyWeakReference *self)
90{
91 PyObject *callback;
92
93 assert(self != NULL);
94 assert(PyWeakref_Check(self));
95 /* Preserve and restore the callback around clear_weakref. */
96 callback = self->wr_callback;
97 self->wr_callback = NULL;
98 clear_weakref(self);
99 self->wr_callback = callback;
100}
Fred Drake8844d522001-10-05 21:52:26 +0000101
102static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000103weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000104{
Fred Drake0a4dd392004-07-02 18:57:45 +0000105 PyObject_GC_UnTrack(self);
106 clear_weakref((PyWeakReference *) self);
Christian Heimese93237d2007-12-19 02:37:44 +0000107 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000108}
109
110
111static int
112gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
113{
Thomas Woutersc6e55062006-04-15 21:47:09 +0000114 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000115 return 0;
116}
117
118
119static int
120gc_clear(PyWeakReference *self)
121{
122 clear_weakref(self);
123 return 0;
124}
125
126
127static PyObject *
128weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
129{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000130 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000131
Martin v. Löwis15e62742006-02-27 16:46:16 +0000132 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000133 PyObject *object = PyWeakref_GET_OBJECT(self);
134 Py_INCREF(object);
135 return (object);
136 }
137 return NULL;
138}
139
140
141static long
142weakref_hash(PyWeakReference *self)
143{
144 if (self->hash != -1)
145 return self->hash;
146 if (PyWeakref_GET_OBJECT(self) == Py_None) {
147 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
148 return -1;
149 }
150 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
151 return self->hash;
152}
Tim Peters403a2032003-11-20 21:21:46 +0000153
Fred Drake8844d522001-10-05 21:52:26 +0000154
155static PyObject *
156weakref_repr(PyWeakReference *self)
157{
158 char buffer[256];
159 if (PyWeakref_GET_OBJECT(self) == Py_None) {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000160 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
Fred Drake8844d522001-10-05 21:52:26 +0000161 }
162 else {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000163 char *name = NULL;
164 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
165 "__name__");
166 if (nameobj == NULL)
167 PyErr_Clear();
168 else if (PyString_Check(nameobj))
169 name = PyString_AS_STRING(nameobj);
Barry Warsawd5867562001-11-28 21:01:56 +0000170 PyOS_snprintf(buffer, sizeof(buffer),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000171 name ? "<weakref at %p; to '%.50s' at %p (%s)>"
172 : "<weakref at %p; to '%.50s' at %p>",
173 self,
174 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
175 PyWeakref_GET_OBJECT(self),
176 name);
177 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000178 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000179 return PyString_FromString(buffer);
Fred Drake8844d522001-10-05 21:52:26 +0000180}
181
182/* Weak references only support equality, not ordering. Two weak references
183 are equal if the underlying objects are equal. If the underlying object has
184 gone away, they are equal if they are identical. */
185
186static PyObject *
187weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
188{
Antoine Pitroub704eab2012-11-11 19:36:51 +0100189 if ((op != Py_EQ && op != Py_NE) || self->ob_type != other->ob_type) {
Fred Drake8844d522001-10-05 21:52:26 +0000190 Py_INCREF(Py_NotImplemented);
191 return Py_NotImplemented;
192 }
193 if (PyWeakref_GET_OBJECT(self) == Py_None
194 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroub704eab2012-11-11 19:36:51 +0100195 int res = (self == other);
196 if (op == Py_NE)
197 res = !res;
198 if (res)
199 Py_RETURN_TRUE;
200 else
201 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000202 }
203 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
204 PyWeakref_GET_OBJECT(other), op);
205}
206
Fred Drake0a4dd392004-07-02 18:57:45 +0000207/* Given the head of an object's list of weak references, extract the
208 * two callback-less refs (ref and proxy). Used to determine if the
209 * shared references exist and to determine the back link for newly
210 * inserted references.
211 */
212static void
213get_basic_refs(PyWeakReference *head,
214 PyWeakReference **refp, PyWeakReference **proxyp)
215{
216 *refp = NULL;
217 *proxyp = NULL;
218
219 if (head != NULL && head->wr_callback == NULL) {
220 /* We need to be careful that the "basic refs" aren't
221 subclasses of the main types. That complicates this a
222 little. */
223 if (PyWeakref_CheckRefExact(head)) {
224 *refp = head;
225 head = head->wr_next;
226 }
227 if (head != NULL
228 && head->wr_callback == NULL
229 && PyWeakref_CheckProxy(head)) {
230 *proxyp = head;
231 /* head = head->wr_next; */
232 }
233 }
234}
235
236/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
237static void
238insert_after(PyWeakReference *newref, PyWeakReference *prev)
239{
240 newref->wr_prev = prev;
241 newref->wr_next = prev->wr_next;
242 if (prev->wr_next != NULL)
243 prev->wr_next->wr_prev = newref;
244 prev->wr_next = newref;
245}
246
247/* Insert 'newref' at the head of the list; 'list' points to the variable
248 * that stores the head.
249 */
250static void
251insert_head(PyWeakReference *newref, PyWeakReference **list)
252{
253 PyWeakReference *next = *list;
254
255 newref->wr_prev = NULL;
256 newref->wr_next = next;
257 if (next != NULL)
258 next->wr_prev = newref;
259 *list = newref;
260}
261
262static int
263parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
264 PyObject **obp, PyObject **callbackp)
265{
266 /* XXX Should check that kwargs == NULL or is empty. */
267 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
268}
269
270static PyObject *
271weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
272{
273 PyWeakReference *self = NULL;
274 PyObject *ob, *callback = NULL;
275
276 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
277 PyWeakReference *ref, *proxy;
278 PyWeakReference **list;
279
Christian Heimese93237d2007-12-19 02:37:44 +0000280 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000281 PyErr_Format(PyExc_TypeError,
282 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000283 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000284 return NULL;
285 }
286 if (callback == Py_None)
287 callback = NULL;
288 list = GET_WEAKREFS_LISTPTR(ob);
289 get_basic_refs(*list, &ref, &proxy);
290 if (callback == NULL && type == &_PyWeakref_RefType) {
291 if (ref != NULL) {
292 /* We can re-use an existing reference. */
293 Py_INCREF(ref);
294 return (PyObject *)ref;
295 }
296 }
297 /* We have to create a new reference. */
298 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
299 list on ob can be mutated. This means that the ref and
300 proxy pointers we got back earlier may have been collected,
301 so we need to compute these values again before we use
302 them. */
303 self = (PyWeakReference *) (type->tp_alloc(type, 0));
304 if (self != NULL) {
305 init_weakref(self, ob, callback);
306 if (callback == NULL && type == &_PyWeakref_RefType) {
307 insert_head(self, list);
308 }
309 else {
310 PyWeakReference *prev;
311
312 get_basic_refs(*list, &ref, &proxy);
313 prev = (proxy == NULL) ? ref : proxy;
314 if (prev == NULL)
315 insert_head(self, list);
316 else
317 insert_after(self, prev);
318 }
319 }
320 }
321 return (PyObject *)self;
322}
323
324static int
325weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
326{
327 PyObject *tmp;
328
329 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
330 return 0;
331 else
Benjamin Peterson97179b02008-09-09 20:55:01 +0000332 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000333}
334
Fred Drake8844d522001-10-05 21:52:26 +0000335
336PyTypeObject
337_PyWeakref_RefType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000338 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000339 "weakref",
340 sizeof(PyWeakReference),
341 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000342 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000343 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000344 0, /*tp_getattr*/
345 0, /*tp_setattr*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000346 0, /*tp_compare*/
Fred Drake8844d522001-10-05 21:52:26 +0000347 (reprfunc)weakref_repr, /*tp_repr*/
348 0, /*tp_as_number*/
349 0, /*tp_as_sequence*/
350 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000351 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000352 (ternaryfunc)weakref_call, /*tp_call*/
353 0, /*tp_str*/
354 0, /*tp_getattro*/
355 0, /*tp_setattro*/
356 0, /*tp_as_buffer*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000357 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
358 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000359 0, /*tp_doc*/
360 (traverseproc)gc_traverse, /*tp_traverse*/
361 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000362 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000363 0, /*tp_weaklistoffset*/
364 0, /*tp_iter*/
365 0, /*tp_iternext*/
366 0, /*tp_methods*/
367 0, /*tp_members*/
368 0, /*tp_getset*/
369 0, /*tp_base*/
370 0, /*tp_dict*/
371 0, /*tp_descr_get*/
372 0, /*tp_descr_set*/
373 0, /*tp_dictoffset*/
Georg Brandl347b3002006-03-30 11:57:00 +0000374 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000375 PyType_GenericAlloc, /*tp_alloc*/
376 weakref___new__, /*tp_new*/
377 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000378};
379
380
381static int
382proxy_checkref(PyWeakReference *proxy)
383{
384 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
385 PyErr_SetString(PyExc_ReferenceError,
386 "weakly-referenced object no longer exists");
387 return 0;
388 }
389 return 1;
390}
391
392
Fred Drake73006d02001-10-18 18:04:18 +0000393/* If a parameter is a proxy, check that it is still "live" and wrap it,
394 * replacing the original value with the raw object. Raises ReferenceError
395 * if the param is a dead proxy.
396 */
397#define UNWRAP(o) \
398 if (PyWeakref_CheckProxy(o)) { \
399 if (!proxy_checkref((PyWeakReference *)o)) \
400 return NULL; \
401 o = PyWeakref_GET_OBJECT(o); \
402 }
403
Fred Drake2a908f62001-12-19 16:44:30 +0000404#define UNWRAP_I(o) \
405 if (PyWeakref_CheckProxy(o)) { \
406 if (!proxy_checkref((PyWeakReference *)o)) \
407 return -1; \
408 o = PyWeakref_GET_OBJECT(o); \
409 }
410
Fred Drake8844d522001-10-05 21:52:26 +0000411#define WRAP_UNARY(method, generic) \
412 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000413 method(PyObject *proxy) { \
414 UNWRAP(proxy); \
415 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000416 }
417
418#define WRAP_BINARY(method, generic) \
419 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000420 method(PyObject *x, PyObject *y) { \
421 UNWRAP(x); \
422 UNWRAP(y); \
423 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000424 }
425
Fred Drake31f4d1f2001-10-18 19:21:46 +0000426/* Note that the third arg needs to be checked for NULL since the tp_call
427 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000428 */
Fred Drake8844d522001-10-05 21:52:26 +0000429#define WRAP_TERNARY(method, generic) \
430 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000431 method(PyObject *proxy, PyObject *v, PyObject *w) { \
432 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000433 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000434 if (w != NULL) \
435 UNWRAP(w); \
436 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000437 }
438
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000439#define WRAP_METHOD(method, special) \
440 static PyObject * \
441 method(PyObject *proxy) { \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000442 UNWRAP(proxy); \
443 return PyObject_CallMethod(proxy, special, ""); \
444 }
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000445
Fred Drake8844d522001-10-05 21:52:26 +0000446
447/* direct slots */
448
449WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
450WRAP_UNARY(proxy_str, PyObject_Str)
451WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
452
Fred Drake8844d522001-10-05 21:52:26 +0000453static PyObject *
454proxy_repr(PyWeakReference *proxy)
455{
456 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000457 PyOS_snprintf(buf, sizeof(buf),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000458 "<weakproxy at %p to %.100s at %p>", proxy,
459 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
460 PyWeakref_GET_OBJECT(proxy));
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000461 return PyString_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000462}
463
464
465static int
466proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
467{
468 if (!proxy_checkref(proxy))
469 return -1;
470 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
471}
472
473static int
Fred Drake2a908f62001-12-19 16:44:30 +0000474proxy_compare(PyObject *proxy, PyObject *v)
Fred Drake8844d522001-10-05 21:52:26 +0000475{
Fred Drake2a908f62001-12-19 16:44:30 +0000476 UNWRAP_I(proxy);
477 UNWRAP_I(v);
478 return PyObject_Compare(proxy, v);
Fred Drake8844d522001-10-05 21:52:26 +0000479}
480
481/* number slots */
482WRAP_BINARY(proxy_add, PyNumber_Add)
483WRAP_BINARY(proxy_sub, PyNumber_Subtract)
484WRAP_BINARY(proxy_mul, PyNumber_Multiply)
485WRAP_BINARY(proxy_div, PyNumber_Divide)
Georg Brandl88659b02008-05-20 08:40:43 +0000486WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
487WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000488WRAP_BINARY(proxy_mod, PyNumber_Remainder)
489WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
490WRAP_TERNARY(proxy_pow, PyNumber_Power)
491WRAP_UNARY(proxy_neg, PyNumber_Negative)
492WRAP_UNARY(proxy_pos, PyNumber_Positive)
493WRAP_UNARY(proxy_abs, PyNumber_Absolute)
494WRAP_UNARY(proxy_invert, PyNumber_Invert)
495WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
496WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
497WRAP_BINARY(proxy_and, PyNumber_And)
498WRAP_BINARY(proxy_xor, PyNumber_Xor)
499WRAP_BINARY(proxy_or, PyNumber_Or)
500WRAP_UNARY(proxy_int, PyNumber_Int)
501WRAP_UNARY(proxy_long, PyNumber_Long)
502WRAP_UNARY(proxy_float, PyNumber_Float)
503WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
504WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
505WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
506WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
Georg Brandl88659b02008-05-20 08:40:43 +0000507WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
508WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000509WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
510WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
511WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
512WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
513WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
514WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
515WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandl88659b02008-05-20 08:40:43 +0000516WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000517
Tim Peters403a2032003-11-20 21:21:46 +0000518static int
Fred Drake8844d522001-10-05 21:52:26 +0000519proxy_nonzero(PyWeakReference *proxy)
520{
521 PyObject *o = PyWeakref_GET_OBJECT(proxy);
522 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000523 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000524 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000525}
526
Fred Drake0a4dd392004-07-02 18:57:45 +0000527static void
528proxy_dealloc(PyWeakReference *self)
529{
530 if (self->wr_callback != NULL)
531 PyObject_GC_UnTrack((PyObject *)self);
532 clear_weakref(self);
533 PyObject_GC_Del(self);
534}
535
Fred Drake8844d522001-10-05 21:52:26 +0000536/* sequence slots */
537
538static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000539proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
Fred Drake8844d522001-10-05 21:52:26 +0000540{
541 if (!proxy_checkref(proxy))
542 return NULL;
543 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
544}
545
546static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000547proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
Fred Drake8844d522001-10-05 21:52:26 +0000548{
549 if (!proxy_checkref(proxy))
550 return -1;
551 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
552}
553
554static int
555proxy_contains(PyWeakReference *proxy, PyObject *value)
556{
557 if (!proxy_checkref(proxy))
558 return -1;
559 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
560}
561
562
563/* mapping slots */
564
Martin v. Löwis18e16552006-02-15 17:27:45 +0000565static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000566proxy_length(PyWeakReference *proxy)
567{
568 if (!proxy_checkref(proxy))
569 return -1;
570 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
571}
572
573WRAP_BINARY(proxy_getitem, PyObject_GetItem)
574
575static int
576proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
577{
578 if (!proxy_checkref(proxy))
579 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000580
581 if (value == NULL)
582 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
583 else
584 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000585}
586
Fred Drakef16c3dc2002-08-09 18:34:16 +0000587/* iterator slots */
588
589static PyObject *
590proxy_iter(PyWeakReference *proxy)
591{
592 if (!proxy_checkref(proxy))
593 return NULL;
594 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
595}
596
597static PyObject *
598proxy_iternext(PyWeakReference *proxy)
599{
600 if (!proxy_checkref(proxy))
601 return NULL;
602 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
603}
604
Fred Drake8844d522001-10-05 21:52:26 +0000605
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000606WRAP_METHOD(proxy_unicode, "__unicode__");
607
608
609static PyMethodDef proxy_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000610 {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS},
611 {NULL, NULL}
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000612};
613
614
Fred Drake8844d522001-10-05 21:52:26 +0000615static PyNumberMethods proxy_as_number = {
Georg Brandl347b3002006-03-30 11:57:00 +0000616 proxy_add, /*nb_add*/
617 proxy_sub, /*nb_subtract*/
618 proxy_mul, /*nb_multiply*/
619 proxy_div, /*nb_divide*/
620 proxy_mod, /*nb_remainder*/
621 proxy_divmod, /*nb_divmod*/
622 proxy_pow, /*nb_power*/
623 proxy_neg, /*nb_negative*/
624 proxy_pos, /*nb_positive*/
625 proxy_abs, /*nb_absolute*/
626 (inquiry)proxy_nonzero, /*nb_nonzero*/
627 proxy_invert, /*nb_invert*/
628 proxy_lshift, /*nb_lshift*/
629 proxy_rshift, /*nb_rshift*/
630 proxy_and, /*nb_and*/
631 proxy_xor, /*nb_xor*/
632 proxy_or, /*nb_or*/
633 0, /*nb_coerce*/
634 proxy_int, /*nb_int*/
635 proxy_long, /*nb_long*/
636 proxy_float, /*nb_float*/
637 0, /*nb_oct*/
638 0, /*nb_hex*/
639 proxy_iadd, /*nb_inplace_add*/
640 proxy_isub, /*nb_inplace_subtract*/
641 proxy_imul, /*nb_inplace_multiply*/
642 proxy_idiv, /*nb_inplace_divide*/
643 proxy_imod, /*nb_inplace_remainder*/
644 proxy_ipow, /*nb_inplace_power*/
645 proxy_ilshift, /*nb_inplace_lshift*/
646 proxy_irshift, /*nb_inplace_rshift*/
647 proxy_iand, /*nb_inplace_and*/
648 proxy_ixor, /*nb_inplace_xor*/
649 proxy_ior, /*nb_inplace_or*/
Georg Brandl88659b02008-05-20 08:40:43 +0000650 proxy_floor_div, /*nb_floor_divide*/
651 proxy_true_div, /*nb_true_divide*/
652 proxy_ifloor_div, /*nb_inplace_floor_divide*/
653 proxy_itrue_div, /*nb_inplace_true_divide*/
654 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000655};
656
657static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000658 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000659 0, /*sq_concat*/
660 0, /*sq_repeat*/
661 0, /*sq_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000662 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000663 0, /*sq_ass_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000664 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000665 (objobjproc)proxy_contains, /* sq_contains */
666};
667
668static PyMappingMethods proxy_as_mapping = {
Georg Brandl347b3002006-03-30 11:57:00 +0000669 (lenfunc)proxy_length, /*mp_length*/
670 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000671 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
672};
673
674
675PyTypeObject
676_PyWeakref_ProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000677 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000678 "weakproxy",
679 sizeof(PyWeakReference),
680 0,
681 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000682 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000683 0, /* tp_print */
684 0, /* tp_getattr */
685 0, /* tp_setattr */
686 proxy_compare, /* tp_compare */
687 (reprfunc)proxy_repr, /* tp_repr */
688 &proxy_as_number, /* tp_as_number */
689 &proxy_as_sequence, /* tp_as_sequence */
690 &proxy_as_mapping, /* tp_as_mapping */
691 0, /* tp_hash */
692 0, /* tp_call */
Georg Brandl347b3002006-03-30 11:57:00 +0000693 proxy_str, /* tp_str */
694 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000695 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000696 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000697 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000698 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
699 0, /* tp_doc */
700 (traverseproc)gc_traverse, /* tp_traverse */
701 (inquiry)gc_clear, /* tp_clear */
702 0, /* tp_richcompare */
703 0, /* tp_weaklistoffset */
704 (getiterfunc)proxy_iter, /* tp_iter */
705 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000706 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000707};
708
709
710PyTypeObject
711_PyWeakref_CallableProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000712 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000713 "weakcallableproxy",
714 sizeof(PyWeakReference),
715 0,
716 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000717 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000718 0, /* tp_print */
719 0, /* tp_getattr */
720 0, /* tp_setattr */
721 proxy_compare, /* tp_compare */
722 (unaryfunc)proxy_repr, /* tp_repr */
723 &proxy_as_number, /* tp_as_number */
724 &proxy_as_sequence, /* tp_as_sequence */
725 &proxy_as_mapping, /* tp_as_mapping */
726 0, /* tp_hash */
727 proxy_call, /* tp_call */
728 proxy_str, /* tp_str */
Georg Brandl347b3002006-03-30 11:57:00 +0000729 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000730 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000731 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000732 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000733 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
734 0, /* tp_doc */
735 (traverseproc)gc_traverse, /* tp_traverse */
736 (inquiry)gc_clear, /* tp_clear */
737 0, /* tp_richcompare */
738 0, /* tp_weaklistoffset */
739 (getiterfunc)proxy_iter, /* tp_iter */
740 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000741};
742
743
Fred Drake8844d522001-10-05 21:52:26 +0000744
745PyObject *
746PyWeakref_NewRef(PyObject *ob, PyObject *callback)
747{
748 PyWeakReference *result = NULL;
749 PyWeakReference **list;
750 PyWeakReference *ref, *proxy;
751
Christian Heimese93237d2007-12-19 02:37:44 +0000752 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000753 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000754 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000755 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000756 return NULL;
757 }
758 list = GET_WEAKREFS_LISTPTR(ob);
759 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000760 if (callback == Py_None)
761 callback = NULL;
762 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000763 /* return existing weak reference if it exists */
764 result = ref;
765 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000766 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000767 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000768 /* Note: new_weakref() can trigger cyclic GC, so the weakref
769 list on ob can be mutated. This means that the ref and
770 proxy pointers we got back earlier may have been collected,
771 so we need to compute these values again before we use
772 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000773 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000774 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000775 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000776 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000777 if (ref == NULL)
778 insert_head(result, list);
779 else {
780 /* Someone else added a ref without a callback
781 during GC. Return that one instead of this one
782 to avoid violating the invariants of the list
783 of weakrefs for ob. */
784 Py_DECREF(result);
785 Py_INCREF(ref);
786 result = ref;
787 }
Fred Drake8844d522001-10-05 21:52:26 +0000788 }
789 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000790 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000791
Fred Drakebc875f52004-02-04 23:14:14 +0000792 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000793 if (prev == NULL)
794 insert_head(result, list);
795 else
796 insert_after(result, prev);
797 }
Fred Drake8844d522001-10-05 21:52:26 +0000798 }
799 }
800 return (PyObject *) result;
801}
802
803
804PyObject *
805PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
806{
807 PyWeakReference *result = NULL;
808 PyWeakReference **list;
809 PyWeakReference *ref, *proxy;
810
Christian Heimese93237d2007-12-19 02:37:44 +0000811 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000812 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000813 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000814 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000815 return NULL;
816 }
817 list = GET_WEAKREFS_LISTPTR(ob);
818 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000819 if (callback == Py_None)
820 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000821 if (callback == NULL)
822 /* attempt to return an existing weak reference if it exists */
823 result = proxy;
824 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000825 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000826 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000827 /* Note: new_weakref() can trigger cyclic GC, so the weakref
828 list on ob can be mutated. This means that the ref and
829 proxy pointers we got back earlier may have been collected,
830 so we need to compute these values again before we use
831 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000832 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000833 if (result != NULL) {
834 PyWeakReference *prev;
835
836 if (PyCallable_Check(ob))
Christian Heimese93237d2007-12-19 02:37:44 +0000837 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000838 else
Christian Heimese93237d2007-12-19 02:37:44 +0000839 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000840 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000841 if (callback == NULL) {
842 if (proxy != NULL) {
843 /* Someone else added a proxy without a callback
844 during GC. Return that one instead of this one
845 to avoid violating the invariants of the list
846 of weakrefs for ob. */
847 Py_DECREF(result);
848 Py_INCREF(result = proxy);
849 goto skip_insert;
850 }
Fred Drake8844d522001-10-05 21:52:26 +0000851 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000852 }
Fred Drake8844d522001-10-05 21:52:26 +0000853 else
854 prev = (proxy == NULL) ? ref : proxy;
855
856 if (prev == NULL)
857 insert_head(result, list);
858 else
859 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000860 skip_insert:
861 ;
Fred Drake8844d522001-10-05 21:52:26 +0000862 }
863 }
864 return (PyObject *) result;
865}
866
867
868PyObject *
869PyWeakref_GetObject(PyObject *ref)
870{
871 if (ref == NULL || !PyWeakref_Check(ref)) {
872 PyErr_BadInternalCall();
873 return NULL;
874 }
875 return PyWeakref_GET_OBJECT(ref);
876}
877
Tim Petersead8b7a2004-10-30 23:09:22 +0000878/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
879 * handle_weakrefs().
880 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000881static void
882handle_callback(PyWeakReference *ref, PyObject *callback)
883{
Georg Brandl684fd0c2006-05-25 19:15:31 +0000884 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000885
886 if (cbresult == NULL)
887 PyErr_WriteUnraisable(callback);
888 else
889 Py_DECREF(cbresult);
890}
891
892/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000893 *
894 * This iterates through the weak references for 'object' and calls callbacks
895 * for those references which have one. It returns when all callbacks have
896 * been attempted.
897 */
898void
899PyObject_ClearWeakRefs(PyObject *object)
900{
901 PyWeakReference **list;
902
903 if (object == NULL
Christian Heimese93237d2007-12-19 02:37:44 +0000904 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000905 || object->ob_refcnt != 0) {
906 PyErr_BadInternalCall();
907 return;
908 }
909 list = GET_WEAKREFS_LISTPTR(object);
910 /* Remove the callback-less basic and proxy references */
911 if (*list != NULL && (*list)->wr_callback == NULL) {
912 clear_weakref(*list);
913 if (*list != NULL && (*list)->wr_callback == NULL)
914 clear_weakref(*list);
915 }
916 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000917 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000918 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000919 int restore_error = PyErr_Occurred() ? 1 : 0;
920 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000921
Fred Drakeef8ebd12001-12-10 23:44:54 +0000922 if (restore_error)
923 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000924 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000925 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000926
Fred Drakeef8ebd12001-12-10 23:44:54 +0000927 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000928 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000929 if (callback != NULL) {
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000930 if (current->ob_refcnt > 0)
931 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000932 Py_DECREF(callback);
933 }
Fred Drake8844d522001-10-05 21:52:26 +0000934 }
935 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000936 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000937 Py_ssize_t i = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000938
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000939 tuple = PyTuple_New(count * 2);
940 if (tuple == NULL) {
941 if (restore_error)
942 PyErr_Fetch(&err_type, &err_value, &err_tb);
943 return;
944 }
Fred Drake8844d522001-10-05 21:52:26 +0000945
946 for (i = 0; i < count; ++i) {
947 PyWeakReference *next = current->wr_next;
948
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000949 if (current->ob_refcnt > 0)
950 {
951 Py_INCREF(current);
952 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
953 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
954 }
955 else {
956 Py_DECREF(current->wr_callback);
957 }
Fred Drake8844d522001-10-05 21:52:26 +0000958 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000959 clear_weakref(current);
960 current = next;
961 }
962 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000963 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000964
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000965 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000966 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000967 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
968 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000969 }
Fred Drake8844d522001-10-05 21:52:26 +0000970 }
971 Py_DECREF(tuple);
972 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000973 if (restore_error)
974 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000975 }
976}