875da178587c866c202d311a5c6b21ac1f7c0ec3
[platform/upstream/pygobject2.git] / gi / _gobject / pygobject.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * pygtk- Python bindings for the GTK toolkit.
3  * Copyright (C) 1998-2003  James Henstridge
4  *
5  *   pygobject.c: wrapper for the GObject type.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
20  * USA
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <pyglib.h>
28 #include "pygobject-private.h"
29 #include "pyginterface.h"
30 #include "pygparamspec.h"
31
32 #include "pygi.h"
33
34
35 static void pygobject_dealloc(PyGObject *self);
36 static int  pygobject_traverse(PyGObject *self, visitproc visit, void *arg);
37 static int  pygobject_clear(PyGObject *self);
38 static PyObject * pyg_type_get_bases(GType gtype);
39 static inline int pygobject_clear(PyGObject *self);
40 static PyObject * pygobject_weak_ref_new(GObject *obj, PyObject *callback, PyObject *user_data);
41 static PyObject * pygbinding_weak_ref_new(GObject *obj);
42 static inline PyGObjectData * pyg_object_peek_inst_data(GObject *obj);
43 static void pygobject_inherit_slots(PyTypeObject *type, PyObject *bases,
44                                     gboolean check_for_present);
45 static void pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset,
46                                     gboolean check_for_present);
47 GType PY_TYPE_OBJECT = 0;
48 GQuark pygobject_custom_key;
49 GQuark pygobject_class_key;
50 GQuark pygobject_class_init_key;
51 GQuark pygobject_wrapper_key;
52 GQuark pygobject_has_updated_constructor_key;
53 GQuark pygobject_instance_data_key;
54
55 /* Copied from glib. gobject uses hyphens in property names, but in Python
56  * we can only represent hyphens as underscores. Convert underscores to
57  * hyphens for glib compatibility. */
58 static void
59 canonicalize_key (gchar *key)
60 {
61     gchar *p;
62
63     for (p = key; *p != 0; p++)
64     {
65         gchar c = *p;
66
67         if (c != '-' &&
68             (c < '0' || c > '9') &&
69             (c < 'A' || c > 'Z') &&
70             (c < 'a' || c > 'z'))
71                 *p = '-';
72     }
73 }
74
75 /* -------------- class <-> wrapper manipulation --------------- */
76
77 void
78 pygobject_data_free(PyGObjectData *data)
79 {
80     /* This function may be called after the python interpreter has already
81      * been shut down. If this happens, we cannot do any python calls, so just
82      * free the memory. */
83     PyGILState_STATE state;
84     PyThreadState *_save = NULL;
85
86     GSList *closures, *tmp;
87
88     if (Py_IsInitialized()) {
89         state = pyglib_gil_state_ensure();
90         Py_DECREF(data->type);
91         /* We cannot use Py_BEGIN_ALLOW_THREADS here because this is inside
92          * a branch. */
93         Py_UNBLOCK_THREADS; /* Modifies _save */
94     }
95
96     tmp = closures = data->closures;
97 #ifndef NDEBUG
98     data->closures = NULL;
99     data->type = NULL;
100 #endif
101     while (tmp) {
102         GClosure *closure = tmp->data;
103  
104           /* we get next item first, because the current link gets
105            * invalidated by pygobject_unwatch_closure */
106         tmp = tmp->next;
107         g_closure_invalidate(closure);
108     }
109  
110     if (data->closures != NULL)
111         g_warning("invalidated all closures, but data->closures != NULL !");
112
113     g_free(data);
114
115     if (Py_IsInitialized()) {
116         Py_BLOCK_THREADS; /* Restores _save */
117         pyglib_gil_state_release(state);
118     }
119 }
120
121 static inline PyGObjectData *
122 pygobject_data_new(void)
123 {
124     PyGObjectData *data;
125     data = g_new0(PyGObjectData, 1);
126     return data;
127 }
128
129 static inline PyGObjectData *
130 pygobject_get_inst_data(PyGObject *self)
131 {
132     PyGObjectData *inst_data;
133
134     if (G_UNLIKELY(!self->obj))
135         return NULL;
136     inst_data = g_object_get_qdata(self->obj, pygobject_instance_data_key);
137     if (inst_data == NULL)
138     {
139         inst_data = pygobject_data_new();
140
141         inst_data->type = Py_TYPE(self);
142         Py_INCREF((PyObject *) inst_data->type);
143
144         g_object_set_qdata_full(self->obj, pygobject_instance_data_key,
145                                 inst_data, (GDestroyNotify) pygobject_data_free);
146     }
147     return inst_data;
148 }
149
150
151 PyTypeObject *PyGObject_MetaType = NULL;
152
153 /**
154  * pygobject_sink:
155  * @obj: a GObject
156  * 
157  * As Python handles reference counting for us, the "floating
158  * reference" code in GTK is not all that useful.  In fact, it can
159  * cause leaks.  This function should be called to remove the floating
160  * references on objects on construction.
161  **/
162 void
163 pygobject_sink(GObject *obj)
164 {
165     /* The default behaviour for GInitiallyUnowned subclasses is to call ref_sink().
166      * - if the object is new and owned by someone else, its ref has been sunk and
167      *   we need to keep the one from that someone and add our own "fresh ref"
168      * - if the object is not and owned by nobody, its ref is floating and we need
169      *   to transform it into a regular ref.
170      */
171     if (G_IS_INITIALLY_UNOWNED(obj)) {
172         g_object_ref_sink(obj);
173     }
174 }
175
176 typedef struct {
177     PyObject_HEAD
178     GParamSpec **props;
179     guint n_props;
180     guint index;
181 } PyGPropsIter;
182
183 PYGLIB_DEFINE_TYPE("gi._gobject.GPropsIter", PyGPropsIter_Type, PyGPropsIter);
184
185 static void
186 pyg_props_iter_dealloc(PyGPropsIter *self)
187 {
188     g_free(self->props);
189     PyObject_Del((PyObject*) self);
190 }
191
192 static PyObject*
193 pygobject_props_iter_next(PyGPropsIter *iter)
194 {
195     if (iter->index < iter->n_props)
196         return pyg_param_spec_new(iter->props[iter->index++]);
197     else {
198         PyErr_SetNone(PyExc_StopIteration);
199         return NULL;
200     }
201 }
202
203 typedef struct {
204     PyObject_HEAD
205     /* a reference to the object containing the properties */
206     PyGObject *pygobject;
207     GType      gtype;
208 } PyGProps;
209
210 static void
211 PyGProps_dealloc(PyGProps* self)
212 {
213     PyGObject *tmp;
214
215     PyObject_GC_UnTrack((PyObject*)self);
216
217     tmp = self->pygobject;
218     self->pygobject = NULL;
219     Py_XDECREF(tmp);
220
221     PyObject_GC_Del((PyObject*)self);
222 }
223
224 static PyObject*
225 build_parameter_list(GObjectClass *class)
226 {
227     GParamSpec **props;
228     guint n_props = 0, i;
229     PyObject *prop_str;
230     PyObject *props_list;
231
232     props = g_object_class_list_properties(class, &n_props);
233     props_list = PyList_New(n_props);
234     for (i = 0; i < n_props; i++) {
235         char *name;
236         name = g_strdup(g_param_spec_get_name(props[i]));
237         /* hyphens cannot belong in identifiers */
238         g_strdelimit(name, "-", '_');
239         prop_str = PYGLIB_PyUnicode_FromString(name);
240         
241         PyList_SetItem(props_list, i, prop_str);
242         g_free(name);
243     }
244
245     g_type_class_unref(class);
246
247     if (props)
248         g_free(props);
249     
250     return props_list;
251 }
252
253 static PyObject*
254 PyGProps_getattro(PyGProps *self, PyObject *attr)
255 {
256     char *attr_name, *property_name;
257     GObjectClass *class;
258     GParamSpec *pspec;
259     GValue value = { 0, };
260     PyObject *ret;
261
262     attr_name = PYGLIB_PyUnicode_AsString(attr);
263     if (!attr_name) {
264         PyErr_Clear();
265         return PyObject_GenericGetAttr((PyObject *)self, attr);
266     }
267
268     class = g_type_class_ref(self->gtype);
269     
270     if (!strcmp(attr_name, "__members__")) {
271         ret = build_parameter_list(class);
272         g_type_class_unref(class);
273         return ret;
274     }
275
276     /* g_object_class_find_property recurses through the class hierarchy,
277      * so the resulting pspec tells us the owner_type that owns the property
278      * we're dealing with. */
279     property_name = g_strdup(attr_name);
280     canonicalize_key(property_name);
281     pspec = g_object_class_find_property(class, property_name);
282     g_free(property_name);
283     g_type_class_unref(class);
284
285     if (!pspec) {
286         return PyObject_GenericGetAttr((PyObject *)self, attr);
287     }
288
289     if (!(pspec->flags & G_PARAM_READABLE)) {
290         PyErr_Format(PyExc_TypeError,
291                      "property '%s' is not readable", attr_name);
292         return NULL;
293     }
294
295     if (!self->pygobject) {
296         /* If we're doing it without an instance, return a GParamSpec */
297         return pyg_param_spec_new(pspec);
298     }
299
300     if (!pyg_gtype_is_custom (pspec->owner_type)) {
301         /* The GType is not implemented at the Python level: see if we can
302          * read the property value via gi. */
303         ret = pygi_get_property_value (self->pygobject, pspec);
304         if (ret)
305             return ret;
306     }
307
308     /* The GType is implemented in Python, or we failed to read it via gi:
309      * do a straightforward read. */
310     Py_BEGIN_ALLOW_THREADS;
311     g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
312     g_object_get_property(self->pygobject->obj, pspec->name, &value);
313     Py_END_ALLOW_THREADS;
314
315     ret = pyg_param_gvalue_as_pyobject(&value, TRUE, pspec);
316     g_value_unset(&value);
317     
318     return ret;
319 }
320
321 static gboolean
322 set_property_from_pspec(GObject *obj,
323                         GParamSpec *pspec,
324                         PyObject *pvalue)
325 {
326     GValue value = { 0, };
327
328     if (pspec->flags & G_PARAM_CONSTRUCT_ONLY) {
329         PyErr_Format(PyExc_TypeError,
330                      "property '%s' can only be set in constructor",
331                      pspec->name);
332         return FALSE;
333     }   
334
335     if (!(pspec->flags & G_PARAM_WRITABLE)) {
336         PyErr_Format(PyExc_TypeError,
337                      "property '%s' is not writable", pspec->name);
338         return FALSE;
339     }   
340
341     g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
342     if (pyg_param_gvalue_from_pyobject(&value, pvalue, pspec) < 0) {
343         PyObject *pvalue_str = PyObject_Str(pvalue);
344         PyErr_Format(PyExc_TypeError,
345                      "could not convert '%s' to type '%s' when setting property '%s.%s'",
346                      PYGLIB_PyUnicode_AsString(pvalue_str),
347                      g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)),
348                      G_OBJECT_TYPE_NAME(obj),
349                      pspec->name);
350         Py_DECREF(pvalue_str);
351         return FALSE;
352     }
353
354     Py_BEGIN_ALLOW_THREADS;
355     g_object_set_property(obj, pspec->name, &value);
356     g_value_unset(&value);
357     Py_END_ALLOW_THREADS;
358
359     return TRUE;
360 }
361
362 PYGLIB_DEFINE_TYPE("gi._gobject.GProps", PyGProps_Type, PyGProps);
363
364 static int
365 PyGProps_setattro(PyGProps *self, PyObject *attr, PyObject *pvalue)
366 {
367     GParamSpec *pspec;
368     char *attr_name, *property_name;
369     GObject *obj;
370     int ret = -1;
371     
372     if (pvalue == NULL) {
373         PyErr_SetString(PyExc_TypeError, "properties cannot be "
374                         "deleted");
375         return -1;
376     }
377
378     attr_name = PYGLIB_PyUnicode_AsString(attr);
379     if (!attr_name) {
380         PyErr_Clear();
381         return PyObject_GenericSetAttr((PyObject *)self, attr, pvalue);
382     }
383
384     if (!self->pygobject) {
385         PyErr_SetString(PyExc_TypeError,
386                         "cannot set GOject properties without an instance");
387         return -1;
388     }
389
390     obj = self->pygobject->obj;
391
392     property_name = g_strdup(attr_name);
393     canonicalize_key(property_name);
394
395     /* g_object_class_find_property recurses through the class hierarchy,
396      * so the resulting pspec tells us the owner_type that owns the property
397      * we're dealing with. */
398     pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(obj),
399                                          property_name);
400     g_free(property_name);
401     if (!pspec) {
402         return PyObject_GenericSetAttr((PyObject *)self, attr, pvalue);
403     }
404     if (!pyg_gtype_is_custom (pspec->owner_type)) {
405         /* This GType is not implemented in Python: see if we can set the
406          * property via gi. */
407         ret = pygi_set_property_value (self->pygobject, pspec, pvalue);
408         if (ret == 0)
409             return 0;
410         else if (ret == -1 && PyErr_Occurred())
411             return -1;
412     }
413
414     /* This GType is implemented in Python, or we failed to set it via gi:
415      * do a straightforward set. */
416     if (!set_property_from_pspec(obj, pspec, pvalue))
417         return -1;
418                                   
419     return 0;
420 }
421
422 static int
423 pygobject_props_traverse(PyGProps *self, visitproc visit, void *arg)
424 {
425     if (self->pygobject && visit((PyObject *) self->pygobject, arg) < 0)
426         return -1;
427     return 0;
428 }
429
430 static PyObject*
431 pygobject_props_get_iter(PyGProps *self)
432 {
433     PyGPropsIter *iter;
434     GObjectClass *class;
435
436     iter = PyObject_NEW(PyGPropsIter, &PyGPropsIter_Type);
437     class = g_type_class_ref(self->gtype);
438     iter->props = g_object_class_list_properties(class, &iter->n_props);
439     iter->index = 0;
440     g_type_class_unref(class);
441     return (PyObject *) iter;
442 }
443
444 static Py_ssize_t
445 PyGProps_length(PyGProps *self)
446 {
447     GObjectClass *class;
448     GParamSpec **props;
449     guint n_props;
450     
451     class = g_type_class_ref(self->gtype);
452     props = g_object_class_list_properties(class, &n_props);
453     g_type_class_unref(class);
454     g_free(props);
455
456     return (Py_ssize_t)n_props;
457 }
458
459 static PySequenceMethods _PyGProps_as_sequence = {
460     (lenfunc) PyGProps_length,
461     0,
462     0,
463     0,
464     0,
465     0,
466     0
467 };
468
469 PYGLIB_DEFINE_TYPE("gi._gobject.GPropsDescr", PyGPropsDescr_Type, PyObject);
470
471 static PyObject *
472 pyg_props_descr_descr_get(PyObject *self, PyObject *obj, PyObject *type)
473 {
474     PyGProps *gprops;
475
476     gprops = PyObject_GC_New(PyGProps, &PyGProps_Type);
477     if (obj == NULL || obj == Py_None) {
478         gprops->pygobject = NULL;
479         gprops->gtype = pyg_type_from_object(type);
480     } else {
481         if (!PyObject_IsInstance(obj, (PyObject *) &PyGObject_Type)) {
482             PyErr_SetString(PyExc_TypeError, "cannot use GObject property"
483                             " descriptor on non-GObject instances");
484             return NULL;
485         }
486         Py_INCREF(obj);
487         gprops->pygobject = (PyGObject *) obj;
488         gprops->gtype = pyg_type_from_object(obj);
489     }
490     return (PyObject *) gprops;
491 }
492
493 /**
494  * pygobject_register_class:
495  * @dict: the module dictionary.  A reference to the type will be stored here.
496  * @type_name: not used ?
497  * @gtype: the GType of the GObject subclass.
498  * @type: the Python type object for this wrapper.
499  * @static_bases: a tuple of Python type objects that are the bases of
500  * this type
501  *
502  * This function is used to register a Python type as the wrapper for
503  * a particular GObject subclass.  It will also insert a reference to
504  * the wrapper class into the module dictionary passed as a reference,
505  * which simplifies initialisation.
506  */
507 void
508 pygobject_register_class(PyObject *dict, const gchar *type_name,
509                          GType gtype, PyTypeObject *type,
510                          PyObject *static_bases)
511 {
512     PyObject *o;
513     const char *class_name, *s;
514     PyObject *runtime_bases;
515     PyObject *bases_list, *bases, *mod_name;
516     int i;
517     
518     class_name = type->tp_name;
519     s = strrchr(class_name, '.');
520     if (s != NULL)
521         class_name = s + 1;
522
523     runtime_bases = pyg_type_get_bases(gtype);
524     if (static_bases) {
525         PyTypeObject *py_parent_type = (PyTypeObject *) PyTuple_GET_ITEM(static_bases, 0);
526         bases_list = PySequence_List(static_bases);
527           /* we start at index 1 because we want to skip the primary
528            * base, otherwise we might get MRO conflict */
529         for (i = 1; i < PyTuple_GET_SIZE(runtime_bases); ++i)
530         {
531             PyObject *base = PyTuple_GET_ITEM(runtime_bases, i);
532             int contains = PySequence_Contains(bases_list, base);
533             if (contains < 0)
534                 PyErr_Print();
535             else if (!contains) {
536                 if (!PySequence_Contains(py_parent_type->tp_mro, base)) {
537 #if 0
538                     g_message("Adding missing base %s to type %s",
539                               ((PyTypeObject *)base)->tp_name, type->tp_name);
540 #endif
541                     PyList_Append(bases_list, base);
542                 }
543             }
544         }
545         bases = PySequence_Tuple(bases_list);
546         Py_DECREF(bases_list);
547         Py_DECREF(runtime_bases);
548     } else
549         bases = runtime_bases;
550
551     Py_TYPE(type) = PyGObject_MetaType;
552     type->tp_bases = bases;
553     if (G_LIKELY(bases)) {
554         type->tp_base = (PyTypeObject *)PyTuple_GetItem(bases, 0);
555         Py_INCREF(type->tp_base);
556     }
557
558     pygobject_inherit_slots(type, bases, TRUE);
559
560     if (PyType_Ready(type) < 0) {
561         g_warning ("couldn't make the type `%s' ready", type->tp_name);
562         return;
563     }
564
565     /* Set type.__module__ to the name of the module,
566      * otherwise it'll default to 'gobject', see #376099
567      */
568     s = strrchr(type->tp_name, '.');
569     if (s != NULL) {
570         mod_name = PYGLIB_PyUnicode_FromStringAndSize(type->tp_name, (int)(s - type->tp_name));
571         PyDict_SetItemString(type->tp_dict, "__module__", mod_name);
572         Py_DECREF(mod_name);
573     }
574     
575     if (gtype) {
576         o = pyg_type_wrapper_new(gtype);
577         PyDict_SetItemString(type->tp_dict, "__gtype__", o);
578         Py_DECREF(o);
579
580         /* stash a pointer to the python class with the GType */
581         Py_INCREF(type);
582         g_type_set_qdata(gtype, pygobject_class_key, type);
583     }
584
585     /* set up __doc__ descriptor on type */
586     PyDict_SetItemString(type->tp_dict, "__doc__",
587                          pyg_object_descr_doc_get());
588
589     PyDict_SetItemString(dict, (char *)class_name, (PyObject *)type);
590 }
591
592 static void
593 pyg_toggle_notify (gpointer data, GObject *object, gboolean is_last_ref)
594 {
595     PyGObject *self = (PyGObject*) data;
596     PyGILState_STATE state;
597
598     state = pyglib_gil_state_ensure();
599
600     if (is_last_ref)
601         Py_DECREF(self);
602     else
603         Py_INCREF(self);
604
605     pyglib_gil_state_release(state);
606 }
607
608   /* Called when the inst_dict is first created; switches the 
609      reference counting strategy to start using toggle ref to keep the
610      wrapper alive while the GObject lives.  In contrast, while
611      inst_dict was NULL the python wrapper is allowed to die at
612      will and is recreated on demand. */
613 static inline void
614 pygobject_switch_to_toggle_ref(PyGObject *self)
615 {
616     g_assert(self->obj->ref_count >= 1);
617
618     if (self->private_flags.flags & PYGOBJECT_USING_TOGGLE_REF)
619         return; /* already using toggle ref */
620     self->private_flags.flags |= PYGOBJECT_USING_TOGGLE_REF;
621       /* Note that add_toggle_ref will never immediately call back into 
622          pyg_toggle_notify */
623     Py_INCREF((PyObject *) self);
624     g_object_add_toggle_ref(self->obj, pyg_toggle_notify, self);
625     g_object_unref(self->obj);
626 }
627
628 /* Called when an custom gobject is initalized via g_object_new instead of
629    its constructor.  The next time the wrapper is access via 
630    pygobject_new_full it will sink the floating reference instead of
631    adding a new reference and causing a leak */
632  
633 void
634 pygobject_ref_float(PyGObject *self)
635 {
636     /* should only be floated once */
637     g_assert(!(self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF));
638     
639     self->private_flags.flags |= PYGOBJECT_IS_FLOATING_REF;
640 }
641
642 /* Called by gobject_new_full, if the floating flag is set remove it, otherwise
643    ref the pyobject */
644 void
645 pygobject_ref_sink(PyGObject *self)
646 {
647     if (self->private_flags.flags & PYGOBJECT_IS_FLOATING_REF)
648         self->private_flags.flags &= ~PYGOBJECT_IS_FLOATING_REF;
649     else
650         Py_INCREF ( (PyObject *) self);
651 }
652
653 /**
654  * pygobject_register_wrapper:
655  * @self: the wrapper instance
656  *
657  * In the constructor of PyGTK wrappers, this function should be
658  * called after setting the obj member.  It will tie the wrapper
659  * instance to the GObject so that the same wrapper instance will
660  * always be used for this GObject instance.
661  */
662 void
663 pygobject_register_wrapper(PyObject *self)
664 {
665     PyGObject *gself;
666
667     g_return_if_fail(self != NULL);
668     g_return_if_fail(PyObject_TypeCheck(self, &PyGObject_Type));
669
670     gself = (PyGObject *)self;
671
672     g_assert(gself->obj->ref_count >= 1);
673       /* save wrapper pointer so we can access it later */
674     g_object_set_qdata_full(gself->obj, pygobject_wrapper_key, gself, NULL);
675     if (gself->inst_dict)
676         pygobject_switch_to_toggle_ref(gself);
677 }
678
679 static PyObject *
680 pyg_type_get_bases(GType gtype)
681 {
682     GType *interfaces, parent_type, interface_type;
683     guint n_interfaces;
684     PyTypeObject *py_parent_type, *py_interface_type;
685     PyObject *bases;
686     int i;
687     
688     if (G_UNLIKELY(gtype == G_TYPE_OBJECT))
689         return NULL;
690
691     /* Lookup the parent type */
692     parent_type = g_type_parent(gtype);
693     py_parent_type = pygobject_lookup_class(parent_type);
694     interfaces = g_type_interfaces(gtype, &n_interfaces);
695     bases = PyTuple_New(n_interfaces + 1);
696     /* We will always put the parent at the first position in bases */
697     Py_INCREF(py_parent_type); /* PyTuple_SetItem steals a reference */
698     PyTuple_SetItem(bases, 0, (PyObject *) py_parent_type);
699
700     /* And traverse interfaces */
701     if (n_interfaces) {
702         for (i = 0; i < n_interfaces; i++) {
703             interface_type = interfaces[i];
704             py_interface_type = pygobject_lookup_class(interface_type);
705             Py_INCREF(py_interface_type); /* PyTuple_SetItem steals a reference */
706             PyTuple_SetItem(bases, i + 1, (PyObject *) py_interface_type);
707         }
708     }
709     g_free(interfaces);
710     return bases;
711 }
712
713 /**
714  * pygobject_new_with_interfaces
715  * @gtype: the GType of the GObject subclass.
716  *
717  * Creates a new PyTypeObject from the given GType with interfaces attached in
718  * bases.
719  *
720  * Returns: a PyTypeObject for the new type or NULL if it couldn't be created
721  */
722 static PyTypeObject *
723 pygobject_new_with_interfaces(GType gtype)
724 {
725     PyGILState_STATE state;
726     PyObject *o;
727     PyTypeObject *type;
728     PyObject *dict;
729     PyTypeObject *py_parent_type;
730     PyObject *bases;
731     PyObject *modules, *module;
732     gchar *type_name, *mod_name, *gtype_name;
733
734     state = pyglib_gil_state_ensure();
735
736     bases = pyg_type_get_bases(gtype);
737     py_parent_type = (PyTypeObject *) PyTuple_GetItem(bases, 0);
738
739     dict = PyDict_New();
740     
741     o = pyg_type_wrapper_new(gtype);
742     PyDict_SetItemString(dict, "__gtype__", o);
743     Py_DECREF(o);
744
745     /* set up __doc__ descriptor on type */
746     PyDict_SetItemString(dict, "__doc__", pyg_object_descr_doc_get());
747
748     /* generate the pygtk module name and extract the base type name */
749     gtype_name = (gchar*)g_type_name(gtype);
750     if (g_str_has_prefix(gtype_name, "Gtk")) {
751         mod_name = "gtk";
752         gtype_name += 3;
753         type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
754     } else if (g_str_has_prefix(gtype_name, "Gdk")) {
755         mod_name = "gtk.gdk";
756         gtype_name += 3;
757         type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
758     } else if (g_str_has_prefix(gtype_name, "Atk")) {
759         mod_name = "atk";
760         gtype_name += 3;
761         type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
762     } else if (g_str_has_prefix(gtype_name, "Pango")) {
763         mod_name = "pango";
764         gtype_name += 5;
765         type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
766     } else {
767         mod_name = "__main__";
768         type_name = g_strconcat(mod_name, ".", gtype_name, NULL);
769     }
770
771     type = (PyTypeObject*)PyObject_CallFunction((PyObject *) Py_TYPE(py_parent_type),
772                                                 "sNN", type_name, bases, dict);
773     g_free(type_name);
774
775     if (type == NULL) {
776         PyErr_Print();
777         pyglib_gil_state_release(state);
778         return NULL;
779     }
780
781       /* Workaround python tp_(get|set)attr slot inheritance bug.
782        * Fixes bug #144135. */
783     if (!type->tp_getattr && py_parent_type->tp_getattr) {
784         type->tp_getattro = NULL;
785         type->tp_getattr = py_parent_type->tp_getattr;
786     }
787     if (!type->tp_setattr && py_parent_type->tp_setattr) {
788         type->tp_setattro = NULL;
789         type->tp_setattr = py_parent_type->tp_setattr;
790     }
791       /* override more python stupid hacks behind our back */
792     type->tp_dealloc = py_parent_type->tp_dealloc;
793     type->tp_alloc = py_parent_type->tp_alloc;
794     type->tp_free = py_parent_type->tp_free;
795     type->tp_traverse = py_parent_type->tp_traverse;
796     type->tp_clear = py_parent_type->tp_clear;
797
798     pygobject_inherit_slots(type, bases, FALSE);
799
800     if (PyType_Ready(type) < 0) {
801         g_warning ("couldn't make the type `%s' ready", type->tp_name);
802         pyglib_gil_state_release(state);
803         return NULL;
804     }
805     /* insert type name in module dict */
806     modules = PyImport_GetModuleDict();
807     if ((module = PyDict_GetItemString(modules, mod_name)) != NULL) {
808         if (PyObject_SetAttrString(module, gtype_name, (PyObject *)type) < 0)
809             PyErr_Clear();
810     }
811
812     /* stash a pointer to the python class with the GType */
813     Py_INCREF(type);
814     g_type_set_qdata(gtype, pygobject_class_key, type);
815
816     pyglib_gil_state_release(state);
817
818     return type;
819 }
820
821 /* Pick appropriate value for given slot (at slot_offset inside
822  * PyTypeObject structure).  It must be a pointer, e.g. a pointer to a
823  * function.  We use the following heuristic:
824  *
825  * - Scan all types listed as bases of the type.
826  * - If for exactly one base type slot value is non-NULL and
827  *   different from that of 'object' and 'GObject', set current type
828  *   slot into that value.
829  * - Otherwise (if there is more than one such base type or none at
830  *   all) don't touch it and live with Python default.
831  *
832  * The intention here is to propagate slot from custom wrappers to
833  * wrappers created at runtime when appropriate.  We prefer to be on
834  * the safe side, so if there is potential collision (more than one
835  * custom slot value), we discard custom overrides altogether.
836  *
837  * When registering type with pygobject_register_class(), i.e. a type
838  * that has been manually created (likely with Codegen help),
839  * `check_for_present' should be set to TRUE.  In this case, the
840  * function will never overwrite any non-NULL slots already present in
841  * the type.  If `check_for_present' is FALSE, such non-NULL slots are
842  * though to be set by Python interpreter and so will be overwritten
843  * if heuristic above says so.
844  */
845 static void
846 pygobject_inherit_slots(PyTypeObject *type, PyObject *bases, gboolean check_for_present)
847 {
848     static int slot_offsets[] = { offsetof(PyTypeObject, tp_richcompare),
849 #if PY_VERSION_HEX < 0x03000000
850                                   offsetof(PyTypeObject, tp_compare),
851 #endif
852                                   offsetof(PyTypeObject, tp_richcompare),
853                                   offsetof(PyTypeObject, tp_hash),
854                                   offsetof(PyTypeObject, tp_iter),
855                                   offsetof(PyTypeObject, tp_repr),
856                                   offsetof(PyTypeObject, tp_str),
857                                   offsetof(PyTypeObject, tp_print) };
858     int i;
859
860     /* Happens when registering gobject.GObject itself, at least. */
861     if (!bases)
862         return;
863
864     for (i = 0; i < G_N_ELEMENTS(slot_offsets); ++i)
865         pygobject_find_slot_for(type, bases, slot_offsets[i], check_for_present);
866 }
867
868 static void
869 pygobject_find_slot_for(PyTypeObject *type, PyObject *bases, int slot_offset,
870                         gboolean check_for_present)
871 {
872 #define TYPE_SLOT(type)  (* (void **) (((char *) (type)) + slot_offset))
873
874     void *found_slot = NULL;
875     int num_bases = PyTuple_Size(bases);
876     int i;
877
878     if (check_for_present && TYPE_SLOT(type) != NULL) {
879         /* We are requested to check if there is any custom slot value
880          * in this type already and there actually is.  Don't
881          * overwrite it.
882          */
883         return;
884     }
885
886     for (i = 0; i < num_bases; ++i) {
887         PyTypeObject *base_type = (PyTypeObject *) PyTuple_GetItem(bases, i);
888         void *slot = TYPE_SLOT(base_type);
889
890         if (slot == NULL)
891             continue;
892         if (slot == TYPE_SLOT(&PyGObject_Type) ||
893             slot == TYPE_SLOT(&PyBaseObject_Type))
894             continue;
895
896         if (found_slot != NULL && found_slot != slot) {
897             /* We have a conflict: more than one base use different
898              * custom slots.  To be on the safe side, we bail out.
899              */
900             return;
901         }
902
903         found_slot = slot;
904     }
905
906     /* Only perform the final assignment if at least one base has a
907      * custom value.  Otherwise just leave this type's slot untouched.
908      */
909     if (found_slot != NULL)
910         TYPE_SLOT(type) = found_slot;
911
912 #undef TYPE_SLOT
913 }
914
915 /**
916  * pygobject_lookup_class:
917  * @gtype: the GType of the GObject subclass.
918  *
919  * This function looks up the wrapper class used to represent
920  * instances of a GObject represented by @gtype.  If no wrapper class
921  * or interface has been registered for the given GType, then a new
922  * type will be created.
923  *
924  * Returns: The wrapper class for the GObject or NULL if the
925  *          GType has no registered type and a new type couldn't be created
926  */
927 PyTypeObject *
928 pygobject_lookup_class(GType gtype)
929 {
930     PyTypeObject *py_type;
931
932     if (gtype == G_TYPE_INTERFACE)
933         return &PyGInterface_Type;
934     
935     py_type = g_type_get_qdata(gtype, pygobject_class_key);
936     if (py_type == NULL) {
937         py_type = g_type_get_qdata(gtype, pyginterface_type_key);
938
939     if (py_type == NULL)
940         py_type = (PyTypeObject *)pygi_type_import_by_g_type(gtype);
941
942         if (py_type == NULL) {
943             py_type = pygobject_new_with_interfaces(gtype);
944             g_type_set_qdata(gtype, pyginterface_type_key, py_type);
945         }
946     }
947     
948     return py_type;
949 }
950
951 /**
952  * pygobject_new_full:
953  * @obj: a GObject instance.
954  * @steal: whether to steal a ref from the GObject or add (sink) a new one.
955  * @g_class: the GObjectClass
956  *
957  * This function gets a reference to a wrapper for the given GObject
958  * instance.  If a wrapper has already been created, a new reference
959  * to that wrapper will be returned.  Otherwise, a wrapper instance
960  * will be created.
961  *
962  * Returns: a reference to the wrapper for the GObject.
963  */
964 PyObject *
965 pygobject_new_full(GObject *obj, gboolean steal, gpointer g_class)
966 {
967     PyGObject *self;
968
969     if (obj == NULL) {
970         Py_RETURN_NONE;
971     }
972
973     /* If the GObject already has a PyObject wrapper stashed in its qdata, re-use it.
974      */
975     self = (PyGObject *)g_object_get_qdata(obj, pygobject_wrapper_key);
976     if (self != NULL) {
977         /* Note the use of "pygobject_ref_sink" here only deals with PyObject
978          * wrapper ref counts and has nothing to do with GObject.
979          */
980         pygobject_ref_sink(self);
981
982         /* If steal is true, we also want to decref the incoming GObjects which
983          * already have a Python wrapper because the wrapper is already holding a
984          * strong reference.
985          */
986         if (steal)
987             g_object_unref (obj);
988
989     } else {
990         /* create wrapper */
991         PyGObjectData *inst_data = pyg_object_peek_inst_data(obj);
992         PyTypeObject *tp;
993         if (inst_data)
994             tp = inst_data->type;
995         else {
996             if (g_class)
997                 tp = pygobject_lookup_class(G_OBJECT_CLASS_TYPE(g_class));
998             else
999                 tp = pygobject_lookup_class(G_OBJECT_TYPE(obj));
1000         }
1001         g_assert(tp != NULL);
1002         
1003         /* need to bump type refcount if created with
1004            pygobject_new_with_interfaces(). fixes bug #141042 */
1005         if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE)
1006             Py_INCREF(tp);
1007         self = PyObject_GC_New(PyGObject, tp);
1008         if (self == NULL)
1009             return NULL;
1010         self->inst_dict = NULL;
1011         self->weakreflist = NULL;
1012         self->private_flags.flags = 0;
1013         self->obj = obj;
1014
1015         /* If we are not stealing a ref or the object is floating,
1016          * add a regular ref or sink the object. */
1017         if (g_object_is_floating (obj))
1018             self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
1019         if (!steal || self->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING)
1020             g_object_ref_sink (obj);
1021
1022         pygobject_register_wrapper((PyObject *)self);
1023         PyObject_GC_Track((PyObject *)self);
1024     }
1025
1026     return (PyObject *)self;
1027 }
1028
1029
1030 PyObject *
1031 pygobject_new(GObject *obj)
1032 {
1033     return pygobject_new_full(obj,
1034                               /*steal=*/FALSE,
1035                               NULL);
1036 }
1037
1038 static void
1039 pygobject_unwatch_closure(gpointer data, GClosure *closure)
1040 {
1041     PyGObjectData *inst_data = data;
1042
1043     inst_data->closures = g_slist_remove (inst_data->closures, closure);
1044 }
1045
1046 /**
1047  * pygobject_watch_closure:
1048  * @self: a GObject wrapper instance
1049  * @closure: a GClosure to watch
1050  *
1051  * Adds a closure to the list of watched closures for the wrapper.
1052  * The closure must be one returned by pyg_closure_new().  When the
1053  * cycle GC traverses the wrapper instance, it will enumerate the
1054  * references to Python objects stored in watched closures.  If the
1055  * cycle GC tells the wrapper to clear itself, the watched closures
1056  * will be invalidated.
1057  */
1058 void
1059 pygobject_watch_closure(PyObject *self, GClosure *closure)
1060 {
1061     PyGObject *gself;
1062     PyGObjectData *data;
1063
1064     g_return_if_fail(self != NULL);
1065     g_return_if_fail(PyObject_TypeCheck(self, &PyGObject_Type));
1066     g_return_if_fail(closure != NULL);
1067
1068     gself = (PyGObject *)self;
1069     data = pygobject_get_inst_data(gself);
1070     g_return_if_fail(g_slist_find(data->closures, closure) == NULL);
1071     data->closures = g_slist_prepend(data->closures, closure);
1072     g_closure_add_invalidate_notifier(closure, data, pygobject_unwatch_closure);
1073 }
1074
1075
1076 /* -------------- PyGObject behaviour ----------------- */
1077
1078 PYGLIB_DEFINE_TYPE("gi._gobject.GObject", PyGObject_Type, PyGObject);
1079
1080 static void
1081 pygobject_dealloc(PyGObject *self)
1082 {
1083     /* Untrack must be done first. This is because followup calls such as
1084      * ClearWeakRefs could call into Python and cause new allocations to
1085      * happen, which could in turn could trigger the garbage collector,
1086      * which would then get confused as it is tracking this half-deallocated
1087      * object. */
1088     PyObject_GC_UnTrack((PyObject *)self);
1089
1090     PyObject_ClearWeakRefs((PyObject *)self);
1091       /* this forces inst_data->type to be updated, which could prove
1092        * important if a new wrapper has to be created and it is of a
1093        * unregistered type */
1094     pygobject_get_inst_data(self);
1095     pygobject_clear(self);
1096     /* the following causes problems with subclassed types */
1097     /* Py_TYPE(self)->tp_free((PyObject *)self); */
1098     PyObject_GC_Del(self);
1099 }
1100
1101 static PyObject*
1102 pygobject_richcompare(PyObject *self, PyObject *other, int op)
1103 {
1104     int isinst;
1105
1106     isinst = PyObject_IsInstance(self, (PyObject*)&PyGObject_Type);
1107     if (isinst == -1)
1108         return NULL;
1109     if (!isinst) {
1110         Py_INCREF(Py_NotImplemented);
1111         return Py_NotImplemented;
1112     }
1113     isinst = PyObject_IsInstance(other, (PyObject*)&PyGObject_Type);
1114     if (isinst == -1)
1115         return NULL;
1116     if (!isinst) {
1117         Py_INCREF(Py_NotImplemented);
1118         return Py_NotImplemented;
1119     }
1120
1121     return _pyglib_generic_ptr_richcompare(((PyGObject*)self)->obj,
1122                                            ((PyGObject*)other)->obj,
1123                                            op);
1124 }
1125
1126 static long
1127 pygobject_hash(PyGObject *self)
1128 {
1129     return (long)self->obj;
1130 }
1131
1132 static PyObject *
1133 pygobject_repr(PyGObject *self)
1134 {
1135     gchar buf[256];
1136
1137     g_snprintf(buf, sizeof(buf),
1138                "<%s object at 0x%lx (%s at 0x%lx)>",
1139                Py_TYPE(self)->tp_name,
1140                (long)self,
1141                self->obj ? G_OBJECT_TYPE_NAME(self->obj) : "uninitialized",
1142                (long)self->obj);
1143     return PYGLIB_PyUnicode_FromString(buf);
1144 }
1145
1146
1147 static int
1148 pygobject_traverse(PyGObject *self, visitproc visit, void *arg)
1149 {
1150     int ret = 0;
1151     GSList *tmp;
1152     PyGObjectData *data = pygobject_get_inst_data(self);
1153
1154     if (self->inst_dict) ret = visit(self->inst_dict, arg);
1155     if (ret != 0) return ret;
1156
1157     if (data) {
1158
1159         for (tmp = data->closures; tmp != NULL; tmp = tmp->next) {
1160             PyGClosure *closure = tmp->data;
1161
1162             if (closure->callback) ret = visit(closure->callback, arg);
1163             if (ret != 0) return ret;
1164
1165             if (closure->extra_args) ret = visit(closure->extra_args, arg);
1166             if (ret != 0) return ret;
1167
1168             if (closure->swap_data) ret = visit(closure->swap_data, arg);
1169             if (ret != 0) return ret;
1170         }
1171     }
1172     return ret;
1173 }
1174
1175 static inline int
1176 pygobject_clear(PyGObject *self)
1177 {
1178     if (self->obj) {
1179         g_object_set_qdata_full(self->obj, pygobject_wrapper_key, NULL, NULL);
1180         if (self->inst_dict) {
1181             g_object_remove_toggle_ref(self->obj, pyg_toggle_notify, self);
1182             self->private_flags.flags &= ~PYGOBJECT_USING_TOGGLE_REF;
1183         } else {
1184             Py_BEGIN_ALLOW_THREADS;
1185             g_object_unref(self->obj);
1186             Py_END_ALLOW_THREADS;
1187         }
1188         self->obj = NULL;
1189     }
1190     Py_CLEAR(self->inst_dict);
1191     return 0;
1192 }
1193
1194 static void
1195 pygobject_free(PyObject *op)
1196 {
1197     PyObject_GC_Del(op);
1198 }
1199
1200 gboolean
1201 pygobject_prepare_construct_properties(GObjectClass *class, PyObject *kwargs,
1202                                        guint *n_params, GParameter **params)
1203 {
1204     *n_params = 0;
1205     *params = NULL;
1206
1207     if (kwargs) {
1208         Py_ssize_t pos = 0;
1209         PyObject *key;
1210         PyObject *value;
1211
1212         *params = g_new0(GParameter, PyDict_Size(kwargs));
1213         while (PyDict_Next(kwargs, &pos, &key, &value)) {
1214             GParamSpec *pspec;
1215             GParameter *param = &(*params)[*n_params];
1216             const gchar *key_str = PYGLIB_PyUnicode_AsString(key);
1217
1218             pspec = g_object_class_find_property(class, key_str);
1219             if (!pspec) {
1220                 PyErr_Format(PyExc_TypeError,
1221                              "gobject `%s' doesn't support property `%s'",
1222                              G_OBJECT_CLASS_NAME(class), key_str);
1223                 return FALSE;
1224             }
1225             g_value_init(&param->value, G_PARAM_SPEC_VALUE_TYPE(pspec));
1226             if (pyg_param_gvalue_from_pyobject(&param->value, value, pspec) < 0) {
1227                 PyErr_Format(PyExc_TypeError,
1228                              "could not convert value for property `%s' from %s to %s",
1229                              key_str, Py_TYPE(value)->tp_name,
1230                              g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)));
1231                 return FALSE;
1232             }
1233             param->name = g_strdup(key_str);
1234             ++(*n_params);
1235         }
1236     }
1237     return TRUE;
1238 }
1239
1240 /* ---------------- PyGObject methods ----------------- */
1241
1242 static int
1243 pygobject_init(PyGObject *self, PyObject *args, PyObject *kwargs)
1244 {
1245     GType object_type;
1246     guint n_params = 0, i;
1247     GParameter *params = NULL;
1248     GObjectClass *class;
1249
1250     if (!PyArg_ParseTuple(args, ":GObject.__init__", &object_type))
1251         return -1;
1252
1253     object_type = pyg_type_from_object((PyObject *)self);
1254     if (!object_type)
1255         return -1;
1256
1257     if (G_TYPE_IS_ABSTRACT(object_type)) {
1258         PyErr_Format(PyExc_TypeError, "cannot create instance of abstract "
1259                      "(non-instantiable) type `%s'", g_type_name(object_type));
1260         return -1;
1261     }
1262
1263     if ((class = g_type_class_ref (object_type)) == NULL) {
1264         PyErr_SetString(PyExc_TypeError,
1265                         "could not get a reference to type class");
1266         return -1;
1267     }
1268
1269     if (!pygobject_prepare_construct_properties (class, kwargs, &n_params, &params))
1270         goto cleanup;
1271
1272     if (pygobject_constructv(self, n_params, params))
1273         PyErr_SetString(PyExc_RuntimeError, "could not create object");
1274            
1275  cleanup:
1276     for (i = 0; i < n_params; i++) {
1277         g_free((gchar *) params[i].name);
1278         g_value_unset(&params[i].value);
1279     }
1280     g_free(params);
1281     g_type_class_unref(class);
1282     
1283     return (self->obj) ? 0 : -1;
1284 }
1285
1286 #define CHECK_GOBJECT(self) \
1287     if (!G_IS_OBJECT(self->obj)) {                                           \
1288         PyErr_Format(PyExc_TypeError,                                        \
1289                      "object at %p of type %s is not initialized",           \
1290                      self, Py_TYPE(self)->tp_name);                          \
1291         return NULL;                                                         \
1292     }
1293
1294 static PyObject *
1295 pygobject_get_property(PyGObject *self, PyObject *args)
1296 {
1297     gchar *param_name;
1298     GParamSpec *pspec;
1299     GValue value = { 0, };
1300     PyObject *ret;
1301
1302     if (!PyArg_ParseTuple(args, "s:GObject.get_property", &param_name))
1303         return NULL;
1304
1305     CHECK_GOBJECT(self);
1306     
1307     pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
1308                                          param_name);
1309     if (!pspec) {
1310         PyErr_Format(PyExc_TypeError,
1311                      "object of type `%s' does not have property `%s'",
1312                      g_type_name(G_OBJECT_TYPE(self->obj)), param_name);
1313         return NULL;
1314     }
1315     if (!(pspec->flags & G_PARAM_READABLE)) {
1316         PyErr_Format(PyExc_TypeError, "property %s is not readable",
1317                      param_name);
1318         return NULL;
1319     }
1320     g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
1321     Py_BEGIN_ALLOW_THREADS;
1322     g_object_get_property(self->obj, param_name, &value);
1323     Py_END_ALLOW_THREADS;
1324
1325     ret = pyg_param_gvalue_as_pyobject(&value, TRUE, pspec);
1326     g_value_unset(&value);
1327     return ret;
1328 }
1329
1330 static PyObject *
1331 pygobject_get_properties(PyGObject *self, PyObject *args)
1332 {
1333     GObjectClass *class;
1334     int len, i;
1335     PyObject *tuple;
1336
1337     if ((len = PyTuple_Size(args)) < 1) {
1338         PyErr_SetString(PyExc_TypeError, "requires at least one argument");
1339         return NULL;
1340     }
1341
1342     tuple = PyTuple_New(len);
1343     class = G_OBJECT_GET_CLASS(self->obj);
1344     for (i = 0; i < len; i++) {
1345         PyObject *py_property = PyTuple_GetItem(args, i);
1346         gchar *property_name;
1347         GParamSpec *pspec;
1348         GValue value = { 0 };
1349         PyObject *item;
1350
1351         if (!PYGLIB_PyUnicode_Check(py_property)) {
1352             PyErr_SetString(PyExc_TypeError,
1353                             "Expected string argument for property.");
1354             return NULL;
1355         }
1356
1357         property_name = PYGLIB_PyUnicode_AsString(py_property);
1358
1359         pspec = g_object_class_find_property(class,
1360                                          property_name);
1361         if (!pspec) {
1362             PyErr_Format(PyExc_TypeError,
1363                          "object of type `%s' does not have property `%s'",
1364                          g_type_name(G_OBJECT_TYPE(self->obj)), property_name);
1365         return NULL;
1366         }
1367         if (!(pspec->flags & G_PARAM_READABLE)) {
1368             PyErr_Format(PyExc_TypeError, "property %s is not readable",
1369                         property_name);
1370             return NULL;
1371         }
1372         g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
1373
1374         Py_BEGIN_ALLOW_THREADS;
1375         g_object_get_property(self->obj, property_name, &value);
1376         Py_END_ALLOW_THREADS;
1377
1378         item = pyg_value_as_pyobject(&value, TRUE);
1379         PyTuple_SetItem(tuple, i, item);
1380
1381         g_value_unset(&value);
1382     }
1383
1384     return tuple;
1385 }
1386
1387 static PyObject *
1388 pygobject_set_property(PyGObject *self, PyObject *args)
1389 {
1390     gchar *param_name;
1391     GParamSpec *pspec;
1392     PyObject *pvalue;
1393     int ret = -1;
1394
1395     if (!PyArg_ParseTuple(args, "sO:GObject.set_property", &param_name,
1396                           &pvalue))
1397         return NULL;
1398     
1399     CHECK_GOBJECT(self);
1400     
1401     pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj),
1402                                          param_name);
1403     if (!pspec) {
1404         PyErr_Format(PyExc_TypeError,
1405                      "object of type `%s' does not have property `%s'",
1406                      g_type_name(G_OBJECT_TYPE(self->obj)), param_name);
1407         return NULL;
1408     }
1409     
1410     ret = pygi_set_property_value (self, pspec, pvalue);
1411     if (ret == 0)
1412         goto done;
1413     else if (PyErr_Occurred())
1414         return  NULL;
1415
1416     if (!set_property_from_pspec(self->obj, pspec, pvalue))
1417         return NULL;
1418
1419 done:
1420
1421     Py_INCREF(Py_None);
1422     return Py_None;
1423 }
1424
1425 static PyObject *
1426 pygobject_set_properties(PyGObject *self, PyObject *args, PyObject *kwargs)
1427 {    
1428     GObjectClass    *class;
1429     Py_ssize_t      pos;
1430     PyObject        *value;
1431     PyObject        *key;
1432     PyObject        *result = NULL;
1433
1434     CHECK_GOBJECT(self);
1435
1436     class = G_OBJECT_GET_CLASS(self->obj);
1437     
1438     g_object_freeze_notify (G_OBJECT(self->obj));
1439     pos = 0;
1440
1441     while (kwargs && PyDict_Next (kwargs, &pos, &key, &value)) {
1442         gchar *key_str = PYGLIB_PyUnicode_AsString(key);
1443         GParamSpec *pspec;
1444         int ret = -1;
1445
1446         pspec = g_object_class_find_property(class, key_str);
1447         if (!pspec) {
1448             gchar buf[512];
1449
1450             g_snprintf(buf, sizeof(buf),
1451                        "object `%s' doesn't support property `%s'",
1452                        g_type_name(G_OBJECT_TYPE(self->obj)), key_str);
1453             PyErr_SetString(PyExc_TypeError, buf);
1454             goto exit;
1455         }
1456
1457         ret = pygi_set_property_value (self, pspec, value);
1458         if (ret != 0) {
1459             /* Non-zero return code means that either an error occured ...*/
1460             if (PyErr_Occurred())
1461                 goto exit;
1462
1463             /* ... or the property couldn't be found , so let's try the default
1464              * call. */
1465             if (!set_property_from_pspec(G_OBJECT(self->obj), pspec, value))
1466                 goto exit;
1467         }
1468     }
1469
1470     result = Py_None;
1471
1472  exit:
1473     g_object_thaw_notify (G_OBJECT(self->obj));
1474     Py_XINCREF(result);
1475     return result;
1476 }
1477
1478 /* custom closure for gobject bindings */
1479 static void
1480 pygbinding_closure_invalidate(gpointer data, GClosure *closure)
1481 {
1482     PyGClosure *pc = (PyGClosure *)closure;
1483     PyGILState_STATE state;
1484
1485     state = pyglib_gil_state_ensure();
1486     Py_XDECREF(pc->callback);
1487     Py_XDECREF(pc->extra_args);
1488     pyglib_gil_state_release(state);
1489
1490     pc->callback = NULL;
1491     pc->extra_args = NULL;
1492 }
1493
1494 static void
1495 pygbinding_marshal (GClosure     *closure,
1496                     GValue       *return_value,
1497                     guint         n_param_values,
1498                     const GValue *param_values,
1499                     gpointer      invocation_hint,
1500                     gpointer      marshal_data)
1501 {
1502     PyGILState_STATE state;
1503     PyGClosure *pc = (PyGClosure *)closure;
1504     PyObject *params, *ret;
1505     GValue *out_value;
1506
1507     state = pyglib_gil_state_ensure();
1508
1509     /* construct Python tuple for the parameter values */
1510     params = PyTuple_New(2);
1511     PyTuple_SetItem (params, 0, pyg_value_as_pyobject(&param_values[0], FALSE));
1512     PyTuple_SetItem (params, 1, pyg_value_as_pyobject(&param_values[1], FALSE));
1513
1514     /* params passed to function may have extra arguments */
1515     if (pc->extra_args) {
1516         PyObject *tuple = params;
1517         params = PySequence_Concat(tuple, pc->extra_args);
1518         Py_DECREF(tuple);
1519     }
1520     ret = PyObject_CallObject(pc->callback, params);
1521     if (!ret) {
1522         PyErr_Print ();
1523         goto out;
1524     } else if (ret == Py_None) {
1525         g_value_set_boolean (return_value, FALSE);
1526         goto out;
1527     }
1528
1529     out_value = g_value_get_boxed (&param_values[2]);
1530     if (pyg_value_from_pyobject (out_value, ret) != 0) {
1531         PyErr_SetString (PyExc_ValueError, "can't convert value");
1532         PyErr_Print ();
1533         g_value_set_boolean (return_value, FALSE);
1534     } else {
1535         g_value_set_boolean (return_value, TRUE);
1536     }
1537
1538     Py_DECREF(ret);
1539
1540 out:
1541     Py_DECREF(params);
1542     pyglib_gil_state_release(state);
1543 }
1544
1545 static GClosure *
1546 pygbinding_closure_new (PyObject *callback, PyObject *extra_args)
1547 {
1548     GClosure *closure;
1549
1550     g_return_val_if_fail(callback != NULL, NULL);
1551     closure = g_closure_new_simple(sizeof(PyGClosure), NULL);
1552     g_closure_add_invalidate_notifier(closure, NULL, pygbinding_closure_invalidate);
1553     g_closure_set_marshal(closure, pygbinding_marshal);
1554     Py_INCREF(callback);
1555     ((PyGClosure *)closure)->callback = callback;
1556     if (extra_args && extra_args != Py_None) {
1557         Py_INCREF(extra_args);
1558         if (!PyTuple_Check(extra_args)) {
1559             PyObject *tmp = PyTuple_New(1);
1560             PyTuple_SetItem(tmp, 0, extra_args);
1561             extra_args = tmp;
1562         }
1563         ((PyGClosure *)closure)->extra_args = extra_args;
1564     }
1565     return closure;
1566 }
1567
1568 static PyObject *
1569 pygobject_bind_property(PyGObject *self, PyObject *args)
1570 {
1571         gchar *source_name, *target_name;
1572         gchar *source_canon, *target_canon;
1573         PyObject *target, *source_repr, *target_repr;
1574         PyObject *transform_to, *transform_from, *user_data = NULL;
1575         GBinding *binding;
1576         GBindingFlags flags = G_BINDING_DEFAULT;
1577         GClosure *to_closure = NULL, *from_closure = NULL;
1578
1579         transform_from = NULL;
1580         transform_to = NULL;
1581
1582         if (!PyArg_ParseTuple(args, "sOs|iOOO:GObject.bind_property",
1583                               &source_name, &target, &target_name, &flags,
1584                               &transform_to, &transform_from, &user_data))
1585                 return NULL;
1586
1587         CHECK_GOBJECT(self);
1588         if (!PyObject_TypeCheck(target, &PyGObject_Type)) {
1589                 PyErr_SetString(PyExc_TypeError, "Second argument must be a GObject");
1590                 return NULL;
1591         }
1592
1593         if (transform_to && transform_to != Py_None) {
1594                 if (!PyCallable_Check (transform_to)) {
1595                         PyErr_SetString (PyExc_TypeError,
1596                                          "transform_to must be callable or None");
1597                         return NULL;
1598                 }
1599                 to_closure = pygbinding_closure_new (transform_to, user_data);
1600         }
1601
1602         if (transform_from && transform_from != Py_None) {
1603                 if (!PyCallable_Check (transform_from)) {
1604                         PyErr_SetString (PyExc_TypeError,
1605                                          "transform_from must be callable or None");
1606                         return NULL;
1607                 }
1608                 from_closure = pygbinding_closure_new (transform_from, user_data);
1609         }
1610
1611         /* Canonicalize underscores to hyphens. Note the results must be freed. */
1612         source_canon = g_strdelimit(g_strdup(source_name), "_", '-');
1613         target_canon = g_strdelimit(g_strdup(target_name), "_", '-');
1614
1615         binding = g_object_bind_property_with_closures (G_OBJECT(self->obj), source_canon,
1616                                                         pygobject_get(target), target_canon,
1617                                                         flags, to_closure, from_closure);
1618         g_free(source_canon);
1619         g_free(target_canon);
1620         source_canon = target_canon = NULL;
1621
1622         if (binding == NULL) {
1623                 source_repr = PyObject_Repr((PyObject*)self);
1624                 target_repr = PyObject_Repr(target);
1625                 PyErr_Format(PyExc_TypeError, "Cannot create binding from %s.%s to %s.%s",
1626                              PYGLIB_PyUnicode_AsString(source_repr), source_name,
1627                              PYGLIB_PyUnicode_AsString(target_repr), target_name);
1628                 Py_DECREF(source_repr);
1629                 Py_DECREF(target_repr);
1630                 return NULL;
1631         }
1632
1633         return pygbinding_weak_ref_new(G_OBJECT (binding));
1634 }
1635
1636 static PyObject *
1637 connect_helper(PyGObject *self, gchar *name, PyObject *callback, PyObject *extra_args, PyObject *object, gboolean after)
1638 {
1639     guint sigid;
1640     GQuark detail = 0;
1641     GClosure *closure = NULL;
1642     gulong handlerid;
1643     GSignalQuery query_info;
1644
1645     if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
1646                              &sigid, &detail, TRUE)) {
1647         PyObject *repr = PyObject_Repr((PyObject*)self);
1648         PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
1649                      PYGLIB_PyUnicode_AsString(repr),
1650                      name);
1651         Py_DECREF(repr);
1652         return NULL;
1653     }
1654
1655     g_signal_query (sigid, &query_info);
1656     if (!pyg_gtype_is_custom (query_info.itype)) {
1657         /* The signal is implemented by a non-Python class, probably
1658          * something in the gi repository. */
1659         closure = pygi_signal_closure_new (self, query_info.itype,
1660                                            query_info.signal_name, callback,
1661                                            extra_args, object);
1662     }
1663
1664     if (!closure) {
1665         /* The signal is either implemented at the Python level, or it comes
1666          * from a foreign class that we don't have introspection data for. */
1667         closure = pyg_closure_new (callback, extra_args, object);
1668     }
1669
1670     pygobject_watch_closure((PyObject *)self, closure);
1671     handlerid = g_signal_connect_closure_by_id(self->obj, sigid, detail,
1672                                                closure, after);
1673     return PyLong_FromUnsignedLong(handlerid);
1674 }
1675
1676 static PyObject *
1677 pygobject_connect(PyGObject *self, PyObject *args)
1678 {
1679     PyObject *first, *callback, *extra_args, *ret;
1680     gchar *name;
1681     guint len;
1682
1683     len = PyTuple_Size(args);
1684     if (len < 2) {
1685         PyErr_SetString(PyExc_TypeError,
1686                         "GObject.connect requires at least 2 arguments");
1687         return NULL;
1688     }
1689     first = PySequence_GetSlice(args, 0, 2);
1690     if (!PyArg_ParseTuple(first, "sO:GObject.connect", &name, &callback)) {
1691         Py_DECREF(first);
1692         return NULL;
1693     }
1694     Py_DECREF(first);
1695     if (!PyCallable_Check(callback)) {
1696         PyErr_SetString(PyExc_TypeError, "second argument must be callable");
1697         return NULL;
1698     }
1699     
1700     CHECK_GOBJECT(self);
1701     
1702     extra_args = PySequence_GetSlice(args, 2, len);
1703     if (extra_args == NULL)
1704         return NULL;
1705
1706     ret = connect_helper(self, name, callback, extra_args, NULL, FALSE);
1707     Py_DECREF(extra_args);
1708     return ret;
1709 }
1710
1711 static PyObject *
1712 pygobject_connect_after(PyGObject *self, PyObject *args)
1713 {
1714     PyObject *first, *callback, *extra_args, *ret;
1715     gchar *name;
1716     Py_ssize_t len;
1717
1718     len = PyTuple_Size(args);
1719     if (len < 2) {
1720         PyErr_SetString(PyExc_TypeError,
1721                         "GObject.connect_after requires at least 2 arguments");
1722         return NULL;
1723     }
1724     first = PySequence_GetSlice(args, 0, 2);
1725     if (!PyArg_ParseTuple(first, "sO:GObject.connect_after",
1726                           &name, &callback)) {
1727         Py_DECREF(first);
1728         return NULL;
1729     }
1730     Py_DECREF(first);
1731     if (!PyCallable_Check(callback)) {
1732         PyErr_SetString(PyExc_TypeError, "second argument must be callable");
1733         return NULL;
1734     }
1735     
1736     CHECK_GOBJECT(self);
1737     
1738     extra_args = PySequence_GetSlice(args, 2, len);
1739     if (extra_args == NULL)
1740         return NULL;
1741
1742     ret = connect_helper(self, name, callback, extra_args, NULL, TRUE);
1743     Py_DECREF(extra_args);
1744     return ret;
1745 }
1746
1747 static PyObject *
1748 pygobject_connect_object(PyGObject *self, PyObject *args)
1749 {
1750     PyObject *first, *callback, *extra_args, *object, *ret;
1751     gchar *name;
1752     Py_ssize_t len;
1753
1754     len = PyTuple_Size(args);
1755     if (len < 3) {
1756         PyErr_SetString(PyExc_TypeError,
1757                 "GObject.connect_object requires at least 3 arguments");
1758         return NULL;
1759     }
1760     first = PySequence_GetSlice(args, 0, 3);
1761     if (!PyArg_ParseTuple(first, "sOO:GObject.connect_object",
1762                           &name, &callback, &object)) {
1763         Py_DECREF(first);
1764         return NULL;
1765     }
1766     Py_DECREF(first);
1767     if (!PyCallable_Check(callback)) {
1768         PyErr_SetString(PyExc_TypeError, "second argument must be callable");
1769         return NULL;
1770     }
1771     
1772     CHECK_GOBJECT(self);
1773     
1774     extra_args = PySequence_GetSlice(args, 3, len);
1775     if (extra_args == NULL)
1776         return NULL;
1777
1778     ret = connect_helper(self, name, callback, extra_args, object, FALSE);
1779     Py_DECREF(extra_args);
1780     return ret;
1781 }
1782
1783 static PyObject *
1784 pygobject_connect_object_after(PyGObject *self, PyObject *args)
1785 {
1786     PyObject *first, *callback, *extra_args, *object, *ret;
1787     gchar *name;
1788     Py_ssize_t len;
1789
1790     len = PyTuple_Size(args);
1791     if (len < 3) {
1792         PyErr_SetString(PyExc_TypeError,
1793                 "GObject.connect_object_after requires at least 3 arguments");
1794         return NULL;
1795     }
1796     first = PySequence_GetSlice(args, 0, 3);
1797     if (!PyArg_ParseTuple(first, "sOO:GObject.connect_object_after",
1798                           &name, &callback, &object)) {
1799         Py_DECREF(first);
1800         return NULL;
1801     }
1802     Py_DECREF(first);
1803     if (!PyCallable_Check(callback)) {
1804         PyErr_SetString(PyExc_TypeError, "second argument must be callable");
1805         return NULL;
1806     }
1807     
1808     CHECK_GOBJECT(self);
1809     
1810     extra_args = PySequence_GetSlice(args, 3, len);
1811     if (extra_args == NULL)
1812         return NULL;
1813
1814     ret = connect_helper(self, name, callback, extra_args, object, TRUE);
1815     Py_DECREF(extra_args);
1816     return ret;
1817 }
1818
1819 static PyObject *
1820 pygobject_emit(PyGObject *self, PyObject *args)
1821 {
1822     guint signal_id, i, j;
1823     Py_ssize_t len;
1824     GQuark detail;
1825     PyObject *first, *py_ret, *repr = NULL;
1826     gchar *name;
1827     GSignalQuery query;
1828     GValue *params, ret = { 0, };
1829     
1830     len = PyTuple_Size(args);
1831     if (len < 1) {
1832         PyErr_SetString(PyExc_TypeError,"GObject.emit needs at least one arg");
1833         return NULL;
1834     }
1835     first = PySequence_GetSlice(args, 0, 1);
1836     if (!PyArg_ParseTuple(first, "s:GObject.emit", &name)) {
1837         Py_DECREF(first);
1838         return NULL;
1839     }
1840     Py_DECREF(first);
1841     
1842     CHECK_GOBJECT(self);
1843     
1844     if (!g_signal_parse_name(name, G_OBJECT_TYPE(self->obj),
1845                              &signal_id, &detail, TRUE)) {
1846         repr = PyObject_Repr((PyObject*)self);
1847         PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
1848                      PYGLIB_PyUnicode_AsString(repr),
1849                      name);
1850         Py_DECREF(repr);
1851         return NULL;
1852     }
1853     g_signal_query(signal_id, &query);
1854     if (len != query.n_params + 1) {
1855         gchar buf[128];
1856
1857         g_snprintf(buf, sizeof(buf),
1858                    "%d parameters needed for signal %s; %ld given",
1859                    query.n_params, name, (long int) (len - 1));
1860         PyErr_SetString(PyExc_TypeError, buf);
1861         return NULL;
1862     }
1863
1864     params = g_new0(GValue, query.n_params + 1);
1865     g_value_init(&params[0], G_OBJECT_TYPE(self->obj));
1866     g_value_set_object(&params[0], G_OBJECT(self->obj));
1867
1868     for (i = 0; i < query.n_params; i++)
1869         g_value_init(&params[i + 1],
1870                      query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE);
1871     for (i = 0; i < query.n_params; i++) {
1872         PyObject *item = PyTuple_GetItem(args, i+1);
1873
1874         if (pyg_value_from_pyobject(&params[i+1], item) < 0) {
1875             gchar buf[128];
1876             g_snprintf(buf, sizeof(buf),
1877                        "could not convert type %s to %s required for parameter %d",
1878                        Py_TYPE(item)->tp_name,
1879                        G_VALUE_TYPE_NAME(&params[i+1]), i);
1880             PyErr_SetString(PyExc_TypeError, buf);
1881
1882             for (j = 0; j <= i; j++)
1883                 g_value_unset(&params[j]);
1884
1885             g_free(params);
1886             return NULL;
1887         }
1888     }    
1889
1890     if (query.return_type != G_TYPE_NONE)
1891         g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
1892     
1893     g_signal_emitv(params, signal_id, detail, &ret);
1894
1895     for (i = 0; i < query.n_params + 1; i++)
1896         g_value_unset(&params[i]);
1897     
1898     g_free(params);
1899     if ((query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE) != G_TYPE_NONE) {
1900         py_ret = pyg_value_as_pyobject(&ret, TRUE);
1901         g_value_unset(&ret);
1902     } else {
1903         Py_INCREF(Py_None);
1904         py_ret = Py_None;
1905     }
1906
1907     return py_ret;
1908 }
1909
1910 static PyObject *
1911 pygobject_chain_from_overridden(PyGObject *self, PyObject *args)
1912 {
1913     GSignalInvocationHint *ihint;
1914     guint signal_id, i;
1915     Py_ssize_t len;
1916     PyObject *py_ret;
1917     const gchar *name;
1918     GSignalQuery query;
1919     GValue *params, ret = { 0, };
1920     
1921     CHECK_GOBJECT(self);
1922     
1923     ihint = g_signal_get_invocation_hint(self->obj);
1924     if (!ihint) {
1925         PyErr_SetString(PyExc_TypeError, "could not find signal invocation "
1926                         "information for this object.");
1927         return NULL;
1928     }
1929
1930     signal_id = ihint->signal_id;
1931     name = g_signal_name(signal_id);
1932
1933     len = PyTuple_Size(args);
1934     if (signal_id == 0) {
1935         PyErr_SetString(PyExc_TypeError, "unknown signal name");
1936         return NULL;
1937     }
1938     g_signal_query(signal_id, &query);
1939     if (len != query.n_params) {
1940         gchar buf[128];
1941
1942         g_snprintf(buf, sizeof(buf),
1943                    "%d parameters needed for signal %s; %ld given",
1944                    query.n_params, name, (long int) len);
1945         PyErr_SetString(PyExc_TypeError, buf);
1946         return NULL;
1947     }
1948     params = g_new0(GValue, query.n_params + 1);
1949     g_value_init(&params[0], G_OBJECT_TYPE(self->obj));
1950     g_value_set_object(&params[0], G_OBJECT(self->obj));
1951
1952     for (i = 0; i < query.n_params; i++)
1953         g_value_init(&params[i + 1],
1954                      query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE);
1955     for (i = 0; i < query.n_params; i++) {
1956         PyObject *item = PyTuple_GetItem(args, i);
1957
1958         if (pyg_boxed_check(item, (query.param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE))) {
1959             g_value_set_static_boxed(&params[i+1], pyg_boxed_get(item, void));
1960         }
1961         else if (pyg_value_from_pyobject(&params[i+1], item) < 0) {
1962             gchar buf[128];
1963
1964             g_snprintf(buf, sizeof(buf),
1965                        "could not convert type %s to %s required for parameter %d",
1966                        Py_TYPE(item)->tp_name,
1967                        g_type_name(G_VALUE_TYPE(&params[i+1])), i);
1968             PyErr_SetString(PyExc_TypeError, buf);
1969             for (i = 0; i < query.n_params + 1; i++)
1970                 g_value_unset(&params[i]);
1971             g_free(params);
1972             return NULL;
1973         }
1974     }
1975     if (query.return_type != G_TYPE_NONE)
1976         g_value_init(&ret, query.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
1977     g_signal_chain_from_overridden(params, &ret);
1978     for (i = 0; i < query.n_params + 1; i++)
1979         g_value_unset(&params[i]);
1980     g_free(params);
1981     if (query.return_type != G_TYPE_NONE) {
1982         py_ret = pyg_value_as_pyobject(&ret, TRUE);
1983         g_value_unset(&ret);
1984     } else {
1985         Py_INCREF(Py_None);
1986         py_ret = Py_None;
1987     }
1988     return py_ret;
1989 }
1990
1991
1992 static PyObject *
1993 pygobject_weak_ref(PyGObject *self, PyObject *args)
1994 {
1995     int len;
1996     PyObject *callback = NULL, *user_data = NULL;
1997     PyObject *retval;
1998
1999     CHECK_GOBJECT(self);
2000
2001     if ((len = PySequence_Length(args)) >= 1) {
2002         callback = PySequence_ITEM(args, 0);
2003         user_data = PySequence_GetSlice(args, 1, len);
2004     }
2005     retval = pygobject_weak_ref_new(self->obj, callback, user_data);
2006     Py_XDECREF(callback);
2007     Py_XDECREF(user_data);
2008     return retval;
2009 }
2010
2011
2012 static PyObject *
2013 pygobject_copy(PyGObject *self)
2014 {
2015     PyErr_SetString(PyExc_TypeError,
2016                     "GObject descendants' instances are non-copyable");
2017     return NULL;
2018 }
2019
2020 static PyObject *
2021 pygobject_deepcopy(PyGObject *self, PyObject *args)
2022 {
2023     PyErr_SetString(PyExc_TypeError,
2024                     "GObject descendants' instances are non-copyable");
2025     return NULL;
2026 }
2027
2028
2029 static PyObject *
2030 pygobject_disconnect_by_func(PyGObject *self, PyObject *args)
2031 {
2032     PyObject *pyfunc = NULL, *repr = NULL;
2033     GClosure *closure = NULL;
2034     guint retval;
2035     
2036     CHECK_GOBJECT(self);
2037
2038     if (!PyArg_ParseTuple(args, "O:GObject.disconnect_by_func", &pyfunc))
2039         return NULL;
2040
2041     if (!PyCallable_Check(pyfunc)) {
2042         PyErr_SetString(PyExc_TypeError, "first argument must be callable");
2043         return NULL;
2044     }
2045
2046     closure = gclosure_from_pyfunc(self, pyfunc);
2047     if (!closure) {
2048         repr = PyObject_Repr((PyObject*)pyfunc);
2049         PyErr_Format(PyExc_TypeError, "nothing connected to %s",
2050                      PYGLIB_PyUnicode_AsString(repr));
2051         Py_DECREF(repr);
2052         return NULL;
2053     }
2054     
2055     retval = g_signal_handlers_disconnect_matched(self->obj,
2056                                                   G_SIGNAL_MATCH_CLOSURE,
2057                                                   0, 0,
2058                                                   closure,
2059                                                   NULL, NULL);
2060     return PYGLIB_PyLong_FromLong(retval);
2061 }
2062
2063 static PyObject *
2064 pygobject_handler_block_by_func(PyGObject *self, PyObject *args)
2065 {
2066     PyObject *pyfunc = NULL, *repr = NULL;
2067     GClosure *closure = NULL;
2068     guint retval;
2069     
2070     CHECK_GOBJECT(self);
2071
2072     if (!PyArg_ParseTuple(args, "O:GObject.handler_block_by_func", &pyfunc))
2073         return NULL;
2074
2075     if (!PyCallable_Check(pyfunc)) {
2076         PyErr_SetString(PyExc_TypeError, "first argument must be callable");
2077         return NULL;
2078     }
2079
2080     closure = gclosure_from_pyfunc(self, pyfunc);
2081     if (!closure) {
2082         repr = PyObject_Repr((PyObject*)pyfunc);
2083         PyErr_Format(PyExc_TypeError, "nothing connected to %s",
2084                      PYGLIB_PyUnicode_AsString(repr));
2085         Py_DECREF(repr);
2086         return NULL;
2087     }
2088     
2089     retval = g_signal_handlers_block_matched(self->obj,
2090                                              G_SIGNAL_MATCH_CLOSURE,
2091                                              0, 0,
2092                                              closure,
2093                                              NULL, NULL);
2094     return PYGLIB_PyLong_FromLong(retval);
2095 }
2096
2097 static PyObject *
2098 pygobject_handler_unblock_by_func(PyGObject *self, PyObject *args)
2099 {
2100     PyObject *pyfunc = NULL, *repr = NULL;
2101     GClosure *closure = NULL;
2102     guint retval;
2103     
2104     CHECK_GOBJECT(self);
2105
2106     if (!PyArg_ParseTuple(args, "O:GObject.handler_unblock_by_func", &pyfunc))
2107         return NULL;
2108
2109     if (!PyCallable_Check(pyfunc)) {
2110         PyErr_SetString(PyExc_TypeError, "first argument must be callable");
2111         return NULL;
2112     }
2113
2114     closure = gclosure_from_pyfunc(self, pyfunc);
2115     if (!closure) {
2116         repr = PyObject_Repr((PyObject*)pyfunc);
2117         PyErr_Format(PyExc_TypeError, "nothing connected to %s",
2118                      PYGLIB_PyUnicode_AsString(repr));
2119         Py_DECREF(repr);
2120         return NULL;
2121     }
2122     
2123     retval = g_signal_handlers_unblock_matched(self->obj,
2124                                                G_SIGNAL_MATCH_CLOSURE,
2125                                                0, 0,
2126                                                closure,
2127                                                NULL, NULL);
2128     return PYGLIB_PyLong_FromLong(retval);
2129 }
2130
2131
2132 static PyMethodDef pygobject_methods[] = {
2133     { "get_property", (PyCFunction)pygobject_get_property, METH_VARARGS },
2134     { "get_properties", (PyCFunction)pygobject_get_properties, METH_VARARGS },
2135     { "set_property", (PyCFunction)pygobject_set_property, METH_VARARGS },
2136     { "set_properties", (PyCFunction)pygobject_set_properties, METH_VARARGS|METH_KEYWORDS },
2137     { "bind_property", (PyCFunction)pygobject_bind_property, METH_VARARGS|METH_KEYWORDS },
2138     { "connect", (PyCFunction)pygobject_connect, METH_VARARGS },
2139     { "connect_after", (PyCFunction)pygobject_connect_after, METH_VARARGS },
2140     { "connect_object", (PyCFunction)pygobject_connect_object, METH_VARARGS },
2141     { "connect_object_after", (PyCFunction)pygobject_connect_object_after, METH_VARARGS },
2142     { "disconnect_by_func", (PyCFunction)pygobject_disconnect_by_func, METH_VARARGS },
2143     { "handler_block_by_func", (PyCFunction)pygobject_handler_block_by_func, METH_VARARGS },
2144     { "handler_unblock_by_func", (PyCFunction)pygobject_handler_unblock_by_func, METH_VARARGS },
2145     { "emit", (PyCFunction)pygobject_emit, METH_VARARGS },
2146     { "chain", (PyCFunction)pygobject_chain_from_overridden,METH_VARARGS },
2147     { "weak_ref", (PyCFunction)pygobject_weak_ref, METH_VARARGS },
2148     { "__copy__", (PyCFunction)pygobject_copy, METH_NOARGS },
2149     { "__deepcopy__", (PyCFunction)pygobject_deepcopy, METH_VARARGS },
2150     { NULL, NULL, 0 }
2151 };
2152
2153
2154 static PyObject *
2155 pygobject_get_dict(PyGObject *self, void *closure)
2156 {
2157     if (self->inst_dict == NULL) {
2158         self->inst_dict = PyDict_New();
2159         if (self->inst_dict == NULL)
2160             return NULL;
2161         if (G_LIKELY(self->obj))
2162             pygobject_switch_to_toggle_ref(self);
2163     }
2164     Py_INCREF(self->inst_dict);
2165     return self->inst_dict;
2166 }
2167
2168 static PyObject *
2169 pygobject_get_refcount(PyGObject *self, void *closure)
2170 {
2171     if (self->obj == NULL) {
2172         PyErr_Format(PyExc_TypeError, "GObject instance is not yet created");
2173         return NULL;
2174     }
2175     return PYGLIB_PyLong_FromLong(self->obj->ref_count);
2176 }
2177
2178 static PyObject *
2179 pygobject_get_pointer(PyGObject *self, void *closure)
2180 {
2181     return PYGLIB_CPointer_WrapPointer (self->obj, NULL);
2182 }
2183
2184 static int
2185 pygobject_setattro(PyObject *self, PyObject *name, PyObject *value)
2186 {
2187     int res;
2188     PyGObject *gself = (PyGObject *) self;
2189     PyObject *inst_dict_before = gself->inst_dict;
2190       /* call parent type's setattro */
2191     res = PyGObject_Type.tp_base->tp_setattro(self, name, value);
2192     if (inst_dict_before == NULL && gself->inst_dict != NULL) {
2193         if (G_LIKELY(gself->obj))
2194             pygobject_switch_to_toggle_ref(gself);
2195     }
2196     return res;
2197 }
2198
2199 static PyGetSetDef pygobject_getsets[] = {
2200     { "__dict__", (getter)pygobject_get_dict, (setter)0 },
2201     { "__grefcount__", (getter)pygobject_get_refcount, (setter)0, },
2202     { "__gpointer__", (getter)pygobject_get_pointer, (setter)0, },
2203     { NULL, 0, 0 }
2204 };
2205
2206 /* ------------------------------------ */
2207 /* ****** GObject weak reference ****** */
2208 /* ------------------------------------ */
2209
2210 typedef struct {
2211     PyObject_HEAD
2212     GObject *obj;
2213     PyObject *callback;
2214     PyObject *user_data;
2215     gboolean have_floating_ref;
2216 } PyGObjectWeakRef;
2217
2218 PYGLIB_DEFINE_TYPE("gi._gobject.GObjectWeakRef", PyGObjectWeakRef_Type, PyGObjectWeakRef);
2219
2220 static int
2221 pygobject_weak_ref_traverse(PyGObjectWeakRef *self, visitproc visit, void *arg)
2222 {
2223     if (self->callback && visit(self->callback, arg) < 0)
2224         return -1;
2225     if (self->user_data && visit(self->user_data, arg) < 0)
2226         return -1;
2227     return 0;
2228 }
2229
2230 static void
2231 pygobject_weak_ref_notify(PyGObjectWeakRef *self, GObject *dummy)
2232 {
2233     self->obj = NULL;
2234     if (self->callback) {
2235         PyObject *retval;
2236         PyGILState_STATE state = pyglib_gil_state_ensure();
2237         retval = PyObject_Call(self->callback, self->user_data, NULL);
2238         if (retval) {
2239             if (retval != Py_None)
2240                 PyErr_Format(PyExc_TypeError,
2241                              "GObject weak notify callback returned a value"
2242                              " of type %s, should return None",
2243                              Py_TYPE(retval)->tp_name);
2244             Py_DECREF(retval);
2245             PyErr_Print();
2246         } else
2247             PyErr_Print();
2248         Py_CLEAR(self->callback);
2249         Py_CLEAR(self->user_data);
2250         if (self->have_floating_ref) {
2251             self->have_floating_ref = FALSE;
2252             Py_DECREF((PyObject *) self);
2253         }
2254         pyglib_gil_state_release(state);
2255     }
2256 }
2257
2258 static inline int
2259 pygobject_weak_ref_clear(PyGObjectWeakRef *self)
2260 {
2261     Py_CLEAR(self->callback);
2262     Py_CLEAR(self->user_data);
2263     if (self->obj) {
2264         g_object_weak_unref(self->obj, (GWeakNotify) pygobject_weak_ref_notify, self);
2265         self->obj = NULL;
2266     }
2267     return 0;
2268 }
2269
2270 static void
2271 pygobject_weak_ref_dealloc(PyGObjectWeakRef *self)
2272 {
2273     PyObject_GC_UnTrack((PyObject *)self);
2274     pygobject_weak_ref_clear(self);
2275     PyObject_GC_Del(self);
2276 }
2277
2278 static PyObject *
2279 pygobject_weak_ref_new(GObject *obj, PyObject *callback, PyObject *user_data)
2280 {
2281     PyGObjectWeakRef *self;
2282
2283     self = PyObject_GC_New(PyGObjectWeakRef, &PyGObjectWeakRef_Type);
2284     self->callback = callback;
2285     self->user_data = user_data;
2286     Py_XINCREF(self->callback);
2287     Py_XINCREF(self->user_data);
2288     self->obj = obj;
2289     g_object_weak_ref(self->obj, (GWeakNotify) pygobject_weak_ref_notify, self);
2290     if (callback != NULL) {
2291           /* when we have a callback, we should INCREF the weakref
2292            * object to make it stay alive even if it goes out of scope */
2293         self->have_floating_ref = TRUE;
2294         Py_INCREF((PyObject *) self);
2295     }
2296     return (PyObject *) self;
2297 }
2298
2299 static PyObject *
2300 pygobject_weak_ref_unref(PyGObjectWeakRef *self, PyObject *args)
2301 {
2302     if (!self->obj) {
2303         PyErr_SetString(PyExc_ValueError, "weak ref already unreffed");
2304         return NULL;
2305     }
2306     g_object_weak_unref(self->obj, (GWeakNotify) pygobject_weak_ref_notify, self);
2307     self->obj = NULL;
2308     if (self->have_floating_ref) {
2309         self->have_floating_ref = FALSE;
2310         Py_DECREF(self);
2311     }
2312     Py_INCREF(Py_None);
2313     return Py_None;
2314 }
2315
2316 static PyMethodDef pygobject_weak_ref_methods[] = {
2317     { "unref", (PyCFunction)pygobject_weak_ref_unref, METH_NOARGS},
2318     { NULL, NULL, 0}
2319 };
2320
2321 static PyObject *
2322 pygobject_weak_ref_call(PyGObjectWeakRef *self, PyObject *args, PyObject *kw)
2323 {
2324     static char *argnames[] = {NULL};
2325
2326     if (!PyArg_ParseTupleAndKeywords(args, kw, ":__call__", argnames))
2327         return NULL;
2328
2329     if (self->obj)
2330         return pygobject_new(self->obj);
2331     else {
2332         Py_INCREF(Py_None);
2333         return Py_None;
2334     }
2335 }
2336
2337
2338 /* -------------- GBinding Weak Reference ----------------- */
2339
2340 /**
2341  * BindingWeakRef
2342  *
2343  * The BindingWeakRef object is used to manage GBinding objects within python
2344  * created through GObject.bind_property. It is a sub-class PyGObjectWeakRef so
2345  * that we can maintain the same reference counting semantics between Python
2346  * and GObject Binding objects. This gives explicit direct control of the
2347  * binding lifetime by using the "unbind" method on the BindingWeakRef object
2348  * along with implicit management based on the lifetime of the source or
2349  * target objects.
2350  */
2351
2352 PYGLIB_DEFINE_TYPE("gi._gobject.GBindingWeakRef", PyGBindingWeakRef_Type, PyGObjectWeakRef);
2353
2354 static PyObject *
2355 pygbinding_weak_ref_new(GObject *obj)
2356 {
2357         PyGObjectWeakRef *self;
2358
2359         self = PyObject_GC_New(PyGObjectWeakRef, &PyGBindingWeakRef_Type);
2360         self->callback = NULL;
2361         self->user_data = NULL;
2362         self->obj = obj;
2363         g_object_weak_ref(self->obj, (GWeakNotify) pygobject_weak_ref_notify, self);
2364         return (PyObject *) self;
2365 }
2366
2367 static PyObject *
2368 pygbinding_weak_ref_unbind(PyGObjectWeakRef *self, PyObject *args)
2369 {
2370     if (!self->obj) {
2371         PyErr_SetString(PyExc_ValueError, "weak binding ref already unreffed");
2372         return NULL;
2373     }
2374     g_object_unref(self->obj);
2375     Py_INCREF(Py_None);
2376     return Py_None;
2377 }
2378
2379 static PyMethodDef pygbinding_weak_ref_methods[] = {
2380     { "unbind", (PyCFunction)pygbinding_weak_ref_unbind, METH_NOARGS},
2381     { NULL, NULL, 0}
2382 };
2383
2384
2385 static gpointer
2386 pyobject_copy(gpointer boxed)
2387 {
2388     PyObject *object = boxed;
2389
2390     Py_INCREF(object);
2391     return object;
2392 }
2393
2394 static void
2395 pyobject_free(gpointer boxed)
2396 {
2397     PyObject *object = boxed;
2398     PyGILState_STATE state;
2399
2400     state = pyglib_gil_state_ensure();
2401     Py_DECREF(object);
2402     pyglib_gil_state_release(state);
2403 }
2404
2405 void
2406 pygobject_object_register_types(PyObject *d)
2407 {
2408     PyObject *o, *descr;
2409
2410     pygobject_custom_key = g_quark_from_static_string("PyGObject::custom");
2411     pygobject_class_key = g_quark_from_static_string("PyGObject::class");
2412     pygobject_class_init_key = g_quark_from_static_string("PyGObject::class-init");
2413     pygobject_wrapper_key = g_quark_from_static_string("PyGObject::wrapper");
2414     pygobject_has_updated_constructor_key =
2415         g_quark_from_static_string("PyGObject::has-updated-constructor");
2416     pygobject_instance_data_key = g_quark_from_static_string("PyGObject::instance-data");
2417
2418     /* GObject */
2419     if (!PY_TYPE_OBJECT)
2420         PY_TYPE_OBJECT = g_boxed_type_register_static("PyObject",
2421                                                       pyobject_copy,
2422                                                       pyobject_free);
2423     PyGObject_Type.tp_dealloc = (destructor)pygobject_dealloc;
2424     PyGObject_Type.tp_richcompare = pygobject_richcompare;
2425     PyGObject_Type.tp_repr = (reprfunc)pygobject_repr;
2426     PyGObject_Type.tp_hash = (hashfunc)pygobject_hash;
2427     PyGObject_Type.tp_setattro = (setattrofunc)pygobject_setattro;
2428     PyGObject_Type.tp_flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2429                                Py_TPFLAGS_HAVE_GC);
2430     PyGObject_Type.tp_traverse = (traverseproc)pygobject_traverse;
2431     PyGObject_Type.tp_clear = (inquiry)pygobject_clear;
2432     PyGObject_Type.tp_weaklistoffset = offsetof(PyGObject, weakreflist);
2433     PyGObject_Type.tp_methods = pygobject_methods;
2434     PyGObject_Type.tp_getset = pygobject_getsets;
2435     PyGObject_Type.tp_dictoffset = offsetof(PyGObject, inst_dict);
2436     PyGObject_Type.tp_init = (initproc)pygobject_init;
2437     PyGObject_Type.tp_free = (freefunc)pygobject_free;
2438     PyGObject_Type.tp_alloc = PyType_GenericAlloc;
2439     PyGObject_Type.tp_new = PyType_GenericNew;
2440     pygobject_register_class(d, "GObject", G_TYPE_OBJECT,
2441                              &PyGObject_Type, NULL);
2442     PyDict_SetItemString(PyGObject_Type.tp_dict, "__gdoc__",
2443                          pyg_object_descr_doc_get());
2444
2445     /* GProps */
2446     PyGProps_Type.tp_dealloc = (destructor)PyGProps_dealloc;
2447     PyGProps_Type.tp_as_sequence = (PySequenceMethods*)&_PyGProps_as_sequence;
2448     PyGProps_Type.tp_getattro = (getattrofunc)PyGProps_getattro;
2449     PyGProps_Type.tp_setattro = (setattrofunc)PyGProps_setattro;
2450     PyGProps_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
2451     PyGProps_Type.tp_doc = "The properties of the GObject accessible as "
2452         "Python attributes.";
2453     PyGProps_Type.tp_traverse = (traverseproc)pygobject_props_traverse;
2454     PyGProps_Type.tp_iter = (getiterfunc)pygobject_props_get_iter;
2455     if (PyType_Ready(&PyGProps_Type) < 0)
2456         return;
2457
2458     /* GPropsDescr */
2459     PyGPropsDescr_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2460     PyGPropsDescr_Type.tp_descr_get = pyg_props_descr_descr_get;
2461     if (PyType_Ready(&PyGPropsDescr_Type) < 0)
2462         return;
2463     descr = PyObject_New(PyObject, &PyGPropsDescr_Type);
2464     PyDict_SetItemString(PyGObject_Type.tp_dict, "props", descr);
2465     PyDict_SetItemString(PyGObject_Type.tp_dict, "__module__",
2466                         o=PYGLIB_PyUnicode_FromString("gi._gobject._gobject"));
2467     Py_DECREF(o);
2468
2469     /* GPropsIter */
2470     PyGPropsIter_Type.tp_dealloc = (destructor)pyg_props_iter_dealloc;
2471     PyGPropsIter_Type.tp_flags = Py_TPFLAGS_DEFAULT;
2472     PyGPropsIter_Type.tp_doc = "GObject properties iterator";
2473     PyGPropsIter_Type.tp_iternext = (iternextfunc)pygobject_props_iter_next;
2474     if (PyType_Ready(&PyGPropsIter_Type) < 0)
2475         return;
2476
2477     PyGObjectWeakRef_Type.tp_dealloc = (destructor)pygobject_weak_ref_dealloc;
2478     PyGObjectWeakRef_Type.tp_call = (ternaryfunc)pygobject_weak_ref_call;
2479     PyGObjectWeakRef_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
2480     PyGObjectWeakRef_Type.tp_doc = "A GObject weak reference";
2481     PyGObjectWeakRef_Type.tp_traverse = (traverseproc)pygobject_weak_ref_traverse;
2482     PyGObjectWeakRef_Type.tp_clear = (inquiry)pygobject_weak_ref_clear;
2483     PyGObjectWeakRef_Type.tp_methods = pygobject_weak_ref_methods;
2484     if (PyType_Ready(&PyGObjectWeakRef_Type) < 0)
2485         return;
2486     PyDict_SetItemString(d, "GObjectWeakRef", (PyObject *) &PyGObjectWeakRef_Type);
2487
2488     PyGBindingWeakRef_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
2489     PyGBindingWeakRef_Type.tp_doc = "A GBinding weak reference";
2490     PyGBindingWeakRef_Type.tp_methods = pygbinding_weak_ref_methods;
2491     PyGBindingWeakRef_Type.tp_base = &PyGObjectWeakRef_Type;
2492     if (PyType_Ready(&PyGBindingWeakRef_Type) < 0)
2493         return;
2494     PyDict_SetItemString(d, "GBindingWeakRef", (PyObject *) &PyGBindingWeakRef_Type);
2495 }