blob: 7b943b0f00491bde7a2a88a2d6802d92d59dd5f5 [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
55 if (PyWeakref_GET_OBJECT(self) != Py_None) {
56 PyWeakReference **list = GET_WEAKREFS_LISTPTR(
57 PyWeakref_GET_OBJECT(self));
58
59 if (*list == self)
Antoine Pitrouc83ea132010-05-09 14:46:46 +000060 /* If 'self' is the end of the list (and thus self->wr_next == NULL)
61 then the weakref list itself (and thus the value of *list) will
62 end up being set to NULL. */
Fred Drake8844d522001-10-05 21:52:26 +000063 *list = self->wr_next;
64 self->wr_object = Py_None;
Fred Drake8844d522001-10-05 21:52:26 +000065 if (self->wr_prev != NULL)
66 self->wr_prev->wr_next = self->wr_next;
67 if (self->wr_next != NULL)
68 self->wr_next->wr_prev = self->wr_prev;
69 self->wr_prev = NULL;
70 self->wr_next = NULL;
Tim Peters403a2032003-11-20 21:21:46 +000071 }
72 if (callback != NULL) {
73 Py_DECREF(callback);
74 self->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +000075 }
76}
77
Tim Peters403a2032003-11-20 21:21:46 +000078/* Cyclic gc uses this to *just* clear the passed-in reference, leaving
79 * the callback intact and uncalled. It must be possible to call self's
80 * tp_dealloc() after calling this, so self has to be left in a sane enough
81 * state for that to work. We expect tp_dealloc to decref the callback
82 * then. The reason for not letting clear_weakref() decref the callback
83 * right now is that if the callback goes away, that may in turn trigger
84 * another callback (if a weak reference to the callback exists) -- running
85 * arbitrary Python code in the middle of gc is a disaster. The convolution
86 * here allows gc to delay triggering such callbacks until the world is in
87 * a sane state again.
88 */
89void
90_PyWeakref_ClearRef(PyWeakReference *self)
91{
92 PyObject *callback;
93
94 assert(self != NULL);
95 assert(PyWeakref_Check(self));
96 /* Preserve and restore the callback around clear_weakref. */
97 callback = self->wr_callback;
98 self->wr_callback = NULL;
99 clear_weakref(self);
100 self->wr_callback = callback;
101}
Fred Drake8844d522001-10-05 21:52:26 +0000102
103static void
Fred Drake0a4dd392004-07-02 18:57:45 +0000104weakref_dealloc(PyObject *self)
Fred Drake8844d522001-10-05 21:52:26 +0000105{
Fred Drake0a4dd392004-07-02 18:57:45 +0000106 PyObject_GC_UnTrack(self);
107 clear_weakref((PyWeakReference *) self);
Christian Heimese93237d2007-12-19 02:37:44 +0000108 Py_TYPE(self)->tp_free(self);
Fred Drake8844d522001-10-05 21:52:26 +0000109}
110
111
112static int
113gc_traverse(PyWeakReference *self, visitproc visit, void *arg)
114{
Thomas Woutersc6e55062006-04-15 21:47:09 +0000115 Py_VISIT(self->wr_callback);
Fred Drake8844d522001-10-05 21:52:26 +0000116 return 0;
117}
118
119
120static int
121gc_clear(PyWeakReference *self)
122{
123 clear_weakref(self);
124 return 0;
125}
126
127
128static PyObject *
129weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw)
130{
Martin v. Löwis15e62742006-02-27 16:46:16 +0000131 static char *kwlist[] = {NULL};
Fred Drake8844d522001-10-05 21:52:26 +0000132
Martin v. Löwis15e62742006-02-27 16:46:16 +0000133 if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) {
Fred Drake8844d522001-10-05 21:52:26 +0000134 PyObject *object = PyWeakref_GET_OBJECT(self);
135 Py_INCREF(object);
136 return (object);
137 }
138 return NULL;
139}
140
141
142static long
143weakref_hash(PyWeakReference *self)
144{
145 if (self->hash != -1)
146 return self->hash;
147 if (PyWeakref_GET_OBJECT(self) == Py_None) {
148 PyErr_SetString(PyExc_TypeError, "weak object has gone away");
149 return -1;
150 }
151 self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self));
152 return self->hash;
153}
Tim Peters403a2032003-11-20 21:21:46 +0000154
Fred Drake8844d522001-10-05 21:52:26 +0000155
156static PyObject *
157weakref_repr(PyWeakReference *self)
158{
159 char buffer[256];
160 if (PyWeakref_GET_OBJECT(self) == Py_None) {
Guido van Rossumc1f6e8c2003-04-16 21:13:23 +0000161 PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self);
Fred Drake8844d522001-10-05 21:52:26 +0000162 }
163 else {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000164 char *name = NULL;
165 PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self),
166 "__name__");
167 if (nameobj == NULL)
168 PyErr_Clear();
169 else if (PyString_Check(nameobj))
170 name = PyString_AS_STRING(nameobj);
Barry Warsawd5867562001-11-28 21:01:56 +0000171 PyOS_snprintf(buffer, sizeof(buffer),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000172 name ? "<weakref at %p; to '%.50s' at %p (%s)>"
173 : "<weakref at %p; to '%.50s' at %p>",
174 self,
175 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
176 PyWeakref_GET_OBJECT(self),
177 name);
178 Py_XDECREF(nameobj);
Fred Drake8844d522001-10-05 21:52:26 +0000179 }
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000180 return PyString_FromString(buffer);
Fred Drake8844d522001-10-05 21:52:26 +0000181}
182
183/* Weak references only support equality, not ordering. Two weak references
184 are equal if the underlying objects are equal. If the underlying object has
185 gone away, they are equal if they are identical. */
186
187static PyObject *
188weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
189{
Antoine Pitroub704eab2012-11-11 19:36:51 +0100190 if ((op != Py_EQ && op != Py_NE) || self->ob_type != other->ob_type) {
Fred Drake8844d522001-10-05 21:52:26 +0000191 Py_INCREF(Py_NotImplemented);
192 return Py_NotImplemented;
193 }
194 if (PyWeakref_GET_OBJECT(self) == Py_None
195 || PyWeakref_GET_OBJECT(other) == Py_None) {
Antoine Pitroub704eab2012-11-11 19:36:51 +0100196 int res = (self == other);
197 if (op == Py_NE)
198 res = !res;
199 if (res)
200 Py_RETURN_TRUE;
201 else
202 Py_RETURN_FALSE;
Fred Drake8844d522001-10-05 21:52:26 +0000203 }
204 return PyObject_RichCompare(PyWeakref_GET_OBJECT(self),
205 PyWeakref_GET_OBJECT(other), op);
206}
207
Fred Drake0a4dd392004-07-02 18:57:45 +0000208/* Given the head of an object's list of weak references, extract the
209 * two callback-less refs (ref and proxy). Used to determine if the
210 * shared references exist and to determine the back link for newly
211 * inserted references.
212 */
213static void
214get_basic_refs(PyWeakReference *head,
215 PyWeakReference **refp, PyWeakReference **proxyp)
216{
217 *refp = NULL;
218 *proxyp = NULL;
219
220 if (head != NULL && head->wr_callback == NULL) {
221 /* We need to be careful that the "basic refs" aren't
222 subclasses of the main types. That complicates this a
223 little. */
224 if (PyWeakref_CheckRefExact(head)) {
225 *refp = head;
226 head = head->wr_next;
227 }
228 if (head != NULL
229 && head->wr_callback == NULL
230 && PyWeakref_CheckProxy(head)) {
231 *proxyp = head;
232 /* head = head->wr_next; */
233 }
234 }
235}
236
237/* Insert 'newref' in the list after 'prev'. Both must be non-NULL. */
238static void
239insert_after(PyWeakReference *newref, PyWeakReference *prev)
240{
241 newref->wr_prev = prev;
242 newref->wr_next = prev->wr_next;
243 if (prev->wr_next != NULL)
244 prev->wr_next->wr_prev = newref;
245 prev->wr_next = newref;
246}
247
248/* Insert 'newref' at the head of the list; 'list' points to the variable
249 * that stores the head.
250 */
251static void
252insert_head(PyWeakReference *newref, PyWeakReference **list)
253{
254 PyWeakReference *next = *list;
255
256 newref->wr_prev = NULL;
257 newref->wr_next = next;
258 if (next != NULL)
259 next->wr_prev = newref;
260 *list = newref;
261}
262
263static int
264parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs,
265 PyObject **obp, PyObject **callbackp)
266{
267 /* XXX Should check that kwargs == NULL or is empty. */
268 return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
269}
270
271static PyObject *
272weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
273{
274 PyWeakReference *self = NULL;
275 PyObject *ob, *callback = NULL;
276
277 if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
278 PyWeakReference *ref, *proxy;
279 PyWeakReference **list;
280
Christian Heimese93237d2007-12-19 02:37:44 +0000281 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake0a4dd392004-07-02 18:57:45 +0000282 PyErr_Format(PyExc_TypeError,
283 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000284 Py_TYPE(ob)->tp_name);
Fred Drake0a4dd392004-07-02 18:57:45 +0000285 return NULL;
286 }
287 if (callback == Py_None)
288 callback = NULL;
289 list = GET_WEAKREFS_LISTPTR(ob);
290 get_basic_refs(*list, &ref, &proxy);
291 if (callback == NULL && type == &_PyWeakref_RefType) {
292 if (ref != NULL) {
293 /* We can re-use an existing reference. */
294 Py_INCREF(ref);
295 return (PyObject *)ref;
296 }
297 }
298 /* We have to create a new reference. */
299 /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
300 list on ob can be mutated. This means that the ref and
301 proxy pointers we got back earlier may have been collected,
302 so we need to compute these values again before we use
303 them. */
304 self = (PyWeakReference *) (type->tp_alloc(type, 0));
305 if (self != NULL) {
306 init_weakref(self, ob, callback);
307 if (callback == NULL && type == &_PyWeakref_RefType) {
308 insert_head(self, list);
309 }
310 else {
311 PyWeakReference *prev;
312
313 get_basic_refs(*list, &ref, &proxy);
314 prev = (proxy == NULL) ? ref : proxy;
315 if (prev == NULL)
316 insert_head(self, list);
317 else
318 insert_after(self, prev);
319 }
320 }
321 }
322 return (PyObject *)self;
323}
324
325static int
326weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
327{
328 PyObject *tmp;
329
330 if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
331 return 0;
332 else
Benjamin Peterson97179b02008-09-09 20:55:01 +0000333 return -1;
Fred Drake0a4dd392004-07-02 18:57:45 +0000334}
335
Fred Drake8844d522001-10-05 21:52:26 +0000336
337PyTypeObject
338_PyWeakref_RefType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000339 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000340 "weakref",
341 sizeof(PyWeakReference),
342 0,
Fred Drake0a4dd392004-07-02 18:57:45 +0000343 weakref_dealloc, /*tp_dealloc*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000344 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000345 0, /*tp_getattr*/
346 0, /*tp_setattr*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000347 0, /*tp_compare*/
Fred Drake8844d522001-10-05 21:52:26 +0000348 (reprfunc)weakref_repr, /*tp_repr*/
349 0, /*tp_as_number*/
350 0, /*tp_as_sequence*/
351 0, /*tp_as_mapping*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000352 (hashfunc)weakref_hash, /*tp_hash*/
Fred Drake8844d522001-10-05 21:52:26 +0000353 (ternaryfunc)weakref_call, /*tp_call*/
354 0, /*tp_str*/
355 0, /*tp_getattro*/
356 0, /*tp_setattro*/
357 0, /*tp_as_buffer*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000358 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE
359 | Py_TPFLAGS_BASETYPE, /*tp_flags*/
Fred Drake8844d522001-10-05 21:52:26 +0000360 0, /*tp_doc*/
361 (traverseproc)gc_traverse, /*tp_traverse*/
362 (inquiry)gc_clear, /*tp_clear*/
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000363 (richcmpfunc)weakref_richcompare, /*tp_richcompare*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000364 0, /*tp_weaklistoffset*/
365 0, /*tp_iter*/
366 0, /*tp_iternext*/
367 0, /*tp_methods*/
368 0, /*tp_members*/
369 0, /*tp_getset*/
370 0, /*tp_base*/
371 0, /*tp_dict*/
372 0, /*tp_descr_get*/
373 0, /*tp_descr_set*/
374 0, /*tp_dictoffset*/
Georg Brandl347b3002006-03-30 11:57:00 +0000375 weakref___init__, /*tp_init*/
Fred Drake0a4dd392004-07-02 18:57:45 +0000376 PyType_GenericAlloc, /*tp_alloc*/
377 weakref___new__, /*tp_new*/
378 PyObject_GC_Del, /*tp_free*/
Fred Drake8844d522001-10-05 21:52:26 +0000379};
380
381
382static int
383proxy_checkref(PyWeakReference *proxy)
384{
385 if (PyWeakref_GET_OBJECT(proxy) == Py_None) {
386 PyErr_SetString(PyExc_ReferenceError,
387 "weakly-referenced object no longer exists");
388 return 0;
389 }
390 return 1;
391}
392
393
Fred Drake73006d02001-10-18 18:04:18 +0000394/* If a parameter is a proxy, check that it is still "live" and wrap it,
395 * replacing the original value with the raw object. Raises ReferenceError
396 * if the param is a dead proxy.
397 */
398#define UNWRAP(o) \
399 if (PyWeakref_CheckProxy(o)) { \
400 if (!proxy_checkref((PyWeakReference *)o)) \
401 return NULL; \
402 o = PyWeakref_GET_OBJECT(o); \
403 }
404
Fred Drake2a908f62001-12-19 16:44:30 +0000405#define UNWRAP_I(o) \
406 if (PyWeakref_CheckProxy(o)) { \
407 if (!proxy_checkref((PyWeakReference *)o)) \
408 return -1; \
409 o = PyWeakref_GET_OBJECT(o); \
410 }
411
Fred Drake8844d522001-10-05 21:52:26 +0000412#define WRAP_UNARY(method, generic) \
413 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000414 method(PyObject *proxy) { \
415 UNWRAP(proxy); \
416 return generic(proxy); \
Fred Drake8844d522001-10-05 21:52:26 +0000417 }
418
419#define WRAP_BINARY(method, generic) \
420 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000421 method(PyObject *x, PyObject *y) { \
422 UNWRAP(x); \
423 UNWRAP(y); \
424 return generic(x, y); \
Fred Drake8844d522001-10-05 21:52:26 +0000425 }
426
Fred Drake31f4d1f2001-10-18 19:21:46 +0000427/* Note that the third arg needs to be checked for NULL since the tp_call
428 * slot can receive NULL for this arg.
Fred Drake73006d02001-10-18 18:04:18 +0000429 */
Fred Drake8844d522001-10-05 21:52:26 +0000430#define WRAP_TERNARY(method, generic) \
431 static PyObject * \
Fred Drake73006d02001-10-18 18:04:18 +0000432 method(PyObject *proxy, PyObject *v, PyObject *w) { \
433 UNWRAP(proxy); \
Fred Drake31f4d1f2001-10-18 19:21:46 +0000434 UNWRAP(v); \
Fred Drake73006d02001-10-18 18:04:18 +0000435 if (w != NULL) \
436 UNWRAP(w); \
437 return generic(proxy, v, w); \
Fred Drake8844d522001-10-05 21:52:26 +0000438 }
439
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000440#define WRAP_METHOD(method, special) \
441 static PyObject * \
442 method(PyObject *proxy) { \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000443 UNWRAP(proxy); \
444 return PyObject_CallMethod(proxy, special, ""); \
445 }
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000446
Fred Drake8844d522001-10-05 21:52:26 +0000447
448/* direct slots */
449
450WRAP_BINARY(proxy_getattr, PyObject_GetAttr)
451WRAP_UNARY(proxy_str, PyObject_Str)
452WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords)
453
Fred Drake8844d522001-10-05 21:52:26 +0000454static PyObject *
455proxy_repr(PyWeakReference *proxy)
456{
457 char buf[160];
Barry Warsawd5867562001-11-28 21:01:56 +0000458 PyOS_snprintf(buf, sizeof(buf),
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000459 "<weakproxy at %p to %.100s at %p>", proxy,
460 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
461 PyWeakref_GET_OBJECT(proxy));
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000462 return PyString_FromString(buf);
Fred Drake8844d522001-10-05 21:52:26 +0000463}
464
465
466static int
467proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value)
468{
469 if (!proxy_checkref(proxy))
470 return -1;
471 return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value);
472}
473
474static int
Fred Drake2a908f62001-12-19 16:44:30 +0000475proxy_compare(PyObject *proxy, PyObject *v)
Fred Drake8844d522001-10-05 21:52:26 +0000476{
Fred Drake2a908f62001-12-19 16:44:30 +0000477 UNWRAP_I(proxy);
478 UNWRAP_I(v);
479 return PyObject_Compare(proxy, v);
Fred Drake8844d522001-10-05 21:52:26 +0000480}
481
482/* number slots */
483WRAP_BINARY(proxy_add, PyNumber_Add)
484WRAP_BINARY(proxy_sub, PyNumber_Subtract)
485WRAP_BINARY(proxy_mul, PyNumber_Multiply)
486WRAP_BINARY(proxy_div, PyNumber_Divide)
Georg Brandl88659b02008-05-20 08:40:43 +0000487WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
488WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000489WRAP_BINARY(proxy_mod, PyNumber_Remainder)
490WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
491WRAP_TERNARY(proxy_pow, PyNumber_Power)
492WRAP_UNARY(proxy_neg, PyNumber_Negative)
493WRAP_UNARY(proxy_pos, PyNumber_Positive)
494WRAP_UNARY(proxy_abs, PyNumber_Absolute)
495WRAP_UNARY(proxy_invert, PyNumber_Invert)
496WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
497WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
498WRAP_BINARY(proxy_and, PyNumber_And)
499WRAP_BINARY(proxy_xor, PyNumber_Xor)
500WRAP_BINARY(proxy_or, PyNumber_Or)
501WRAP_UNARY(proxy_int, PyNumber_Int)
502WRAP_UNARY(proxy_long, PyNumber_Long)
503WRAP_UNARY(proxy_float, PyNumber_Float)
504WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
505WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
506WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
507WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide)
Georg Brandl88659b02008-05-20 08:40:43 +0000508WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
509WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000510WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
511WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
512WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
513WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
514WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
515WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
516WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandl88659b02008-05-20 08:40:43 +0000517WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000518
Tim Peters403a2032003-11-20 21:21:46 +0000519static int
Fred Drake8844d522001-10-05 21:52:26 +0000520proxy_nonzero(PyWeakReference *proxy)
521{
522 PyObject *o = PyWeakref_GET_OBJECT(proxy);
523 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000524 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000525 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000526}
527
Fred Drake0a4dd392004-07-02 18:57:45 +0000528static void
529proxy_dealloc(PyWeakReference *self)
530{
531 if (self->wr_callback != NULL)
532 PyObject_GC_UnTrack((PyObject *)self);
533 clear_weakref(self);
534 PyObject_GC_Del(self);
535}
536
Fred Drake8844d522001-10-05 21:52:26 +0000537/* sequence slots */
538
539static PyObject *
Martin v. Löwis18e16552006-02-15 17:27:45 +0000540proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j)
Fred Drake8844d522001-10-05 21:52:26 +0000541{
542 if (!proxy_checkref(proxy))
543 return NULL;
544 return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j);
545}
546
547static int
Martin v. Löwis18e16552006-02-15 17:27:45 +0000548proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value)
Fred Drake8844d522001-10-05 21:52:26 +0000549{
550 if (!proxy_checkref(proxy))
551 return -1;
552 return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value);
553}
554
555static int
556proxy_contains(PyWeakReference *proxy, PyObject *value)
557{
558 if (!proxy_checkref(proxy))
559 return -1;
560 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
561}
562
563
564/* mapping slots */
565
Martin v. Löwis18e16552006-02-15 17:27:45 +0000566static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000567proxy_length(PyWeakReference *proxy)
568{
569 if (!proxy_checkref(proxy))
570 return -1;
571 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
572}
573
574WRAP_BINARY(proxy_getitem, PyObject_GetItem)
575
576static int
577proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
578{
579 if (!proxy_checkref(proxy))
580 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000581
582 if (value == NULL)
583 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
584 else
585 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000586}
587
Fred Drakef16c3dc2002-08-09 18:34:16 +0000588/* iterator slots */
589
590static PyObject *
591proxy_iter(PyWeakReference *proxy)
592{
593 if (!proxy_checkref(proxy))
594 return NULL;
595 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
596}
597
598static PyObject *
599proxy_iternext(PyWeakReference *proxy)
600{
601 if (!proxy_checkref(proxy))
602 return NULL;
603 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
604}
605
Fred Drake8844d522001-10-05 21:52:26 +0000606
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000607WRAP_METHOD(proxy_unicode, "__unicode__");
608
609
610static PyMethodDef proxy_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000611 {"__unicode__", (PyCFunction)proxy_unicode, METH_NOARGS},
612 {NULL, NULL}
Benjamin Petersondc3c2392009-11-19 03:00:02 +0000613};
614
615
Fred Drake8844d522001-10-05 21:52:26 +0000616static PyNumberMethods proxy_as_number = {
Georg Brandl347b3002006-03-30 11:57:00 +0000617 proxy_add, /*nb_add*/
618 proxy_sub, /*nb_subtract*/
619 proxy_mul, /*nb_multiply*/
620 proxy_div, /*nb_divide*/
621 proxy_mod, /*nb_remainder*/
622 proxy_divmod, /*nb_divmod*/
623 proxy_pow, /*nb_power*/
624 proxy_neg, /*nb_negative*/
625 proxy_pos, /*nb_positive*/
626 proxy_abs, /*nb_absolute*/
627 (inquiry)proxy_nonzero, /*nb_nonzero*/
628 proxy_invert, /*nb_invert*/
629 proxy_lshift, /*nb_lshift*/
630 proxy_rshift, /*nb_rshift*/
631 proxy_and, /*nb_and*/
632 proxy_xor, /*nb_xor*/
633 proxy_or, /*nb_or*/
634 0, /*nb_coerce*/
635 proxy_int, /*nb_int*/
636 proxy_long, /*nb_long*/
637 proxy_float, /*nb_float*/
638 0, /*nb_oct*/
639 0, /*nb_hex*/
640 proxy_iadd, /*nb_inplace_add*/
641 proxy_isub, /*nb_inplace_subtract*/
642 proxy_imul, /*nb_inplace_multiply*/
643 proxy_idiv, /*nb_inplace_divide*/
644 proxy_imod, /*nb_inplace_remainder*/
645 proxy_ipow, /*nb_inplace_power*/
646 proxy_ilshift, /*nb_inplace_lshift*/
647 proxy_irshift, /*nb_inplace_rshift*/
648 proxy_iand, /*nb_inplace_and*/
649 proxy_ixor, /*nb_inplace_xor*/
650 proxy_ior, /*nb_inplace_or*/
Georg Brandl88659b02008-05-20 08:40:43 +0000651 proxy_floor_div, /*nb_floor_divide*/
652 proxy_true_div, /*nb_true_divide*/
653 proxy_ifloor_div, /*nb_inplace_floor_divide*/
654 proxy_itrue_div, /*nb_inplace_true_divide*/
655 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000656};
657
658static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000659 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000660 0, /*sq_concat*/
661 0, /*sq_repeat*/
662 0, /*sq_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000663 (ssizessizeargfunc)proxy_slice, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000664 0, /*sq_ass_item*/
Martin v. Löwis18e16552006-02-15 17:27:45 +0000665 (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000666 (objobjproc)proxy_contains, /* sq_contains */
667};
668
669static PyMappingMethods proxy_as_mapping = {
Georg Brandl347b3002006-03-30 11:57:00 +0000670 (lenfunc)proxy_length, /*mp_length*/
671 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000672 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
673};
674
675
676PyTypeObject
677_PyWeakref_ProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000678 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000679 "weakproxy",
680 sizeof(PyWeakReference),
681 0,
682 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000683 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000684 0, /* tp_print */
685 0, /* tp_getattr */
686 0, /* tp_setattr */
687 proxy_compare, /* tp_compare */
688 (reprfunc)proxy_repr, /* tp_repr */
689 &proxy_as_number, /* tp_as_number */
690 &proxy_as_sequence, /* tp_as_sequence */
691 &proxy_as_mapping, /* tp_as_mapping */
692 0, /* tp_hash */
693 0, /* tp_call */
Georg Brandl347b3002006-03-30 11:57:00 +0000694 proxy_str, /* tp_str */
695 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000696 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000697 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000698 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000699 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
700 0, /* tp_doc */
701 (traverseproc)gc_traverse, /* tp_traverse */
702 (inquiry)gc_clear, /* tp_clear */
703 0, /* tp_richcompare */
704 0, /* tp_weaklistoffset */
705 (getiterfunc)proxy_iter, /* tp_iter */
706 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000707 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000708};
709
710
711PyTypeObject
712_PyWeakref_CallableProxyType = {
Martin v. Löwis68192102007-07-21 06:55:02 +0000713 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000714 "weakcallableproxy",
715 sizeof(PyWeakReference),
716 0,
717 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000718 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000719 0, /* tp_print */
720 0, /* tp_getattr */
721 0, /* tp_setattr */
722 proxy_compare, /* tp_compare */
723 (unaryfunc)proxy_repr, /* tp_repr */
724 &proxy_as_number, /* tp_as_number */
725 &proxy_as_sequence, /* tp_as_sequence */
726 &proxy_as_mapping, /* tp_as_mapping */
727 0, /* tp_hash */
728 proxy_call, /* tp_call */
729 proxy_str, /* tp_str */
Georg Brandl347b3002006-03-30 11:57:00 +0000730 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000731 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000732 0, /* tp_as_buffer */
Fred Drake8844d522001-10-05 21:52:26 +0000733 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drakef16c3dc2002-08-09 18:34:16 +0000734 | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
735 0, /* tp_doc */
736 (traverseproc)gc_traverse, /* tp_traverse */
737 (inquiry)gc_clear, /* tp_clear */
738 0, /* tp_richcompare */
739 0, /* tp_weaklistoffset */
740 (getiterfunc)proxy_iter, /* tp_iter */
741 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000742};
743
744
Fred Drake8844d522001-10-05 21:52:26 +0000745
746PyObject *
747PyWeakref_NewRef(PyObject *ob, PyObject *callback)
748{
749 PyWeakReference *result = NULL;
750 PyWeakReference **list;
751 PyWeakReference *ref, *proxy;
752
Christian Heimese93237d2007-12-19 02:37:44 +0000753 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000754 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000755 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000756 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000757 return NULL;
758 }
759 list = GET_WEAKREFS_LISTPTR(ob);
760 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000761 if (callback == Py_None)
762 callback = NULL;
763 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000764 /* return existing weak reference if it exists */
765 result = ref;
766 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000767 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000768 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000769 /* Note: new_weakref() can trigger cyclic GC, so the weakref
770 list on ob can be mutated. This means that the ref and
771 proxy pointers we got back earlier may have been collected,
772 so we need to compute these values again before we use
773 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000774 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000775 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000776 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000777 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000778 if (ref == NULL)
779 insert_head(result, list);
780 else {
781 /* Someone else added a ref without a callback
782 during GC. Return that one instead of this one
783 to avoid violating the invariants of the list
784 of weakrefs for ob. */
785 Py_DECREF(result);
786 Py_INCREF(ref);
787 result = ref;
788 }
Fred Drake8844d522001-10-05 21:52:26 +0000789 }
790 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000791 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000792
Fred Drakebc875f52004-02-04 23:14:14 +0000793 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000794 if (prev == NULL)
795 insert_head(result, list);
796 else
797 insert_after(result, prev);
798 }
Fred Drake8844d522001-10-05 21:52:26 +0000799 }
800 }
801 return (PyObject *) result;
802}
803
804
805PyObject *
806PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
807{
808 PyWeakReference *result = NULL;
809 PyWeakReference **list;
810 PyWeakReference *ref, *proxy;
811
Christian Heimese93237d2007-12-19 02:37:44 +0000812 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000813 PyErr_Format(PyExc_TypeError,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000814 "cannot create weak reference to '%s' object",
Christian Heimese93237d2007-12-19 02:37:44 +0000815 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000816 return NULL;
817 }
818 list = GET_WEAKREFS_LISTPTR(ob);
819 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000820 if (callback == Py_None)
821 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000822 if (callback == NULL)
823 /* attempt to return an existing weak reference if it exists */
824 result = proxy;
825 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000826 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000827 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000828 /* Note: new_weakref() can trigger cyclic GC, so the weakref
829 list on ob can be mutated. This means that the ref and
830 proxy pointers we got back earlier may have been collected,
831 so we need to compute these values again before we use
832 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000833 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000834 if (result != NULL) {
835 PyWeakReference *prev;
836
837 if (PyCallable_Check(ob))
Christian Heimese93237d2007-12-19 02:37:44 +0000838 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000839 else
Christian Heimese93237d2007-12-19 02:37:44 +0000840 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000841 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000842 if (callback == NULL) {
843 if (proxy != NULL) {
844 /* Someone else added a proxy without a callback
845 during GC. Return that one instead of this one
846 to avoid violating the invariants of the list
847 of weakrefs for ob. */
848 Py_DECREF(result);
849 Py_INCREF(result = proxy);
850 goto skip_insert;
851 }
Fred Drake8844d522001-10-05 21:52:26 +0000852 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000853 }
Fred Drake8844d522001-10-05 21:52:26 +0000854 else
855 prev = (proxy == NULL) ? ref : proxy;
856
857 if (prev == NULL)
858 insert_head(result, list);
859 else
860 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000861 skip_insert:
862 ;
Fred Drake8844d522001-10-05 21:52:26 +0000863 }
864 }
865 return (PyObject *) result;
866}
867
868
869PyObject *
870PyWeakref_GetObject(PyObject *ref)
871{
872 if (ref == NULL || !PyWeakref_Check(ref)) {
873 PyErr_BadInternalCall();
874 return NULL;
875 }
876 return PyWeakref_GET_OBJECT(ref);
877}
878
Tim Petersead8b7a2004-10-30 23:09:22 +0000879/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
880 * handle_weakrefs().
881 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000882static void
883handle_callback(PyWeakReference *ref, PyObject *callback)
884{
Georg Brandl684fd0c2006-05-25 19:15:31 +0000885 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000886
887 if (cbresult == NULL)
888 PyErr_WriteUnraisable(callback);
889 else
890 Py_DECREF(cbresult);
891}
892
893/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000894 *
895 * This iterates through the weak references for 'object' and calls callbacks
896 * for those references which have one. It returns when all callbacks have
897 * been attempted.
898 */
899void
900PyObject_ClearWeakRefs(PyObject *object)
901{
902 PyWeakReference **list;
903
904 if (object == NULL
Christian Heimese93237d2007-12-19 02:37:44 +0000905 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000906 || object->ob_refcnt != 0) {
907 PyErr_BadInternalCall();
908 return;
909 }
910 list = GET_WEAKREFS_LISTPTR(object);
911 /* Remove the callback-less basic and proxy references */
912 if (*list != NULL && (*list)->wr_callback == NULL) {
913 clear_weakref(*list);
914 if (*list != NULL && (*list)->wr_callback == NULL)
915 clear_weakref(*list);
916 }
917 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000918 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000919 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000920 int restore_error = PyErr_Occurred() ? 1 : 0;
921 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000922
Fred Drakeef8ebd12001-12-10 23:44:54 +0000923 if (restore_error)
924 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000925 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000926 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000927
Fred Drakeef8ebd12001-12-10 23:44:54 +0000928 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000929 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000930 if (callback != NULL) {
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000931 if (current->ob_refcnt > 0)
932 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000933 Py_DECREF(callback);
934 }
Fred Drake8844d522001-10-05 21:52:26 +0000935 }
936 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000937 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000938 Py_ssize_t i = 0;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000939
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000940 tuple = PyTuple_New(count * 2);
941 if (tuple == NULL) {
942 if (restore_error)
943 PyErr_Fetch(&err_type, &err_value, &err_tb);
944 return;
945 }
Fred Drake8844d522001-10-05 21:52:26 +0000946
947 for (i = 0; i < count; ++i) {
948 PyWeakReference *next = current->wr_next;
949
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000950 if (current->ob_refcnt > 0)
951 {
952 Py_INCREF(current);
953 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
954 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
955 }
956 else {
957 Py_DECREF(current->wr_callback);
958 }
Fred Drake8844d522001-10-05 21:52:26 +0000959 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000960 clear_weakref(current);
961 current = next;
962 }
963 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000964 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000965
Amaury Forgeot d'Arca8919fe2008-06-16 19:12:42 +0000966 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000967 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000968 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
969 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000970 }
Fred Drake8844d522001-10-05 21:52:26 +0000971 }
972 Py_DECREF(tuple);
973 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000974 if (restore_error)
975 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000976 }
977}