| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | #include "structmember.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define GET_WEAKREFS_LISTPTR(o) \
 | 
					
						
							|  |  |  |         ((PyWeakReference **) PyObject_GET_WEAKREFS_LISTPTR(o)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-08-02 06:14:22 +00:00
										 |  |  | Py_ssize_t | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | _PyWeakref_GetWeakrefCount(PyWeakReference *head) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-08-02 06:14:22 +00:00
										 |  |  |     Py_ssize_t count = 0; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     while (head != NULL) { | 
					
						
							|  |  |  |         ++count; | 
					
						
							|  |  |  |         head = head->wr_next; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return count; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     self->hash = -1; | 
					
						
							|  |  |  |     self->wr_object = ob; | 
					
						
							|  |  |  |     Py_XINCREF(callback); | 
					
						
							|  |  |  |     self->wr_callback = callback; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | static PyWeakReference * | 
					
						
							| 
									
										
										
										
											2002-03-27 15:18:21 +00:00
										 |  |  | new_weakref(PyObject *ob, PyObject *callback) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     PyWeakReference *result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-03-27 15:18:21 +00:00
										 |  |  |     result = PyObject_GC_New(PyWeakReference, &_PyWeakref_RefType); | 
					
						
							|  |  |  |     if (result) { | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |         init_weakref(result, ob, callback); | 
					
						
							| 
									
										
										
										
											2002-03-27 15:18:21 +00:00
										 |  |  |         PyObject_GC_Track(result); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This function clears the passed-in reference and removes it from the
 | 
					
						
							|  |  |  |  * list of weak references for the referent.  This is the only code that | 
					
						
							|  |  |  |  * removes an item from the doubly-linked list of weak references for an | 
					
						
							|  |  |  |  * object; it is also responsible for clearing the callback slot. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | clear_weakref(PyWeakReference *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *callback = self->wr_callback; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (PyWeakref_GET_OBJECT(self) != Py_None) { | 
					
						
							|  |  |  |         PyWeakReference **list = GET_WEAKREFS_LISTPTR( | 
					
						
							|  |  |  |             PyWeakref_GET_OBJECT(self)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (*list == self) | 
					
						
							| 
									
										
										
										
											2007-01-23 23:21:22 +00:00
										 |  |  | 	    /* If 'self' is the end of the list (and thus self->wr_next == NULL)
 | 
					
						
							|  |  |  | 	       then the weakref list itself (and thus the value of *list) will | 
					
						
							|  |  |  | 	       end up being set to NULL. */ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |             *list = self->wr_next; | 
					
						
							|  |  |  |         self->wr_object = Py_None; | 
					
						
							|  |  |  |         if (self->wr_prev != NULL) | 
					
						
							|  |  |  |             self->wr_prev->wr_next = self->wr_next; | 
					
						
							|  |  |  |         if (self->wr_next != NULL) | 
					
						
							|  |  |  |             self->wr_next->wr_prev = self->wr_prev; | 
					
						
							|  |  |  |         self->wr_prev = NULL; | 
					
						
							|  |  |  |         self->wr_next = NULL; | 
					
						
							| 
									
										
										
										
											2003-11-20 21:21:46 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (callback != NULL) { | 
					
						
							|  |  |  |         Py_DECREF(callback); | 
					
						
							|  |  |  |         self->wr_callback = NULL; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-20 21:21:46 +00:00
										 |  |  | /* Cyclic gc uses this to *just* clear the passed-in reference, leaving
 | 
					
						
							|  |  |  |  * the callback intact and uncalled.  It must be possible to call self's | 
					
						
							|  |  |  |  * tp_dealloc() after calling this, so self has to be left in a sane enough | 
					
						
							|  |  |  |  * state for that to work.  We expect tp_dealloc to decref the callback | 
					
						
							|  |  |  |  * then.  The reason for not letting clear_weakref() decref the callback | 
					
						
							|  |  |  |  * right now is that if the callback goes away, that may in turn trigger | 
					
						
							|  |  |  |  * another callback (if a weak reference to the callback exists) -- running | 
					
						
							|  |  |  |  * arbitrary Python code in the middle of gc is a disaster.  The convolution | 
					
						
							|  |  |  |  * here allows gc to delay triggering such callbacks until the world is in | 
					
						
							|  |  |  |  * a sane state again. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | _PyWeakref_ClearRef(PyWeakReference *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *callback; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     assert(self != NULL); | 
					
						
							|  |  |  |     assert(PyWeakref_Check(self)); | 
					
						
							|  |  |  |     /* Preserve and restore the callback around clear_weakref. */ | 
					
						
							|  |  |  |     callback = self->wr_callback; | 
					
						
							|  |  |  |     self->wr_callback = NULL; | 
					
						
							|  |  |  |     clear_weakref(self); | 
					
						
							|  |  |  |     self->wr_callback = callback; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static void | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  | weakref_dealloc(PyObject *self) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     PyObject_GC_UnTrack(self); | 
					
						
							|  |  |  |     clear_weakref((PyWeakReference *) self); | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |     Py_TYPE(self)->tp_free(self); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | gc_traverse(PyWeakReference *self, visitproc visit, void *arg) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-15 21:47:09 +00:00
										 |  |  |     Py_VISIT(self->wr_callback); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | gc_clear(PyWeakReference *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     clear_weakref(self); | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | weakref_call(PyWeakReference *self, PyObject *args, PyObject *kw) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-02-27 16:46:16 +00:00
										 |  |  |     static char *kwlist[] = {NULL}; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-27 16:46:16 +00:00
										 |  |  |     if (PyArg_ParseTupleAndKeywords(args, kw, ":__call__", kwlist)) { | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         PyObject *object = PyWeakref_GET_OBJECT(self); | 
					
						
							|  |  |  |         Py_INCREF(object); | 
					
						
							|  |  |  |         return (object); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static long | 
					
						
							|  |  |  | weakref_hash(PyWeakReference *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (self->hash != -1) | 
					
						
							|  |  |  |         return self->hash; | 
					
						
							|  |  |  |     if (PyWeakref_GET_OBJECT(self) == Py_None) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_TypeError, "weak object has gone away"); | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     self->hash = PyObject_Hash(PyWeakref_GET_OBJECT(self)); | 
					
						
							|  |  |  |     return self->hash; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2003-11-20 21:21:46 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | weakref_repr(PyWeakReference *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     char buffer[256]; | 
					
						
							|  |  |  |     if (PyWeakref_GET_OBJECT(self) == Py_None) { | 
					
						
							| 
									
										
										
										
											2003-04-16 21:13:23 +00:00
										 |  |  |         PyOS_snprintf(buffer, sizeof(buffer), "<weakref at %p; dead>", self); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2003-04-16 21:13:23 +00:00
										 |  |  | 	char *name = NULL; | 
					
						
							|  |  |  | 	PyObject *nameobj = PyObject_GetAttrString(PyWeakref_GET_OBJECT(self), | 
					
						
							|  |  |  | 						   "__name__"); | 
					
						
							|  |  |  | 	if (nameobj == NULL) | 
					
						
							|  |  |  | 		PyErr_Clear(); | 
					
						
							| 
									
										
										
										
											2008-05-26 12:51:38 +00:00
										 |  |  | 	else if (PyBytes_Check(nameobj)) | 
					
						
							|  |  |  | 		name = PyBytes_AS_STRING(nameobj); | 
					
						
							| 
									
										
										
										
											2001-11-28 21:01:56 +00:00
										 |  |  |         PyOS_snprintf(buffer, sizeof(buffer), | 
					
						
							| 
									
										
										
										
											2003-04-16 21:13:23 +00:00
										 |  |  | 		      name ? "<weakref at %p; to '%.50s' at %p (%s)>" | 
					
						
							|  |  |  | 		           : "<weakref at %p; to '%.50s' at %p>", | 
					
						
							|  |  |  | 		      self, | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  | 		      Py_TYPE(PyWeakref_GET_OBJECT(self))->tp_name, | 
					
						
							| 
									
										
										
										
											2003-04-16 21:13:23 +00:00
										 |  |  | 		      PyWeakref_GET_OBJECT(self), | 
					
						
							|  |  |  | 		      name); | 
					
						
							|  |  |  | 	Py_XDECREF(nameobj); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-05-26 12:51:38 +00:00
										 |  |  |     return PyBytes_FromString(buffer); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Weak references only support equality, not ordering. Two weak references
 | 
					
						
							|  |  |  |    are equal if the underlying objects are equal. If the underlying object has | 
					
						
							|  |  |  |    gone away, they are equal if they are identical. */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | weakref_richcompare(PyWeakReference* self, PyWeakReference* other, int op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (op != Py_EQ || self->ob_type != other->ob_type) { | 
					
						
							|  |  |  |         Py_INCREF(Py_NotImplemented); | 
					
						
							|  |  |  |         return Py_NotImplemented; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (PyWeakref_GET_OBJECT(self) == Py_None | 
					
						
							|  |  |  |         || PyWeakref_GET_OBJECT(other) == Py_None) { | 
					
						
							|  |  |  |         PyObject *res = self==other ? Py_True : Py_False; | 
					
						
							|  |  |  |         Py_INCREF(res); | 
					
						
							|  |  |  |         return res; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyObject_RichCompare(PyWeakref_GET_OBJECT(self), | 
					
						
							|  |  |  |                                 PyWeakref_GET_OBJECT(other), op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  | /* Given the head of an object's list of weak references, extract the
 | 
					
						
							|  |  |  |  * two callback-less refs (ref and proxy).  Used to determine if the | 
					
						
							|  |  |  |  * shared references exist and to determine the back link for newly | 
					
						
							|  |  |  |  * inserted references. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | get_basic_refs(PyWeakReference *head, | 
					
						
							|  |  |  |                PyWeakReference **refp, PyWeakReference **proxyp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     *refp = NULL; | 
					
						
							|  |  |  |     *proxyp = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (head != NULL && head->wr_callback == NULL) { | 
					
						
							|  |  |  |         /* We need to be careful that the "basic refs" aren't
 | 
					
						
							|  |  |  |            subclasses of the main types.  That complicates this a | 
					
						
							|  |  |  |            little. */ | 
					
						
							|  |  |  |         if (PyWeakref_CheckRefExact(head)) { | 
					
						
							|  |  |  |             *refp = head; | 
					
						
							|  |  |  |             head = head->wr_next; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (head != NULL | 
					
						
							|  |  |  |             && head->wr_callback == NULL | 
					
						
							|  |  |  |             && PyWeakref_CheckProxy(head)) { | 
					
						
							|  |  |  |             *proxyp = head; | 
					
						
							|  |  |  |             /* head = head->wr_next; */ | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Insert 'newref' in the list after 'prev'.  Both must be non-NULL. */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | insert_after(PyWeakReference *newref, PyWeakReference *prev) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     newref->wr_prev = prev; | 
					
						
							|  |  |  |     newref->wr_next = prev->wr_next; | 
					
						
							|  |  |  |     if (prev->wr_next != NULL) | 
					
						
							|  |  |  |         prev->wr_next->wr_prev = newref; | 
					
						
							|  |  |  |     prev->wr_next = newref; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Insert 'newref' at the head of the list; 'list' points to the variable
 | 
					
						
							|  |  |  |  * that stores the head. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void | 
					
						
							|  |  |  | insert_head(PyWeakReference *newref, PyWeakReference **list) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyWeakReference *next = *list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     newref->wr_prev = NULL; | 
					
						
							|  |  |  |     newref->wr_next = next; | 
					
						
							|  |  |  |     if (next != NULL) | 
					
						
							|  |  |  |         next->wr_prev = newref; | 
					
						
							|  |  |  |     *list = newref; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | parse_weakref_init_args(char *funcname, PyObject *args, PyObject *kwargs, | 
					
						
							|  |  |  |                         PyObject **obp, PyObject **callbackp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* XXX Should check that kwargs == NULL or is empty. */ | 
					
						
							|  |  |  |     return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyWeakReference *self = NULL; | 
					
						
							|  |  |  |     PyObject *ob, *callback = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) { | 
					
						
							|  |  |  |         PyWeakReference *ref, *proxy; | 
					
						
							|  |  |  |         PyWeakReference **list; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |         if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |             PyErr_Format(PyExc_TypeError, | 
					
						
							|  |  |  |                          "cannot create weak reference to '%s' object", | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |                          Py_TYPE(ob)->tp_name); | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |             return NULL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (callback == Py_None) | 
					
						
							|  |  |  |             callback = NULL; | 
					
						
							|  |  |  |         list = GET_WEAKREFS_LISTPTR(ob); | 
					
						
							|  |  |  |         get_basic_refs(*list, &ref, &proxy); | 
					
						
							|  |  |  |         if (callback == NULL && type == &_PyWeakref_RefType) { | 
					
						
							|  |  |  |             if (ref != NULL) { | 
					
						
							|  |  |  |                 /* We can re-use an existing reference. */ | 
					
						
							|  |  |  |                 Py_INCREF(ref); | 
					
						
							|  |  |  |                 return (PyObject *)ref; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         /* We have to create a new reference. */ | 
					
						
							|  |  |  |         /* Note: the tp_alloc() can trigger cyclic GC, so the weakref
 | 
					
						
							|  |  |  |            list on ob can be mutated.  This means that the ref and | 
					
						
							|  |  |  |            proxy pointers we got back earlier may have been collected, | 
					
						
							|  |  |  |            so we need to compute these values again before we use | 
					
						
							|  |  |  |            them. */ | 
					
						
							|  |  |  |         self = (PyWeakReference *) (type->tp_alloc(type, 0)); | 
					
						
							|  |  |  |         if (self != NULL) { | 
					
						
							|  |  |  |             init_weakref(self, ob, callback); | 
					
						
							|  |  |  |             if (callback == NULL && type == &_PyWeakref_RefType) { | 
					
						
							|  |  |  |                 insert_head(self, list); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 PyWeakReference *prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 get_basic_refs(*list, &ref, &proxy); | 
					
						
							|  |  |  |                 prev = (proxy == NULL) ? ref : proxy; | 
					
						
							|  |  |  |                 if (prev == NULL) | 
					
						
							|  |  |  |                     insert_head(self, list); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     insert_after(self, prev); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (PyObject *)self; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp)) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject | 
					
						
							|  |  |  | _PyWeakref_RefType = { | 
					
						
							| 
									
										
										
										
											2007-07-21 06:55:02 +00:00
										 |  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     "weakref", | 
					
						
							|  |  |  |     sizeof(PyWeakReference), | 
					
						
							|  |  |  |     0, | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     weakref_dealloc,            /*tp_dealloc*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     0,	                        /*tp_print*/ | 
					
						
							|  |  |  |     0,                          /*tp_getattr*/ | 
					
						
							|  |  |  |     0,                          /*tp_setattr*/ | 
					
						
							|  |  |  |     0,	                        /*tp_compare*/ | 
					
						
							|  |  |  |     (reprfunc)weakref_repr,     /*tp_repr*/ | 
					
						
							|  |  |  |     0,                          /*tp_as_number*/ | 
					
						
							|  |  |  |     0,                          /*tp_as_sequence*/ | 
					
						
							|  |  |  |     0,                          /*tp_as_mapping*/ | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     (hashfunc)weakref_hash,     /*tp_hash*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     (ternaryfunc)weakref_call,  /*tp_call*/ | 
					
						
							|  |  |  |     0,                          /*tp_str*/ | 
					
						
							|  |  |  |     0,                          /*tp_getattro*/ | 
					
						
							|  |  |  |     0,                          /*tp_setattro*/ | 
					
						
							|  |  |  |     0,                          /*tp_as_buffer*/ | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_HAVE_RICHCOMPARE | 
					
						
							|  |  |  |         | Py_TPFLAGS_BASETYPE,  /*tp_flags*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     0,                          /*tp_doc*/ | 
					
						
							|  |  |  |     (traverseproc)gc_traverse,  /*tp_traverse*/ | 
					
						
							|  |  |  |     (inquiry)gc_clear,          /*tp_clear*/ | 
					
						
							|  |  |  |     (richcmpfunc)weakref_richcompare,	/*tp_richcompare*/ | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     0,                          /*tp_weaklistoffset*/ | 
					
						
							|  |  |  |     0,                          /*tp_iter*/ | 
					
						
							|  |  |  |     0,                          /*tp_iternext*/ | 
					
						
							|  |  |  |     0,                          /*tp_methods*/ | 
					
						
							|  |  |  |     0,                          /*tp_members*/ | 
					
						
							|  |  |  |     0,                          /*tp_getset*/ | 
					
						
							|  |  |  |     0,                          /*tp_base*/ | 
					
						
							|  |  |  |     0,                          /*tp_dict*/ | 
					
						
							|  |  |  |     0,                          /*tp_descr_get*/ | 
					
						
							|  |  |  |     0,                          /*tp_descr_set*/ | 
					
						
							|  |  |  |     0,                          /*tp_dictoffset*/ | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  |     weakref___init__,           /*tp_init*/ | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     PyType_GenericAlloc,        /*tp_alloc*/ | 
					
						
							|  |  |  |     weakref___new__,            /*tp_new*/ | 
					
						
							|  |  |  |     PyObject_GC_Del,            /*tp_free*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | proxy_checkref(PyWeakReference *proxy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (PyWeakref_GET_OBJECT(proxy) == Py_None) { | 
					
						
							|  |  |  |         PyErr_SetString(PyExc_ReferenceError, | 
					
						
							|  |  |  |                         "weakly-referenced object no longer exists"); | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-18 18:04:18 +00:00
										 |  |  | /* If a parameter is a proxy, check that it is still "live" and wrap it,
 | 
					
						
							|  |  |  |  * replacing the original value with the raw object.  Raises ReferenceError | 
					
						
							|  |  |  |  * if the param is a dead proxy. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define UNWRAP(o) \
 | 
					
						
							|  |  |  |         if (PyWeakref_CheckProxy(o)) { \ | 
					
						
							|  |  |  |             if (!proxy_checkref((PyWeakReference *)o)) \ | 
					
						
							|  |  |  |                 return NULL; \ | 
					
						
							|  |  |  |             o = PyWeakref_GET_OBJECT(o); \ | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-19 16:44:30 +00:00
										 |  |  | #define UNWRAP_I(o) \
 | 
					
						
							|  |  |  |         if (PyWeakref_CheckProxy(o)) { \ | 
					
						
							|  |  |  |             if (!proxy_checkref((PyWeakReference *)o)) \ | 
					
						
							|  |  |  |                 return -1; \ | 
					
						
							|  |  |  |             o = PyWeakref_GET_OBJECT(o); \ | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | #define WRAP_UNARY(method, generic) \
 | 
					
						
							|  |  |  |     static PyObject * \ | 
					
						
							| 
									
										
										
										
											2001-10-18 18:04:18 +00:00
										 |  |  |     method(PyObject *proxy) { \ | 
					
						
							|  |  |  |         UNWRAP(proxy); \ | 
					
						
							|  |  |  |         return generic(proxy); \ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define WRAP_BINARY(method, generic) \
 | 
					
						
							|  |  |  |     static PyObject * \ | 
					
						
							| 
									
										
										
										
											2001-10-18 18:04:18 +00:00
										 |  |  |     method(PyObject *x, PyObject *y) { \ | 
					
						
							|  |  |  |         UNWRAP(x); \ | 
					
						
							|  |  |  |         UNWRAP(y); \ | 
					
						
							|  |  |  |         return generic(x, y); \ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-18 19:21:46 +00:00
										 |  |  | /* Note that the third arg needs to be checked for NULL since the tp_call
 | 
					
						
							|  |  |  |  * slot can receive NULL for this arg. | 
					
						
							| 
									
										
										
										
											2001-10-18 18:04:18 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | #define WRAP_TERNARY(method, generic) \
 | 
					
						
							|  |  |  |     static PyObject * \ | 
					
						
							| 
									
										
										
										
											2001-10-18 18:04:18 +00:00
										 |  |  |     method(PyObject *proxy, PyObject *v, PyObject *w) { \ | 
					
						
							|  |  |  |         UNWRAP(proxy); \ | 
					
						
							| 
									
										
										
										
											2001-10-18 19:21:46 +00:00
										 |  |  |         UNWRAP(v); \ | 
					
						
							| 
									
										
										
										
											2001-10-18 18:04:18 +00:00
										 |  |  |         if (w != NULL) \ | 
					
						
							|  |  |  |             UNWRAP(w); \ | 
					
						
							|  |  |  |         return generic(proxy, v, w); \ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* direct slots */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WRAP_BINARY(proxy_getattr, PyObject_GetAttr) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_str, PyObject_Str) | 
					
						
							|  |  |  | WRAP_TERNARY(proxy_call, PyEval_CallObjectWithKeywords) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | proxy_repr(PyWeakReference *proxy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     char buf[160]; | 
					
						
							| 
									
										
										
										
											2001-11-28 21:01:56 +00:00
										 |  |  |     PyOS_snprintf(buf, sizeof(buf), | 
					
						
							| 
									
										
										
										
											2003-04-16 21:13:23 +00:00
										 |  |  | 		  "<weakproxy at %p to %.100s at %p>", proxy, | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  | 		  Py_TYPE(PyWeakref_GET_OBJECT(proxy))->tp_name, | 
					
						
							| 
									
										
										
										
											2001-11-28 21:01:56 +00:00
										 |  |  | 		  PyWeakref_GET_OBJECT(proxy)); | 
					
						
							| 
									
										
										
										
											2008-05-26 12:51:38 +00:00
										 |  |  |     return PyBytes_FromString(buf); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | proxy_setattr(PyWeakReference *proxy, PyObject *name, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     return PyObject_SetAttr(PyWeakref_GET_OBJECT(proxy), name, value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2001-12-19 16:44:30 +00:00
										 |  |  | proxy_compare(PyObject *proxy, PyObject *v) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2001-12-19 16:44:30 +00:00
										 |  |  |     UNWRAP_I(proxy); | 
					
						
							|  |  |  |     UNWRAP_I(v); | 
					
						
							|  |  |  |     return PyObject_Compare(proxy, v); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* number slots */ | 
					
						
							|  |  |  | WRAP_BINARY(proxy_add, PyNumber_Add) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_sub, PyNumber_Subtract) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_mul, PyNumber_Multiply) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_div, PyNumber_Divide) | 
					
						
							| 
									
										
										
										
											2008-05-20 08:40:43 +00:00
										 |  |  | WRAP_BINARY(proxy_floor_div, PyNumber_FloorDivide) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_true_div, PyNumber_TrueDivide) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | WRAP_BINARY(proxy_mod, PyNumber_Remainder) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_divmod, PyNumber_Divmod) | 
					
						
							|  |  |  | WRAP_TERNARY(proxy_pow, PyNumber_Power) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_neg, PyNumber_Negative) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_pos, PyNumber_Positive) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_abs, PyNumber_Absolute) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_invert, PyNumber_Invert) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_lshift, PyNumber_Lshift) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_rshift, PyNumber_Rshift) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_and, PyNumber_And) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_xor, PyNumber_Xor) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_or, PyNumber_Or) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_int, PyNumber_Int) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_long, PyNumber_Long) | 
					
						
							|  |  |  | WRAP_UNARY(proxy_float, PyNumber_Float) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_iadd, PyNumber_InPlaceAdd) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_isub, PyNumber_InPlaceSubtract) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_imul, PyNumber_InPlaceMultiply) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_idiv, PyNumber_InPlaceDivide) | 
					
						
							| 
									
										
										
										
											2008-05-20 08:40:43 +00:00
										 |  |  | WRAP_BINARY(proxy_ifloor_div, PyNumber_InPlaceFloorDivide) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_itrue_div, PyNumber_InPlaceTrueDivide) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | WRAP_BINARY(proxy_imod, PyNumber_InPlaceRemainder) | 
					
						
							|  |  |  | WRAP_TERNARY(proxy_ipow, PyNumber_InPlacePower) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_ilshift, PyNumber_InPlaceLshift) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_irshift, PyNumber_InPlaceRshift) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_iand, PyNumber_InPlaceAnd) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_ixor, PyNumber_InPlaceXor) | 
					
						
							|  |  |  | WRAP_BINARY(proxy_ior, PyNumber_InPlaceOr) | 
					
						
							| 
									
										
										
										
											2008-05-20 08:40:43 +00:00
										 |  |  | WRAP_UNARY(proxy_index, PyNumber_Index) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-11-20 21:21:46 +00:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | proxy_nonzero(PyWeakReference *proxy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyObject *o = PyWeakref_GET_OBJECT(proxy); | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							| 
									
										
										
										
											2004-07-08 01:22:31 +00:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2005-03-27 03:04:54 +00:00
										 |  |  |     return PyObject_IsTrue(o); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | proxy_dealloc(PyWeakReference *self) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (self->wr_callback != NULL) | 
					
						
							|  |  |  |         PyObject_GC_UnTrack((PyObject *)self); | 
					
						
							|  |  |  |     clear_weakref(self); | 
					
						
							|  |  |  |     PyObject_GC_Del(self); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | /* sequence slots */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | proxy_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return PySequence_GetSlice(PyWeakref_GET_OBJECT(proxy), i, j); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | proxy_ass_slice(PyWeakReference *proxy, Py_ssize_t i, Py_ssize_t j, PyObject *value) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     return PySequence_SetSlice(PyWeakref_GET_OBJECT(proxy), i, j, value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | proxy_contains(PyWeakReference *proxy, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     return PySequence_Contains(PyWeakref_GET_OBJECT(proxy), value); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* mapping slots */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  | static Py_ssize_t | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | proxy_length(PyWeakReference *proxy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  |     return PyObject_Length(PyWeakref_GET_OBJECT(proxy)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | WRAP_BINARY(proxy_getitem, PyObject_GetItem) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int | 
					
						
							|  |  |  | proxy_setitem(PyWeakReference *proxy, PyObject *key, PyObject *value) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2003-06-30 04:18:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (value == NULL) | 
					
						
							|  |  |  |         return PyObject_DelItem(PyWeakref_GET_OBJECT(proxy), key); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         return PyObject_SetItem(PyWeakref_GET_OBJECT(proxy), key, value); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  | /* iterator slots */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | proxy_iter(PyWeakReference *proxy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return PyObject_GetIter(PyWeakref_GET_OBJECT(proxy)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject * | 
					
						
							|  |  |  | proxy_iternext(PyWeakReference *proxy) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!proxy_checkref(proxy)) | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     return PyIter_Next(PyWeakref_GET_OBJECT(proxy)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static PyNumberMethods proxy_as_number = { | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  |     proxy_add,              /*nb_add*/ | 
					
						
							|  |  |  |     proxy_sub,              /*nb_subtract*/ | 
					
						
							|  |  |  |     proxy_mul,              /*nb_multiply*/ | 
					
						
							|  |  |  |     proxy_div,              /*nb_divide*/ | 
					
						
							|  |  |  |     proxy_mod,              /*nb_remainder*/ | 
					
						
							|  |  |  |     proxy_divmod,           /*nb_divmod*/ | 
					
						
							|  |  |  |     proxy_pow,              /*nb_power*/ | 
					
						
							|  |  |  |     proxy_neg,              /*nb_negative*/ | 
					
						
							|  |  |  |     proxy_pos,              /*nb_positive*/ | 
					
						
							|  |  |  |     proxy_abs,              /*nb_absolute*/ | 
					
						
							|  |  |  |     (inquiry)proxy_nonzero, /*nb_nonzero*/ | 
					
						
							|  |  |  |     proxy_invert,           /*nb_invert*/ | 
					
						
							|  |  |  |     proxy_lshift,           /*nb_lshift*/ | 
					
						
							|  |  |  |     proxy_rshift,           /*nb_rshift*/ | 
					
						
							|  |  |  |     proxy_and,              /*nb_and*/ | 
					
						
							|  |  |  |     proxy_xor,              /*nb_xor*/ | 
					
						
							|  |  |  |     proxy_or,               /*nb_or*/ | 
					
						
							|  |  |  |     0,                      /*nb_coerce*/ | 
					
						
							|  |  |  |     proxy_int,              /*nb_int*/ | 
					
						
							|  |  |  |     proxy_long,             /*nb_long*/ | 
					
						
							|  |  |  |     proxy_float,            /*nb_float*/ | 
					
						
							|  |  |  |     0,                      /*nb_oct*/ | 
					
						
							|  |  |  |     0,                      /*nb_hex*/ | 
					
						
							|  |  |  |     proxy_iadd,             /*nb_inplace_add*/ | 
					
						
							|  |  |  |     proxy_isub,             /*nb_inplace_subtract*/ | 
					
						
							|  |  |  |     proxy_imul,             /*nb_inplace_multiply*/ | 
					
						
							|  |  |  |     proxy_idiv,             /*nb_inplace_divide*/ | 
					
						
							|  |  |  |     proxy_imod,             /*nb_inplace_remainder*/ | 
					
						
							|  |  |  |     proxy_ipow,             /*nb_inplace_power*/ | 
					
						
							|  |  |  |     proxy_ilshift,          /*nb_inplace_lshift*/ | 
					
						
							|  |  |  |     proxy_irshift,          /*nb_inplace_rshift*/ | 
					
						
							|  |  |  |     proxy_iand,             /*nb_inplace_and*/ | 
					
						
							|  |  |  |     proxy_ixor,             /*nb_inplace_xor*/ | 
					
						
							|  |  |  |     proxy_ior,              /*nb_inplace_or*/ | 
					
						
							| 
									
										
										
										
											2008-05-20 08:40:43 +00:00
										 |  |  |     proxy_floor_div,        /*nb_floor_divide*/ | 
					
						
							|  |  |  |     proxy_true_div,         /*nb_true_divide*/ | 
					
						
							|  |  |  |     proxy_ifloor_div,       /*nb_inplace_floor_divide*/ | 
					
						
							|  |  |  |     proxy_itrue_div,        /*nb_inplace_true_divide*/ | 
					
						
							|  |  |  |     proxy_index,            /*nb_index*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PySequenceMethods proxy_as_sequence = { | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  |     (lenfunc)proxy_length,      /*sq_length*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     0,                          /*sq_concat*/ | 
					
						
							|  |  |  |     0,                          /*sq_repeat*/ | 
					
						
							|  |  |  |     0,                          /*sq_item*/ | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  |     (ssizessizeargfunc)proxy_slice, /*sq_slice*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     0,                          /*sq_ass_item*/ | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  |     (ssizessizeobjargproc)proxy_ass_slice, /*sq_ass_slice*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     (objobjproc)proxy_contains, /* sq_contains */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyMappingMethods proxy_as_mapping = { | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  |     (lenfunc)proxy_length,        /*mp_length*/ | 
					
						
							|  |  |  |     proxy_getitem,                /*mp_subscript*/ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     (objobjargproc)proxy_setitem, /*mp_ass_subscript*/ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject | 
					
						
							|  |  |  | _PyWeakref_ProxyType = { | 
					
						
							| 
									
										
										
										
											2007-07-21 06:55:02 +00:00
										 |  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     "weakproxy", | 
					
						
							|  |  |  |     sizeof(PyWeakReference), | 
					
						
							|  |  |  |     0, | 
					
						
							|  |  |  |     /* methods */ | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     (destructor)proxy_dealloc,          /* tp_dealloc */ | 
					
						
							| 
									
										
										
										
											2003-07-14 21:46:23 +00:00
										 |  |  |     0,				        /* tp_print */ | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  |     0,				        /* tp_getattr */ | 
					
						
							|  |  |  |     0, 				        /* tp_setattr */ | 
					
						
							|  |  |  |     proxy_compare,		        /* tp_compare */ | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  |     (reprfunc)proxy_repr,	        /* tp_repr */ | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  |     &proxy_as_number,		        /* tp_as_number */ | 
					
						
							|  |  |  |     &proxy_as_sequence,		        /* tp_as_sequence */ | 
					
						
							|  |  |  |     &proxy_as_mapping,		        /* tp_as_mapping */ | 
					
						
							|  |  |  |     0,	                                /* tp_hash */ | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  |     0,	                                /* tp_call */ | 
					
						
							|  |  |  |     proxy_str,                          /* tp_str */ | 
					
						
							|  |  |  |     proxy_getattr,                      /* tp_getattro */ | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  |     (setattrofunc)proxy_setattr,        /* tp_setattro */ | 
					
						
							|  |  |  |     0,				        /* tp_as_buffer */ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  |     | Py_TPFLAGS_CHECKTYPES,            /* tp_flags */ | 
					
						
							|  |  |  |     0,                                  /* tp_doc */ | 
					
						
							|  |  |  |     (traverseproc)gc_traverse,          /* tp_traverse */ | 
					
						
							|  |  |  |     (inquiry)gc_clear,                  /* tp_clear */ | 
					
						
							|  |  |  |     0,                                  /* tp_richcompare */ | 
					
						
							|  |  |  |     0,                                  /* tp_weaklistoffset */ | 
					
						
							|  |  |  |     (getiterfunc)proxy_iter,            /* tp_iter */ | 
					
						
							|  |  |  |     (iternextfunc)proxy_iternext,       /* tp_iternext */ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyTypeObject | 
					
						
							|  |  |  | _PyWeakref_CallableProxyType = { | 
					
						
							| 
									
										
										
										
											2007-07-21 06:55:02 +00:00
										 |  |  |     PyVarObject_HEAD_INIT(&PyType_Type, 0) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     "weakcallableproxy", | 
					
						
							|  |  |  |     sizeof(PyWeakReference), | 
					
						
							|  |  |  |     0, | 
					
						
							|  |  |  |     /* methods */ | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |     (destructor)proxy_dealloc,          /* tp_dealloc */ | 
					
						
							| 
									
										
										
										
											2003-07-14 21:46:23 +00:00
										 |  |  |     0,				        /* tp_print */ | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  |     0,				        /* tp_getattr */ | 
					
						
							|  |  |  |     0, 				        /* tp_setattr */ | 
					
						
							|  |  |  |     proxy_compare,		        /* tp_compare */ | 
					
						
							|  |  |  |     (unaryfunc)proxy_repr,	        /* tp_repr */ | 
					
						
							|  |  |  |     &proxy_as_number,		        /* tp_as_number */ | 
					
						
							|  |  |  |     &proxy_as_sequence,		        /* tp_as_sequence */ | 
					
						
							|  |  |  |     &proxy_as_mapping,		        /* tp_as_mapping */ | 
					
						
							|  |  |  |     0,	                                /* tp_hash */ | 
					
						
							| 
									
										
										
										
											2006-03-30 11:57:00 +00:00
										 |  |  |     proxy_call,	                        /* tp_call */ | 
					
						
							|  |  |  |     proxy_str,	                        /* tp_str */ | 
					
						
							|  |  |  |     proxy_getattr,                      /* tp_getattro */ | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  |     (setattrofunc)proxy_setattr,        /* tp_setattro */ | 
					
						
							|  |  |  |     0,				        /* tp_as_buffer */ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | 
					
						
							| 
									
										
										
										
											2002-08-09 18:34:16 +00:00
										 |  |  |     | Py_TPFLAGS_CHECKTYPES,            /* tp_flags */ | 
					
						
							|  |  |  |     0,                                  /* tp_doc */ | 
					
						
							|  |  |  |     (traverseproc)gc_traverse,          /* tp_traverse */ | 
					
						
							|  |  |  |     (inquiry)gc_clear,                  /* tp_clear */ | 
					
						
							|  |  |  |     0,                                  /* tp_richcompare */ | 
					
						
							|  |  |  |     0,                                  /* tp_weaklistoffset */ | 
					
						
							|  |  |  |     (getiterfunc)proxy_iter,            /* tp_iter */ | 
					
						
							|  |  |  |     (iternextfunc)proxy_iternext,       /* tp_iternext */ | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyWeakref_NewRef(PyObject *ob, PyObject *callback) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyWeakReference *result = NULL; | 
					
						
							|  |  |  |     PyWeakReference **list; | 
					
						
							|  |  |  |     PyWeakReference *ref, *proxy; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |     if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2001-10-22 16:31:40 +00:00
										 |  |  | 		     "cannot create weak reference to '%s' object", | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |                      Py_TYPE(ob)->tp_name); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     list = GET_WEAKREFS_LISTPTR(ob); | 
					
						
							|  |  |  |     get_basic_refs(*list, &ref, &proxy); | 
					
						
							| 
									
										
										
										
											2004-02-03 19:52:56 +00:00
										 |  |  |     if (callback == Py_None) | 
					
						
							|  |  |  |         callback = NULL; | 
					
						
							|  |  |  |     if (callback == NULL) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         /* return existing weak reference if it exists */ | 
					
						
							|  |  |  |         result = ref; | 
					
						
							|  |  |  |     if (result != NULL) | 
					
						
							| 
									
										
										
										
											2004-02-04 23:14:14 +00:00
										 |  |  |         Py_INCREF(result); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2004-02-04 23:14:14 +00:00
										 |  |  |         /* Note: new_weakref() can trigger cyclic GC, so the weakref
 | 
					
						
							|  |  |  |            list on ob can be mutated.  This means that the ref and | 
					
						
							|  |  |  |            proxy pointers we got back earlier may have been collected, | 
					
						
							|  |  |  |            so we need to compute these values again before we use | 
					
						
							|  |  |  |            them. */ | 
					
						
							| 
									
										
										
										
											2002-03-27 15:18:21 +00:00
										 |  |  |         result = new_weakref(ob, callback); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         if (result != NULL) { | 
					
						
							| 
									
										
										
										
											2004-08-03 14:47:25 +00:00
										 |  |  |             get_basic_refs(*list, &ref, &proxy); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |             if (callback == NULL) { | 
					
						
							| 
									
										
										
										
											2004-08-03 14:47:25 +00:00
										 |  |  |                 if (ref == NULL) | 
					
						
							|  |  |  |                     insert_head(result, list); | 
					
						
							|  |  |  |                 else { | 
					
						
							|  |  |  |                     /* Someone else added a ref without a callback
 | 
					
						
							|  |  |  |                        during GC.  Return that one instead of this one | 
					
						
							|  |  |  |                        to avoid violating the invariants of the list | 
					
						
							|  |  |  |                        of weakrefs for ob. */ | 
					
						
							|  |  |  |                     Py_DECREF(result); | 
					
						
							|  |  |  |                     Py_INCREF(ref); | 
					
						
							|  |  |  |                     result = ref; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |             else { | 
					
						
							| 
									
										
										
										
											2004-02-04 23:14:14 +00:00
										 |  |  |                 PyWeakReference *prev; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-02-04 23:14:14 +00:00
										 |  |  |                 prev = (proxy == NULL) ? ref : proxy; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |                 if (prev == NULL) | 
					
						
							|  |  |  |                     insert_head(result, list); | 
					
						
							|  |  |  |                 else | 
					
						
							|  |  |  |                     insert_after(result, prev); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (PyObject *) result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyWeakref_NewProxy(PyObject *ob, PyObject *callback) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyWeakReference *result = NULL; | 
					
						
							|  |  |  |     PyWeakReference **list; | 
					
						
							|  |  |  |     PyWeakReference *ref, *proxy; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |     if (!PyType_SUPPORTS_WEAKREFS(Py_TYPE(ob))) { | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         PyErr_Format(PyExc_TypeError, | 
					
						
							| 
									
										
										
										
											2001-10-22 16:31:40 +00:00
										 |  |  | 		     "cannot create weak reference to '%s' object", | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |                      Py_TYPE(ob)->tp_name); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     list = GET_WEAKREFS_LISTPTR(ob); | 
					
						
							|  |  |  |     get_basic_refs(*list, &ref, &proxy); | 
					
						
							| 
									
										
										
										
											2004-02-03 19:52:56 +00:00
										 |  |  |     if (callback == Py_None) | 
					
						
							|  |  |  |         callback = NULL; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     if (callback == NULL) | 
					
						
							|  |  |  |         /* attempt to return an existing weak reference if it exists */ | 
					
						
							|  |  |  |         result = proxy; | 
					
						
							|  |  |  |     if (result != NULL) | 
					
						
							| 
									
										
										
										
											2004-02-04 23:14:14 +00:00
										 |  |  |         Py_INCREF(result); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     else { | 
					
						
							| 
									
										
										
										
											2004-02-04 23:14:14 +00:00
										 |  |  |         /* Note: new_weakref() can trigger cyclic GC, so the weakref
 | 
					
						
							|  |  |  |            list on ob can be mutated.  This means that the ref and | 
					
						
							|  |  |  |            proxy pointers we got back earlier may have been collected, | 
					
						
							|  |  |  |            so we need to compute these values again before we use | 
					
						
							|  |  |  |            them. */ | 
					
						
							| 
									
										
										
										
											2002-03-27 15:18:21 +00:00
										 |  |  |         result = new_weakref(ob, callback); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         if (result != NULL) { | 
					
						
							|  |  |  |             PyWeakReference *prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (PyCallable_Check(ob)) | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |                 Py_TYPE(result) = &_PyWeakref_CallableProxyType; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |             else | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |                 Py_TYPE(result) = &_PyWeakref_ProxyType; | 
					
						
							| 
									
										
										
										
											2004-02-04 23:14:14 +00:00
										 |  |  |             get_basic_refs(*list, &ref, &proxy); | 
					
						
							| 
									
										
										
										
											2004-08-03 14:47:25 +00:00
										 |  |  |             if (callback == NULL) { | 
					
						
							|  |  |  |                 if (proxy != NULL) { | 
					
						
							|  |  |  |                     /* Someone else added a proxy without a callback
 | 
					
						
							|  |  |  |                        during GC.  Return that one instead of this one | 
					
						
							|  |  |  |                        to avoid violating the invariants of the list | 
					
						
							|  |  |  |                        of weakrefs for ob. */ | 
					
						
							|  |  |  |                     Py_DECREF(result); | 
					
						
							|  |  |  |                     Py_INCREF(result = proxy); | 
					
						
							|  |  |  |                     goto skip_insert; | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |                 prev = ref; | 
					
						
							| 
									
										
										
										
											2004-08-03 14:47:25 +00:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |             else | 
					
						
							|  |  |  |                 prev = (proxy == NULL) ? ref : proxy; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (prev == NULL) | 
					
						
							|  |  |  |                 insert_head(result, list); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 insert_after(result, prev); | 
					
						
							| 
									
										
										
										
											2004-08-03 14:47:25 +00:00
										 |  |  |         skip_insert: | 
					
						
							|  |  |  |             ; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return (PyObject *) result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | PyObject * | 
					
						
							|  |  |  | PyWeakref_GetObject(PyObject *ref) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (ref == NULL || !PyWeakref_Check(ref)) { | 
					
						
							|  |  |  |         PyErr_BadInternalCall(); | 
					
						
							|  |  |  |         return NULL; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return PyWeakref_GET_OBJECT(ref); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-10-30 23:09:22 +00:00
										 |  |  | /* Note that there's an inlined copy-paste of handle_callback() in gcmodule.c's
 | 
					
						
							|  |  |  |  * handle_weakrefs(). | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  | static void | 
					
						
							|  |  |  | handle_callback(PyWeakReference *ref, PyObject *callback) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-05-25 19:15:31 +00:00
										 |  |  |     PyObject *cbresult = PyObject_CallFunctionObjArgs(callback, ref, NULL); | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (cbresult == NULL) | 
					
						
							|  |  |  |         PyErr_WriteUnraisable(callback); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         Py_DECREF(cbresult); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* This function is called by the tp_dealloc handler to clear weak references.
 | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This iterates through the weak references for 'object' and calls callbacks | 
					
						
							|  |  |  |  * for those references which have one.  It returns when all callbacks have | 
					
						
							|  |  |  |  * been attempted. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | void | 
					
						
							|  |  |  | PyObject_ClearWeakRefs(PyObject *object) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     PyWeakReference **list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (object == NULL | 
					
						
							| 
									
										
										
										
											2007-12-19 02:37:44 +00:00
										 |  |  |         || !PyType_SUPPORTS_WEAKREFS(Py_TYPE(object)) | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         || object->ob_refcnt != 0) { | 
					
						
							|  |  |  |         PyErr_BadInternalCall(); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     list = GET_WEAKREFS_LISTPTR(object); | 
					
						
							|  |  |  |     /* Remove the callback-less basic and proxy references */ | 
					
						
							|  |  |  |     if (*list != NULL && (*list)->wr_callback == NULL) { | 
					
						
							|  |  |  |         clear_weakref(*list); | 
					
						
							|  |  |  |         if (*list != NULL && (*list)->wr_callback == NULL) | 
					
						
							|  |  |  |             clear_weakref(*list); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (*list != NULL) { | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  |         PyWeakReference *current = *list; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  |         Py_ssize_t count = _PyWeakref_GetWeakrefCount(current); | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  |         int restore_error = PyErr_Occurred() ? 1 : 0; | 
					
						
							|  |  |  |         PyObject *err_type, *err_value, *err_tb; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  |         if (restore_error) | 
					
						
							|  |  |  |             PyErr_Fetch(&err_type, &err_value, &err_tb); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         if (count == 1) { | 
					
						
							|  |  |  |             PyObject *callback = current->wr_callback; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  |             current->wr_callback = NULL; | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |             clear_weakref(current); | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |             if (callback != NULL) { | 
					
						
							|  |  |  |                 handle_callback(current, callback); | 
					
						
							|  |  |  |                 Py_DECREF(callback); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							| 
									
										
										
										
											2006-03-07 15:39:21 +00:00
										 |  |  |             PyObject *tuple; | 
					
						
							| 
									
										
										
										
											2006-02-15 17:27:45 +00:00
										 |  |  |             Py_ssize_t i = 0; | 
					
						
							| 
									
										
										
										
											2006-03-07 15:39:21 +00:00
										 |  |  |      | 
					
						
							|  |  |  |             tuple = PyTuple_New(count * 2); | 
					
						
							|  |  |  |             if (tuple == NULL) { | 
					
						
							|  |  |  |                 if (restore_error) | 
					
						
							|  |  |  |                     PyErr_Fetch(&err_type, &err_value, &err_tb); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |             for (i = 0; i < count; ++i) { | 
					
						
							|  |  |  |                 PyWeakReference *next = current->wr_next; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 Py_INCREF(current); | 
					
						
							|  |  |  |                 PyTuple_SET_ITEM(tuple, i * 2, (PyObject *) current); | 
					
						
							|  |  |  |                 PyTuple_SET_ITEM(tuple, i * 2 + 1, current->wr_callback); | 
					
						
							|  |  |  |                 current->wr_callback = NULL; | 
					
						
							|  |  |  |                 clear_weakref(current); | 
					
						
							|  |  |  |                 current = next; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             for (i = 0; i < count; ++i) { | 
					
						
							|  |  |  |                 PyObject *callback = PyTuple_GET_ITEM(tuple, i * 2 + 1); | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |                 if (callback != NULL) { | 
					
						
							| 
									
										
										
										
											2006-01-08 06:13:44 +00:00
										 |  |  |                     PyObject *item = PyTuple_GET_ITEM(tuple, i * 2); | 
					
						
							|  |  |  |                     handle_callback((PyWeakReference *)item, callback); | 
					
						
							| 
									
										
										
										
											2004-07-02 18:57:45 +00:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |             } | 
					
						
							|  |  |  |             Py_DECREF(tuple); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2001-12-10 23:44:54 +00:00
										 |  |  |         if (restore_error) | 
					
						
							|  |  |  |             PyErr_Restore(err_type, err_value, err_tb); | 
					
						
							| 
									
										
										
										
											2001-10-05 21:52:26 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } |