blob: c99f6ba1b6f125330c757e2dd94276a31d5012a2 [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
Thomas Wouters0e3f5912006-08-11 14:57:12 +00009Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +000010_PyWeakref_GetWeakrefCount(PyWeakReference *head)
11{
Thomas Wouters0e3f5912006-08-11 14:57:12 +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 Pitrouf95a1b32010-05-09 15:52:27 +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 Heimes90aa7642007-12-19 02:45:37 +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 Wouters49fd7fa2006-04-21 10:40:58 +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
Benjamin Peterson8f67d082010-10-17 20:54:53 +0000142static Py_hash_t
Fred Drake8844d522001-10-05 21:52:26 +0000143weakref_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{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100159 PyObject *name, *repr;
160
161 if (PyWeakref_GET_OBJECT(self) == Py_None)
162 return PyUnicode_FromFormat("<weakref at %p; dead>", self);
163
164 name = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self), "__name__");
165 if (name == NULL || !PyUnicode_Check(name)) {
166 if (name == NULL)
167 PyErr_Clear();
168 repr = PyUnicode_FromFormat(
169 "<weakref at %p; to '%s' at %p>",
170 self,
171 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
172 PyWeakref_GET_OBJECT(self));
Fred Drake8844d522001-10-05 21:52:26 +0000173 }
174 else {
Victor Stinner499dfcf2011-03-21 13:26:24 +0100175 repr = PyUnicode_FromFormat(
176 "<weakref at %p; to '%s' at %p (%U)>",
177 self,
178 Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name,
179 PyWeakref_GET_OBJECT(self),
180 name);
Fred Drake8844d522001-10-05 21:52:26 +0000181 }
Victor Stinner499dfcf2011-03-21 13:26:24 +0100182 Py_XDECREF(name);
183 return repr;
Fred Drake8844d522001-10-05 21:52:26 +0000184}
185
186/* Weak references only support equality, not ordering. Two weak references
187 are equal if the underlying objects are equal. If the underlying object has
188 gone away, they are equal if they are identical. */
189
190static PyObject *
191weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op)
192{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000193 if ((op != Py_EQ && op != Py_NE) ||
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 !PyWeakref_Check(self) ||
195 !PyWeakref_Check(other)) {
Brian Curtindfc80e32011-08-10 20:28:54 -0500196 Py_RETURN_NOTIMPLEMENTED;
Fred Drake8844d522001-10-05 21:52:26 +0000197 }
198 if (PyWeakref_GET_OBJECT(self) == Py_None
199 || PyWeakref_GET_OBJECT(other) == Py_None) {
200 PyObject *res = self==other ? Py_True : Py_False;
201 Py_INCREF(res);
202 return res;
203 }
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 Heimes90aa7642007-12-19 02:45:37 +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 Heimes90aa7642007-12-19 02:45:37 +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 Peterson9aa42992008-09-10 21:57:34 +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öwis9f2e3462007-07-21 17:22:18 +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 Pitrouf95a1b32010-05-09 15:52:27 +0000344 0, /*tp_print*/
Fred Drake8844d522001-10-05 21:52:26 +0000345 0, /*tp_getattr*/
346 0, /*tp_setattr*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000347 0, /*tp_reserved*/
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*/
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000358 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC
Fred Drake0a4dd392004-07-02 18:57:45 +0000359 | 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 Pitrouf95a1b32010-05-09 15:52:27 +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*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +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 Peterson32019772009-11-19 03:08:32 +0000440#define WRAP_METHOD(method, special) \
441 static PyObject * \
442 method(PyObject *proxy) { \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000443 UNWRAP(proxy); \
444 return PyObject_CallMethod(proxy, special, ""); \
445 }
Benjamin Peterson32019772009-11-19 03:08:32 +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{
Victor Stinner499dfcf2011-03-21 13:26:24 +0100457 return PyUnicode_FromFormat(
458 "<weakproxy at %p to %s at %p>",
459 proxy,
460 Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name,
461 PyWeakref_GET_OBJECT(proxy));
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
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000473static PyObject *
474proxy_richcompare(PyObject *proxy, PyObject *v, int op)
Fred Drake8844d522001-10-05 21:52:26 +0000475{
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000476 UNWRAP(proxy);
477 UNWRAP(v);
478 return PyObject_RichCompare(proxy, v, op);
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)
Georg Brandlb533e262008-05-25 18:19:30 +0000485WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide)
486WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000487WRAP_BINARY(proxy_mod, PyNumber_Remainder)
488WRAP_BINARY(proxy_divmod, PyNumber_Divmod)
489WRAP_TERNARY(proxy_pow, PyNumber_Power)
490WRAP_UNARY(proxy_neg, PyNumber_Negative)
491WRAP_UNARY(proxy_pos, PyNumber_Positive)
492WRAP_UNARY(proxy_abs, PyNumber_Absolute)
493WRAP_UNARY(proxy_invert, PyNumber_Invert)
494WRAP_BINARY(proxy_lshift, PyNumber_Lshift)
495WRAP_BINARY(proxy_rshift, PyNumber_Rshift)
496WRAP_BINARY(proxy_and, PyNumber_And)
497WRAP_BINARY(proxy_xor, PyNumber_Xor)
498WRAP_BINARY(proxy_or, PyNumber_Or)
Mark Dickinson17c7cd82009-01-17 21:57:11 +0000499WRAP_UNARY(proxy_int, PyNumber_Long)
Fred Drake8844d522001-10-05 21:52:26 +0000500WRAP_UNARY(proxy_float, PyNumber_Float)
501WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd)
502WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract)
503WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply)
Georg Brandlb533e262008-05-25 18:19:30 +0000504WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide)
505WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide)
Fred Drake8844d522001-10-05 21:52:26 +0000506WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder)
507WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower)
508WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift)
509WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift)
510WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd)
511WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor)
512WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr)
Georg Brandlb533e262008-05-25 18:19:30 +0000513WRAP_UNARY(proxy_index, PyNumber_Index)
Fred Drake8844d522001-10-05 21:52:26 +0000514
Tim Peters403a2032003-11-20 21:21:46 +0000515static int
Jack Diederich4dafcc42006-11-28 19:15:13 +0000516proxy_bool(PyWeakReference *proxy)
Fred Drake8844d522001-10-05 21:52:26 +0000517{
518 PyObject *o = PyWeakref_GET_OBJECT(proxy);
519 if (!proxy_checkref(proxy))
Neal Norwitzbdcb9412004-07-08 01:22:31 +0000520 return -1;
Raymond Hettingere6c470f2005-03-27 03:04:54 +0000521 return PyObject_IsTrue(o);
Fred Drake8844d522001-10-05 21:52:26 +0000522}
523
Fred Drake0a4dd392004-07-02 18:57:45 +0000524static void
525proxy_dealloc(PyWeakReference *self)
526{
527 if (self->wr_callback != NULL)
528 PyObject_GC_UnTrack((PyObject *)self);
529 clear_weakref(self);
530 PyObject_GC_Del(self);
531}
532
Fred Drake8844d522001-10-05 21:52:26 +0000533/* sequence slots */
534
Fred Drake8844d522001-10-05 21:52:26 +0000535static int
536proxy_contains(PyWeakReference *proxy, PyObject *value)
537{
538 if (!proxy_checkref(proxy))
539 return -1;
540 return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value);
541}
542
543
544/* mapping slots */
545
Martin v. Löwis18e16552006-02-15 17:27:45 +0000546static Py_ssize_t
Fred Drake8844d522001-10-05 21:52:26 +0000547proxy_length(PyWeakReference *proxy)
548{
549 if (!proxy_checkref(proxy))
550 return -1;
551 return PyObject_Length(PyWeakref_GET_OBJECT(proxy));
552}
553
554WRAP_BINARY(proxy_getitem, PyObject_GetItem)
555
556static int
557proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value)
558{
559 if (!proxy_checkref(proxy))
560 return -1;
Raymond Hettingerd693a812003-06-30 04:18:48 +0000561
562 if (value == NULL)
563 return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key);
564 else
565 return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value);
Fred Drake8844d522001-10-05 21:52:26 +0000566}
567
Fred Drakef16c3dc2002-08-09 18:34:16 +0000568/* iterator slots */
569
570static PyObject *
571proxy_iter(PyWeakReference *proxy)
572{
573 if (!proxy_checkref(proxy))
574 return NULL;
575 return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy));
576}
577
578static PyObject *
579proxy_iternext(PyWeakReference *proxy)
580{
581 if (!proxy_checkref(proxy))
582 return NULL;
583 return PyIter_Next(PyWeakref_GET_OBJECT(proxy));
584}
585
Fred Drake8844d522001-10-05 21:52:26 +0000586
Victor Stinner3e2b7172010-11-09 09:32:19 +0000587WRAP_METHOD(proxy_bytes, "__bytes__")
Benjamin Peterson32019772009-11-19 03:08:32 +0000588
589
590static PyMethodDef proxy_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 {"__bytes__", (PyCFunction)proxy_bytes, METH_NOARGS},
592 {NULL, NULL}
Benjamin Peterson32019772009-11-19 03:08:32 +0000593};
594
595
Fred Drake8844d522001-10-05 21:52:26 +0000596static PyNumberMethods proxy_as_number = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000597 proxy_add, /*nb_add*/
598 proxy_sub, /*nb_subtract*/
599 proxy_mul, /*nb_multiply*/
600 proxy_mod, /*nb_remainder*/
601 proxy_divmod, /*nb_divmod*/
602 proxy_pow, /*nb_power*/
603 proxy_neg, /*nb_negative*/
604 proxy_pos, /*nb_positive*/
605 proxy_abs, /*nb_absolute*/
Jack Diederich4dafcc42006-11-28 19:15:13 +0000606 (inquiry)proxy_bool, /*nb_bool*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000607 proxy_invert, /*nb_invert*/
608 proxy_lshift, /*nb_lshift*/
609 proxy_rshift, /*nb_rshift*/
610 proxy_and, /*nb_and*/
611 proxy_xor, /*nb_xor*/
612 proxy_or, /*nb_or*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000613 proxy_int, /*nb_int*/
Mark Dickinson8055afd2009-01-17 10:04:45 +0000614 0, /*nb_reserved*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000615 proxy_float, /*nb_float*/
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000616 proxy_iadd, /*nb_inplace_add*/
617 proxy_isub, /*nb_inplace_subtract*/
618 proxy_imul, /*nb_inplace_multiply*/
619 proxy_imod, /*nb_inplace_remainder*/
620 proxy_ipow, /*nb_inplace_power*/
621 proxy_ilshift, /*nb_inplace_lshift*/
622 proxy_irshift, /*nb_inplace_rshift*/
623 proxy_iand, /*nb_inplace_and*/
624 proxy_ixor, /*nb_inplace_xor*/
625 proxy_ior, /*nb_inplace_or*/
Georg Brandlb533e262008-05-25 18:19:30 +0000626 proxy_floor_div, /*nb_floor_divide*/
627 proxy_true_div, /*nb_true_divide*/
628 proxy_ifloor_div, /*nb_inplace_floor_divide*/
629 proxy_itrue_div, /*nb_inplace_true_divide*/
630 proxy_index, /*nb_index*/
Fred Drake8844d522001-10-05 21:52:26 +0000631};
632
633static PySequenceMethods proxy_as_sequence = {
Martin v. Löwis18e16552006-02-15 17:27:45 +0000634 (lenfunc)proxy_length, /*sq_length*/
Fred Drake8844d522001-10-05 21:52:26 +0000635 0, /*sq_concat*/
636 0, /*sq_repeat*/
637 0, /*sq_item*/
Thomas Woutersd2cf20e2007-08-30 22:57:53 +0000638 0, /*sq_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000639 0, /*sq_ass_item*/
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000640 0, /*sq_ass_slice*/
Fred Drake8844d522001-10-05 21:52:26 +0000641 (objobjproc)proxy_contains, /* sq_contains */
642};
643
644static PyMappingMethods proxy_as_mapping = {
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000645 (lenfunc)proxy_length, /*mp_length*/
646 proxy_getitem, /*mp_subscript*/
Fred Drake8844d522001-10-05 21:52:26 +0000647 (objobjargproc)proxy_setitem, /*mp_ass_subscript*/
648};
649
650
651PyTypeObject
652_PyWeakref_ProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000653 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000654 "weakproxy",
655 sizeof(PyWeakReference),
656 0,
657 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000658 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000659 0, /* tp_print */
660 0, /* tp_getattr */
661 0, /* tp_setattr */
662 0, /* tp_reserved */
663 (reprfunc)proxy_repr, /* tp_repr */
664 &proxy_as_number, /* tp_as_number */
665 &proxy_as_sequence, /* tp_as_sequence */
666 &proxy_as_mapping, /* tp_as_mapping */
667 0, /* tp_hash */
668 0, /* tp_call */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000669 proxy_str, /* tp_str */
670 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000671 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000673 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000674 0, /* tp_doc */
675 (traverseproc)gc_traverse, /* tp_traverse */
676 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000677 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000678 0, /* tp_weaklistoffset */
679 (getiterfunc)proxy_iter, /* tp_iter */
680 (iternextfunc)proxy_iternext, /* tp_iternext */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000681 proxy_methods, /* tp_methods */
Fred Drake8844d522001-10-05 21:52:26 +0000682};
683
684
685PyTypeObject
686_PyWeakref_CallableProxyType = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000687 PyVarObject_HEAD_INIT(&PyType_Type, 0)
Fred Drake8844d522001-10-05 21:52:26 +0000688 "weakcallableproxy",
689 sizeof(PyWeakReference),
690 0,
691 /* methods */
Fred Drake0a4dd392004-07-02 18:57:45 +0000692 (destructor)proxy_dealloc, /* tp_dealloc */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000693 0, /* tp_print */
694 0, /* tp_getattr */
695 0, /* tp_setattr */
696 0, /* tp_reserved */
697 (unaryfunc)proxy_repr, /* tp_repr */
698 &proxy_as_number, /* tp_as_number */
699 &proxy_as_sequence, /* tp_as_sequence */
700 &proxy_as_mapping, /* tp_as_mapping */
701 0, /* tp_hash */
702 proxy_call, /* tp_call */
703 proxy_str, /* tp_str */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000704 proxy_getattr, /* tp_getattro */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000705 (setattrofunc)proxy_setattr, /* tp_setattro */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 0, /* tp_as_buffer */
Guido van Rossum3cf5b1e2006-07-27 21:53:35 +0000707 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000708 0, /* tp_doc */
709 (traverseproc)gc_traverse, /* tp_traverse */
710 (inquiry)gc_clear, /* tp_clear */
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000711 proxy_richcompare, /* tp_richcompare */
Fred Drakef16c3dc2002-08-09 18:34:16 +0000712 0, /* tp_weaklistoffset */
713 (getiterfunc)proxy_iter, /* tp_iter */
714 (iternextfunc)proxy_iternext, /* tp_iternext */
Fred Drake8844d522001-10-05 21:52:26 +0000715};
716
717
Fred Drake8844d522001-10-05 21:52:26 +0000718
719PyObject *
720PyWeakref_NewRef(PyObject *ob, PyObject *callback)
721{
722 PyWeakReference *result = NULL;
723 PyWeakReference **list;
724 PyWeakReference *ref, *proxy;
725
Christian Heimes90aa7642007-12-19 02:45:37 +0000726 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000727 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000728 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000729 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000730 return NULL;
731 }
732 list = GET_WEAKREFS_LISTPTR(ob);
733 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000734 if (callback == Py_None)
735 callback = NULL;
736 if (callback == NULL)
Fred Drake8844d522001-10-05 21:52:26 +0000737 /* return existing weak reference if it exists */
738 result = ref;
739 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000740 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000741 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000742 /* Note: new_weakref() can trigger cyclic GC, so the weakref
743 list on ob can be mutated. This means that the ref and
744 proxy pointers we got back earlier may have been collected,
745 so we need to compute these values again before we use
746 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000747 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000748 if (result != NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000749 get_basic_refs(*list, &ref, &proxy);
Fred Drake8844d522001-10-05 21:52:26 +0000750 if (callback == NULL) {
Fred Drake6d3265d2004-08-03 14:47:25 +0000751 if (ref == NULL)
752 insert_head(result, list);
753 else {
754 /* Someone else added a ref without a callback
755 during GC. Return that one instead of this one
756 to avoid violating the invariants of the list
757 of weakrefs for ob. */
758 Py_DECREF(result);
759 Py_INCREF(ref);
760 result = ref;
761 }
Fred Drake8844d522001-10-05 21:52:26 +0000762 }
763 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000764 PyWeakReference *prev;
Fred Drake8844d522001-10-05 21:52:26 +0000765
Fred Drakebc875f52004-02-04 23:14:14 +0000766 prev = (proxy == NULL) ? ref : proxy;
Fred Drake8844d522001-10-05 21:52:26 +0000767 if (prev == NULL)
768 insert_head(result, list);
769 else
770 insert_after(result, prev);
771 }
Fred Drake8844d522001-10-05 21:52:26 +0000772 }
773 }
774 return (PyObject *) result;
775}
776
777
778PyObject *
779PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
780{
781 PyWeakReference *result = NULL;
782 PyWeakReference **list;
783 PyWeakReference *ref, *proxy;
784
Christian Heimes90aa7642007-12-19 02:45:37 +0000785 if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) {
Fred Drake8844d522001-10-05 21:52:26 +0000786 PyErr_Format(PyExc_TypeError,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000787 "cannot create weak reference to '%s' object",
Christian Heimes90aa7642007-12-19 02:45:37 +0000788 Py_TYPE(ob)->tp_name);
Fred Drake8844d522001-10-05 21:52:26 +0000789 return NULL;
790 }
791 list = GET_WEAKREFS_LISTPTR(ob);
792 get_basic_refs(*list, &ref, &proxy);
Fred Drake6a2852c2004-02-03 19:52:56 +0000793 if (callback == Py_None)
794 callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000795 if (callback == NULL)
796 /* attempt to return an existing weak reference if it exists */
797 result = proxy;
798 if (result != NULL)
Fred Drakebc875f52004-02-04 23:14:14 +0000799 Py_INCREF(result);
Fred Drake8844d522001-10-05 21:52:26 +0000800 else {
Fred Drakebc875f52004-02-04 23:14:14 +0000801 /* Note: new_weakref() can trigger cyclic GC, so the weakref
802 list on ob can be mutated. This means that the ref and
803 proxy pointers we got back earlier may have been collected,
804 so we need to compute these values again before we use
805 them. */
Neil Schemenauer38a89162002-03-27 15:18:21 +0000806 result = new_weakref(ob, callback);
Fred Drake8844d522001-10-05 21:52:26 +0000807 if (result != NULL) {
808 PyWeakReference *prev;
809
810 if (PyCallable_Check(ob))
Christian Heimes90aa7642007-12-19 02:45:37 +0000811 Py_TYPE(result) = &_PyWeakref_CallableProxyType;
Fred Drake8844d522001-10-05 21:52:26 +0000812 else
Christian Heimes90aa7642007-12-19 02:45:37 +0000813 Py_TYPE(result) = &_PyWeakref_ProxyType;
Fred Drakebc875f52004-02-04 23:14:14 +0000814 get_basic_refs(*list, &ref, &proxy);
Fred Drake6d3265d2004-08-03 14:47:25 +0000815 if (callback == NULL) {
816 if (proxy != NULL) {
817 /* Someone else added a proxy without a callback
818 during GC. Return that one instead of this one
819 to avoid violating the invariants of the list
820 of weakrefs for ob. */
821 Py_DECREF(result);
822 Py_INCREF(result = proxy);
823 goto skip_insert;
824 }
Fred Drake8844d522001-10-05 21:52:26 +0000825 prev = ref;
Fred Drake6d3265d2004-08-03 14:47:25 +0000826 }
Fred Drake8844d522001-10-05 21:52:26 +0000827 else
828 prev = (proxy == NULL) ? ref : proxy;
829
830 if (prev == NULL)
831 insert_head(result, list);
832 else
833 insert_after(result, prev);
Fred Drake6d3265d2004-08-03 14:47:25 +0000834 skip_insert:
835 ;
Fred Drake8844d522001-10-05 21:52:26 +0000836 }
837 }
838 return (PyObject *) result;
839}
840
841
842PyObject *
843PyWeakref_GetObject(PyObject *ref)
844{
845 if (ref == NULL || !PyWeakref_Check(ref)) {
846 PyErr_BadInternalCall();
847 return NULL;
848 }
849 return PyWeakref_GET_OBJECT(ref);
850}
851
Tim Petersead8b7a2004-10-30 23:09:22 +0000852/* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
853 * handle_weakrefs().
854 */
Fred Drakeef8ebd12001-12-10 23:44:54 +0000855static void
856handle_callback(PyWeakReference *ref, PyObject *callback)
857{
Thomas Wouters477c8d52006-05-27 19:21:47 +0000858 PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000859
860 if (cbresult == NULL)
861 PyErr_WriteUnraisable(callback);
862 else
863 Py_DECREF(cbresult);
864}
865
866/* This function is called by the tp_dealloc handler to clear weak references.
Fred Drake8844d522001-10-05 21:52:26 +0000867 *
868 * This iterates through the weak references for 'object' and calls callbacks
869 * for those references which have one. It returns when all callbacks have
870 * been attempted.
871 */
872void
873PyObject_ClearWeakRefs(PyObject *object)
874{
875 PyWeakReference **list;
876
877 if (object == NULL
Christian Heimes90aa7642007-12-19 02:45:37 +0000878 || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object))
Fred Drake8844d522001-10-05 21:52:26 +0000879 || object->ob_refcnt != 0) {
880 PyErr_BadInternalCall();
881 return;
882 }
883 list = GET_WEAKREFS_LISTPTR(object);
884 /* Remove the callback-less basic and proxy references */
885 if (*list != NULL && (*list)->wr_callback == NULL) {
886 clear_weakref(*list);
887 if (*list != NULL && (*list)->wr_callback == NULL)
888 clear_weakref(*list);
889 }
890 if (*list != NULL) {
Fred Drakeef8ebd12001-12-10 23:44:54 +0000891 PyWeakReference *current = *list;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000892 Py_ssize_t count = _PyWeakref_GetWeakrefCount(current);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000893 int restore_error = PyErr_Occurred() ? 1 : 0;
894 PyObject *err_type, *err_value, *err_tb;
Fred Drake8844d522001-10-05 21:52:26 +0000895
Fred Drakeef8ebd12001-12-10 23:44:54 +0000896 if (restore_error)
897 PyErr_Fetch(&err_type, &err_value, &err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000898 if (count == 1) {
Fred Drake8844d522001-10-05 21:52:26 +0000899 PyObject *callback = current->wr_callback;
Fred Drake8844d522001-10-05 21:52:26 +0000900
Fred Drakeef8ebd12001-12-10 23:44:54 +0000901 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000902 clear_weakref(current);
Fred Drake0a4dd392004-07-02 18:57:45 +0000903 if (callback != NULL) {
Benjamin Petersona38d1562008-06-16 20:47:12 +0000904 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000905 handle_callback(current, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000906 Py_DECREF(callback);
907 }
Fred Drake8844d522001-10-05 21:52:26 +0000908 }
909 else {
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000910 PyObject *tuple;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000911 Py_ssize_t i = 0;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000912
Hye-Shik Chang4af5c8c2006-03-07 15:39:21 +0000913 tuple = PyTuple_New(count * 2);
914 if (tuple == NULL) {
915 if (restore_error)
916 PyErr_Fetch(&err_type, &err_value, &err_tb);
917 return;
918 }
Fred Drake8844d522001-10-05 21:52:26 +0000919
920 for (i = 0; i < count; ++i) {
921 PyWeakReference *next = current->wr_next;
922
Benjamin Petersona38d1562008-06-16 20:47:12 +0000923 if (((PyObject *)current)->ob_refcnt > 0)
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000924 {
925 Py_INCREF(current);
926 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current);
927 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback);
928 }
929 else {
930 Py_DECREF(current->wr_callback);
931 }
Fred Drake8844d522001-10-05 21:52:26 +0000932 current->wr_callback = NULL;
Fred Drake8844d522001-10-05 21:52:26 +0000933 clear_weakref(current);
934 current = next;
935 }
936 for (i = 0; i < count; ++i) {
Fred Drake8844d522001-10-05 21:52:26 +0000937 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1);
Fred Drakeef8ebd12001-12-10 23:44:54 +0000938
Amaury Forgeot d'Arcc856c7a2008-06-16 19:50:09 +0000939 /* The tuple may have slots left to NULL */
Fred Drake0a4dd392004-07-02 18:57:45 +0000940 if (callback != NULL) {
Neal Norwitz0c6e2f12006-01-08 06:13:44 +0000941 PyObject *item = PyTuple_GET_ITEM(tuple, i * 2);
942 handle_callback((PyWeakReference *)item, callback);
Fred Drake0a4dd392004-07-02 18:57:45 +0000943 }
Fred Drake8844d522001-10-05 21:52:26 +0000944 }
945 Py_DECREF(tuple);
946 }
Fred Drakeef8ebd12001-12-10 23:44:54 +0000947 if (restore_error)
948 PyErr_Restore(err_type, err_value, err_tb);
Fred Drake8844d522001-10-05 21:52:26 +0000949 }
950}