1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * pygtk- Python bindings for the GTK toolkit.
3  * Copyright (C) 1998-2003  James Henstridge
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <config.h>
20 
21 #include "pygobject-object.h"
22 #include "pygboxed.h"
23 #include "pygenum.h"
24 #include "pygflags.h"
25 #include "pygparamspec.h"
26 #include "pygi-util.h"
27 #include "pygpointer.h"
28 #include "pyginterface.h"
29 
30 #include "pygi-type.h"
31 #include "pygi-value.h"
32 #include "pygi-basictype.h"
33 
34 PyObject *
pygi_type_import_by_name(const char * namespace_,const char * name)35 pygi_type_import_by_name (const char *namespace_,
36                           const char *name)
37 {
38     gchar *module_name;
39     PyObject *py_module;
40     PyObject *py_object;
41 
42     module_name = g_strconcat ("gi.repository.", namespace_, NULL);
43 
44     py_module = PyImport_ImportModule (module_name);
45 
46     g_free (module_name);
47 
48     if (py_module == NULL) {
49         return NULL;
50     }
51 
52     py_object = PyObject_GetAttrString (py_module, name);
53 
54     Py_DECREF (py_module);
55 
56     return py_object;
57 }
58 
59 PyObject *
pygi_type_import_by_g_type(GType g_type)60 pygi_type_import_by_g_type (GType g_type)
61 {
62     GIRepository *repository;
63     GIBaseInfo *info;
64     PyObject *type;
65 
66     repository = g_irepository_get_default();
67 
68     info = g_irepository_find_by_gtype (repository, g_type);
69     if (info == NULL) {
70         return NULL;
71     }
72 
73     type = pygi_type_import_by_gi_info (info);
74     g_base_info_unref (info);
75 
76     return type;
77 }
78 
79 PyObject *
pygi_type_import_by_gi_info(GIBaseInfo * info)80 pygi_type_import_by_gi_info (GIBaseInfo *info)
81 {
82     return pygi_type_import_by_name (g_base_info_get_namespace (info),
83                                      g_base_info_get_name (info));
84 }
85 
86 PyObject *
pygi_type_get_from_g_type(GType g_type)87 pygi_type_get_from_g_type (GType g_type)
88 {
89     PyObject *py_g_type;
90     PyObject *py_type;
91 
92     py_g_type = pyg_type_wrapper_new (g_type);
93     if (py_g_type == NULL) {
94         return NULL;
95     }
96 
97     py_type = PyObject_GetAttrString (py_g_type, "pytype");
98     if (py_type == Py_None) {
99         py_type = pygi_type_import_by_g_type (g_type);
100     }
101 
102     Py_DECREF (py_g_type);
103 
104     return py_type;
105 }
106 
107 /* -------------- __gtype__ objects ---------------------------- */
108 
109 typedef struct {
110     PyObject_HEAD
111     GType type;
112 } PyGTypeWrapper;
113 
114 PYGI_DEFINE_TYPE("gobject.GType", PyGTypeWrapper_Type, PyGTypeWrapper);
115 
116 static PyObject*
generic_gsize_richcompare(gsize a,gsize b,int op)117 generic_gsize_richcompare(gsize a, gsize b, int op)
118 {
119     PyObject *res;
120 
121     switch (op) {
122 
123       case Py_EQ:
124         res = (a == b) ? Py_True : Py_False;
125         Py_INCREF(res);
126         break;
127 
128       case Py_NE:
129         res = (a != b) ? Py_True : Py_False;
130         Py_INCREF(res);
131         break;
132 
133 
134       case Py_LT:
135         res = (a < b) ? Py_True : Py_False;
136         Py_INCREF(res);
137         break;
138 
139       case Py_LE:
140         res = (a <= b) ? Py_True : Py_False;
141         Py_INCREF(res);
142         break;
143 
144       case Py_GT:
145         res = (a > b) ? Py_True : Py_False;
146         Py_INCREF(res);
147         break;
148 
149       case Py_GE:
150         res = (a >= b) ? Py_True : Py_False;
151         Py_INCREF(res);
152         break;
153 
154       default:
155         res = Py_NotImplemented;
156         Py_INCREF(res);
157         break;
158     }
159 
160     return res;
161 }
162 
163 static PyObject*
pyg_type_wrapper_richcompare(PyObject * self,PyObject * other,int op)164 pyg_type_wrapper_richcompare(PyObject *self, PyObject *other, int op)
165 {
166     if (Py_TYPE(self) == Py_TYPE(other) && Py_TYPE(self) == &PyGTypeWrapper_Type)
167         return generic_gsize_richcompare(((PyGTypeWrapper*)self)->type,
168                                         ((PyGTypeWrapper*)other)->type,
169                                         op);
170     else {
171         Py_INCREF(Py_NotImplemented);
172         return Py_NotImplemented;
173     }
174 }
175 
176 static long
pyg_type_wrapper_hash(PyGTypeWrapper * self)177 pyg_type_wrapper_hash(PyGTypeWrapper *self)
178 {
179     return (long)self->type;
180 }
181 
182 static PyObject *
pyg_type_wrapper_repr(PyGTypeWrapper * self)183 pyg_type_wrapper_repr(PyGTypeWrapper *self)
184 {
185     char buf[80];
186     const gchar *name = g_type_name(self->type);
187 
188     g_snprintf(buf, sizeof(buf), "<GType %s (%lu)>",
189 	       name?name:"invalid", (unsigned long int) self->type);
190     return PyUnicode_FromString (buf);
191 }
192 
193 static void
pyg_type_wrapper_dealloc(PyGTypeWrapper * self)194 pyg_type_wrapper_dealloc(PyGTypeWrapper *self)
195 {
196     PyObject_DEL(self);
197 }
198 
199 static GQuark
_pyg_type_key(GType type)200 _pyg_type_key(GType type) {
201     GQuark key;
202 
203     if (g_type_is_a(type, G_TYPE_INTERFACE)) {
204         key = pyginterface_type_key;
205     } else if (g_type_is_a(type, G_TYPE_ENUM)) {
206         key = pygenum_class_key;
207     } else if (g_type_is_a(type, G_TYPE_FLAGS)) {
208         key = pygflags_class_key;
209     } else if (g_type_is_a(type, G_TYPE_POINTER)) {
210         key = pygpointer_class_key;
211     } else if (g_type_is_a(type, G_TYPE_BOXED)) {
212         key = pygboxed_type_key;
213     } else {
214         key = pygobject_class_key;
215     }
216 
217     return key;
218 }
219 
220 static PyObject *
_wrap_g_type_wrapper__get_pytype(PyGTypeWrapper * self,void * closure)221 _wrap_g_type_wrapper__get_pytype(PyGTypeWrapper *self, void *closure)
222 {
223     GQuark key;
224     PyObject *py_type;
225 
226     key = _pyg_type_key(self->type);
227 
228     py_type = g_type_get_qdata(self->type, key);
229     if (!py_type)
230       py_type = Py_None;
231 
232     Py_INCREF(py_type);
233     return py_type;
234 }
235 
236 static int
_wrap_g_type_wrapper__set_pytype(PyGTypeWrapper * self,PyObject * value,void * closure)237 _wrap_g_type_wrapper__set_pytype(PyGTypeWrapper *self, PyObject* value, void *closure)
238 {
239     GQuark key;
240     PyObject *py_type;
241 
242     key = _pyg_type_key(self->type);
243 
244     py_type = g_type_get_qdata(self->type, key);
245     Py_CLEAR(py_type);
246     if (value == Py_None)
247 	g_type_set_qdata(self->type, key, NULL);
248     else if (PyType_Check(value)) {
249 	Py_INCREF(value);
250 	g_type_set_qdata(self->type, key, value);
251     } else {
252 	PyErr_SetString(PyExc_TypeError, "Value must be None or a type object");
253 	return -1;
254     }
255 
256     return 0;
257 }
258 
259 static PyObject *
_wrap_g_type_wrapper__get_name(PyGTypeWrapper * self,void * closure)260 _wrap_g_type_wrapper__get_name(PyGTypeWrapper *self, void *closure)
261 {
262    const char *name = g_type_name(self->type);
263    return PyUnicode_FromString (name ? name : "invalid");
264 }
265 
266 static PyObject *
_wrap_g_type_wrapper__get_parent(PyGTypeWrapper * self,void * closure)267 _wrap_g_type_wrapper__get_parent(PyGTypeWrapper *self, void *closure)
268 {
269    return pyg_type_wrapper_new(g_type_parent(self->type));
270 }
271 
272 static PyObject *
_wrap_g_type_wrapper__get_fundamental(PyGTypeWrapper * self,void * closure)273 _wrap_g_type_wrapper__get_fundamental(PyGTypeWrapper *self, void *closure)
274 {
275    return pyg_type_wrapper_new(g_type_fundamental(self->type));
276 }
277 
278 static PyObject *
_wrap_g_type_wrapper__get_children(PyGTypeWrapper * self,void * closure)279 _wrap_g_type_wrapper__get_children(PyGTypeWrapper *self, void *closure)
280 {
281   guint n_children, i;
282   GType *children;
283   PyObject *retval;
284 
285   children = g_type_children(self->type, &n_children);
286 
287   retval = PyList_New(n_children);
288   for (i = 0; i < n_children; i++)
289       PyList_SetItem(retval, i, pyg_type_wrapper_new(children[i]));
290   g_free(children);
291 
292   return retval;
293 }
294 
295 static PyObject *
_wrap_g_type_wrapper__get_interfaces(PyGTypeWrapper * self,void * closure)296 _wrap_g_type_wrapper__get_interfaces(PyGTypeWrapper *self, void *closure)
297 {
298   guint n_interfaces, i;
299   GType *interfaces;
300   PyObject *retval;
301 
302   interfaces = g_type_interfaces(self->type, &n_interfaces);
303 
304   retval = PyList_New(n_interfaces);
305   for (i = 0; i < n_interfaces; i++)
306       PyList_SetItem(retval, i, pyg_type_wrapper_new(interfaces[i]));
307   g_free(interfaces);
308 
309   return retval;
310 }
311 
312 static PyObject *
_wrap_g_type_wrapper__get_depth(PyGTypeWrapper * self,void * closure)313 _wrap_g_type_wrapper__get_depth(PyGTypeWrapper *self, void *closure)
314 {
315   return pygi_guint_to_py (g_type_depth (self->type));
316 }
317 
318 static PyGetSetDef _PyGTypeWrapper_getsets[] = {
319     { "pytype", (getter)_wrap_g_type_wrapper__get_pytype, (setter)_wrap_g_type_wrapper__set_pytype },
320     { "name",  (getter)_wrap_g_type_wrapper__get_name, (setter)0 },
321     { "fundamental",  (getter)_wrap_g_type_wrapper__get_fundamental, (setter)0 },
322     { "parent",  (getter)_wrap_g_type_wrapper__get_parent, (setter)0 },
323     { "children",  (getter)_wrap_g_type_wrapper__get_children, (setter)0 },
324     { "interfaces",  (getter)_wrap_g_type_wrapper__get_interfaces, (setter)0 },
325     { "depth",  (getter)_wrap_g_type_wrapper__get_depth, (setter)0 },
326     { NULL, (getter)0, (setter)0 }
327 };
328 
329 static PyObject*
_wrap_g_type_is_interface(PyGTypeWrapper * self)330 _wrap_g_type_is_interface(PyGTypeWrapper *self)
331 {
332     return pygi_gboolean_to_py (G_TYPE_IS_INTERFACE (self->type));
333 }
334 
335 static PyObject*
_wrap_g_type_is_classed(PyGTypeWrapper * self)336 _wrap_g_type_is_classed(PyGTypeWrapper *self)
337 {
338     return pygi_gboolean_to_py (G_TYPE_IS_CLASSED (self->type));
339 }
340 
341 static PyObject*
_wrap_g_type_is_instantiatable(PyGTypeWrapper * self)342 _wrap_g_type_is_instantiatable(PyGTypeWrapper *self)
343 {
344     return pygi_gboolean_to_py (G_TYPE_IS_INSTANTIATABLE(self->type));
345 }
346 
347 static PyObject*
_wrap_g_type_is_derivable(PyGTypeWrapper * self)348 _wrap_g_type_is_derivable(PyGTypeWrapper *self)
349 {
350     return pygi_gboolean_to_py (G_TYPE_IS_DERIVABLE (self->type));
351 }
352 
353 static PyObject*
_wrap_g_type_is_deep_derivable(PyGTypeWrapper * self)354 _wrap_g_type_is_deep_derivable(PyGTypeWrapper *self)
355 {
356     return pygi_gboolean_to_py (G_TYPE_IS_DEEP_DERIVABLE (self->type));
357 }
358 
359 static PyObject*
_wrap_g_type_is_abstract(PyGTypeWrapper * self)360 _wrap_g_type_is_abstract(PyGTypeWrapper *self)
361 {
362     return pygi_gboolean_to_py (G_TYPE_IS_ABSTRACT (self->type));
363 }
364 
365 static PyObject*
_wrap_g_type_is_value_abstract(PyGTypeWrapper * self)366 _wrap_g_type_is_value_abstract(PyGTypeWrapper *self)
367 {
368     return pygi_gboolean_to_py (G_TYPE_IS_VALUE_ABSTRACT (self->type));
369 }
370 
371 static PyObject*
_wrap_g_type_is_value_type(PyGTypeWrapper * self)372 _wrap_g_type_is_value_type(PyGTypeWrapper *self)
373 {
374     return pygi_gboolean_to_py (G_TYPE_IS_VALUE_TYPE (self->type));
375 }
376 
377 static PyObject*
_wrap_g_type_has_value_table(PyGTypeWrapper * self)378 _wrap_g_type_has_value_table(PyGTypeWrapper *self)
379 {
380     return pygi_gboolean_to_py (G_TYPE_HAS_VALUE_TABLE (self->type));
381 }
382 
383 static PyObject*
_wrap_g_type_from_name(PyGTypeWrapper * _,PyObject * args)384 _wrap_g_type_from_name(PyGTypeWrapper *_, PyObject *args)
385 {
386     char *type_name;
387     GType type;
388 
389     if (!PyArg_ParseTuple(args, "s:GType.from_name", &type_name))
390 	return NULL;
391 
392     type = g_type_from_name(type_name);
393     if (type == 0) {
394 	PyErr_SetString(PyExc_RuntimeError, "unknown type name");
395 	return NULL;
396     }
397 
398     return pyg_type_wrapper_new(type);
399 }
400 
401 static PyObject*
_wrap_g_type_is_a(PyGTypeWrapper * self,PyObject * args)402 _wrap_g_type_is_a(PyGTypeWrapper *self, PyObject *args)
403 {
404     PyObject *gparent;
405     GType parent;
406 
407     if (!PyArg_ParseTuple(args, "O:GType.is_a", &gparent))
408 	return NULL;
409     else if ((parent = pyg_type_from_object(gparent)) == 0)
410 	return NULL;
411 
412     return pygi_gboolean_to_py (g_type_is_a (self->type, parent));
413 }
414 
415 static PyMethodDef _PyGTypeWrapper_methods[] = {
416     { "is_interface", (PyCFunction)_wrap_g_type_is_interface, METH_NOARGS },
417     { "is_classed", (PyCFunction)_wrap_g_type_is_classed, METH_NOARGS },
418     { "is_instantiatable", (PyCFunction)_wrap_g_type_is_instantiatable, METH_NOARGS },
419     { "is_derivable", (PyCFunction)_wrap_g_type_is_derivable, METH_NOARGS },
420     { "is_deep_derivable", (PyCFunction)_wrap_g_type_is_deep_derivable, METH_NOARGS },
421     { "is_abstract", (PyCFunction)_wrap_g_type_is_abstract, METH_NOARGS },
422     { "is_value_abstract", (PyCFunction)_wrap_g_type_is_value_abstract, METH_NOARGS },
423     { "is_value_type", (PyCFunction)_wrap_g_type_is_value_type, METH_NOARGS },
424     { "has_value_table", (PyCFunction)_wrap_g_type_has_value_table, METH_NOARGS },
425     { "from_name", (PyCFunction)_wrap_g_type_from_name, METH_VARARGS | METH_STATIC },
426     { "is_a", (PyCFunction)_wrap_g_type_is_a, METH_VARARGS },
427     { NULL,  0, 0 }
428 };
429 
430 static int
pyg_type_wrapper_init(PyGTypeWrapper * self,PyObject * args,PyObject * kwargs)431 pyg_type_wrapper_init(PyGTypeWrapper *self, PyObject *args, PyObject *kwargs)
432 {
433     static char *kwlist[] = { "object", NULL };
434     PyObject *py_object;
435     GType type;
436 
437     if (!PyArg_ParseTupleAndKeywords(args, kwargs,
438 				     "O:GType.__init__",
439 				     kwlist, &py_object))
440         return -1;
441 
442     if (!(type = pyg_type_from_object(py_object)))
443 	return -1;
444 
445     self->type = type;
446 
447     return 0;
448 }
449 
450 /**
451  * pyg_type_wrapper_new:
452  * type: a GType
453  *
454  * Creates a Python wrapper for a GType.
455  *
456  * Returns: the Python wrapper.
457  */
458 PyObject *
pyg_type_wrapper_new(GType type)459 pyg_type_wrapper_new(GType type)
460 {
461     PyGTypeWrapper *self;
462 
463     g_assert (Py_TYPE (&PyGTypeWrapper_Type) != NULL);
464     self = (PyGTypeWrapper *)PyObject_NEW(PyGTypeWrapper,
465 					  &PyGTypeWrapper_Type);
466     if (self == NULL)
467 	return NULL;
468 
469     self->type = type;
470     return (PyObject *)self;
471 }
472 
473 /**
474  * pyg_type_from_object_strict:
475  * obj: a Python object
476  * strict: if set to TRUE, raises an exception if it can't perform the
477  *         conversion
478  *
479  * converts a python object to a GType.  If strict is set, raises an
480  * exception if it can't perform the conversion, otherwise returns
481  * PY_TYPE_OBJECT.
482  *
483  * Returns: the corresponding GType, or 0 on error.
484  */
485 
486 GType
pyg_type_from_object_strict(PyObject * obj,gboolean strict)487 pyg_type_from_object_strict(PyObject *obj, gboolean strict)
488 {
489     PyObject *gtype;
490     GType type;
491 
492     /* NULL check */
493     if (!obj) {
494 	PyErr_SetString(PyExc_TypeError, "can't get type from NULL object");
495 	return 0;
496     }
497 
498     /* map some standard types to primitive GTypes ... */
499     if (obj == Py_None)
500 	return G_TYPE_NONE;
501     if (PyType_Check(obj)) {
502 	PyTypeObject *tp = (PyTypeObject *)obj;
503 
504 	if (tp == &PyLong_Type)
505 	    return G_TYPE_INT;
506 	else if (tp == &PyBool_Type)
507 	    return G_TYPE_BOOLEAN;
508 	else if (tp == &PyFloat_Type)
509 	    return G_TYPE_DOUBLE;
510 	else if (tp == &PyUnicode_Type)
511 	    return G_TYPE_STRING;
512 	else if (tp == &PyBaseObject_Type)
513 	    return PY_TYPE_OBJECT;
514     }
515 
516     if (Py_TYPE(obj) == &PyGTypeWrapper_Type) {
517 	return ((PyGTypeWrapper *)obj)->type;
518     }
519 
520     /* handle strings */
521     if (PyUnicode_Check (obj)) {
522 	gchar *name = PyUnicode_AsUTF8(obj);
523 
524 	type = g_type_from_name(name);
525 	if (type != 0) {
526 	    return type;
527 	}
528     }
529 
530     /* finally, look for a __gtype__ attribute on the object */
531     gtype = PyObject_GetAttrString(obj, "__gtype__");
532 
533     if (gtype) {
534 	if (Py_TYPE(gtype) == &PyGTypeWrapper_Type) {
535 	    type = ((PyGTypeWrapper *)gtype)->type;
536 	    Py_DECREF(gtype);
537 	    return type;
538 	}
539 	Py_DECREF(gtype);
540     }
541 
542     PyErr_Clear();
543 
544     /* Some API like those that take GValues can hold a python object as
545      * a pointer.  This is potentially dangerous becuase everything is
546      * passed in as a PyObject so we can't actually type check it.  Only
547      * fallback to PY_TYPE_OBJECT if strict checking is disabled
548      */
549     if (!strict)
550         return PY_TYPE_OBJECT;
551 
552     PyErr_SetString(PyExc_TypeError, "could not get typecode from object");
553     return 0;
554 }
555 
556 /**
557  * pyg_type_from_object:
558  * obj: a Python object
559  *
560  * converts a python object to a GType.  Raises an exception if it
561  * can't perform the conversion.
562  *
563  * Returns: the corresponding GType, or 0 on error.
564  */
565 GType
pyg_type_from_object(PyObject * obj)566 pyg_type_from_object(PyObject *obj)
567 {
568     /* Legacy call always defaults to strict type checking */
569     return pyg_type_from_object_strict(obj, TRUE);
570 }
571 
572 /**
573  * pyg_enum_get_value:
574  * @enum_type: the GType of the flag.
575  * @obj: a Python object representing the flag value
576  * @val: a pointer to the location to store the integer representation of the flag.
577  *
578  * Converts a Python object to the integer equivalent.  The conversion
579  * will depend on the type of the Python object.  If the object is an
580  * integer, it is passed through directly.  If it is a string, it will
581  * be treated as a full or short enum name as defined in the GType.
582  *
583  * Returns: 0 on success or -1 on failure
584  */
585 gint
pyg_enum_get_value(GType enum_type,PyObject * obj,gint * val)586 pyg_enum_get_value(GType enum_type, PyObject *obj, gint *val)
587 {
588     GEnumClass *eclass = NULL;
589     gint res = -1;
590 
591     g_return_val_if_fail(val != NULL, -1);
592     if (!obj) {
593 	*val = 0;
594 	res = 0;
595     } else if (PyLong_Check (obj)) {
596 	if (!pygi_gint_from_py (obj, val))
597 	    res = -1;
598 	else
599 	    res = 0;
600 
601 	if (PyObject_TypeCheck(obj, &PyGEnum_Type) && ((PyGEnum *) obj)->gtype != enum_type) {
602 	    g_warning("expected enumeration type %s, but got %s instead",
603 		      g_type_name(enum_type),
604 		      g_type_name(((PyGEnum *) obj)->gtype));
605 	}
606     /* Dumb code duplication, but probably not worth it to have yet another macro. */
607     } else if (PyLong_Check(obj)) {
608 	if (!pygi_gint_from_py (obj, val))
609 	    res = -1;
610 	else
611 	    res = 0;
612 
613 	if (PyObject_TypeCheck(obj, &PyGEnum_Type) && ((PyGEnum *) obj)->gtype != enum_type) {
614 	    g_warning("expected enumeration type %s, but got %s instead",
615 		      g_type_name(enum_type),
616 		      g_type_name(((PyGEnum *) obj)->gtype));
617 	}
618     } else if (PyUnicode_Check (obj)) {
619 	GEnumValue *info;
620 	char *str = PyUnicode_AsUTF8 (obj);
621 
622 	if (enum_type != G_TYPE_NONE)
623 	    eclass = G_ENUM_CLASS(g_type_class_ref(enum_type));
624 	else {
625 	    PyErr_SetString(PyExc_TypeError, "could not convert string to enum because there is no GType associated to look up the value");
626 	    res = -1;
627 	}
628 	info = g_enum_get_value_by_name(eclass, str);
629 	g_type_class_unref(eclass);
630 
631 	if (!info)
632 	    info = g_enum_get_value_by_nick(eclass, str);
633 	if (info) {
634 	    *val = info->value;
635 	    res = 0;
636 	} else {
637 	    PyErr_SetString(PyExc_TypeError, "could not convert string");
638 	    res = -1;
639 	}
640     } else {
641 	PyErr_SetString(PyExc_TypeError,"enum values must be strings or ints");
642 	res = -1;
643     }
644     return res;
645 }
646 
647 /**
648  * pyg_flags_get_value:
649  * @flag_type: the GType of the flag.
650  * @obj: a Python object representing the flag value
651  * @val: a pointer to the location to store the integer representation of the flag.
652  *
653  * Converts a Python object to the integer equivalent.  The conversion
654  * will depend on the type of the Python object.  If the object is an
655  * integer, it is passed through directly.  If it is a string, it will
656  * be treated as a full or short flag name as defined in the GType.
657  * If it is a tuple, then the items are treated as strings and ORed
658  * together.
659  *
660  * Returns: 0 on success or -1 on failure
661  */
662 gint
pyg_flags_get_value(GType flag_type,PyObject * obj,guint * val)663 pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val)
664 {
665     GFlagsClass *fclass = NULL;
666     gint res = -1;
667 
668     g_return_val_if_fail(val != NULL, -1);
669     if (!obj) {
670 	*val = 0;
671 	res = 0;
672     } else if (PyLong_Check (obj)) {
673 	if (pygi_guint_from_py (obj, val))
674 	    res = 0;
675     } else if (PyLong_Check(obj)) {
676 	if (pygi_guint_from_py (obj, val))
677 	    res = 0;
678     } else if (PyUnicode_Check (obj)) {
679 	GFlagsValue *info;
680 	char *str = PyUnicode_AsUTF8 (obj);
681 
682 	if (flag_type != G_TYPE_NONE)
683 	    fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
684 	else {
685 	    PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
686 	    res = -1;
687 	}
688 	info = g_flags_get_value_by_name(fclass, str);
689 	g_type_class_unref(fclass);
690 
691 	if (!info)
692 	    info = g_flags_get_value_by_nick(fclass, str);
693 	if (info) {
694 	    *val = info->value;
695 	    res = 0;
696 	} else {
697 	    PyErr_SetString(PyExc_TypeError, "could not convert string");
698 	    res = -1;
699 	}
700     } else if (PyTuple_Check(obj)) {
701 	Py_ssize_t i, len;
702 
703 	len = PyTuple_Size(obj);
704 	*val = 0;
705 	res = 0;
706 
707 	if (flag_type != G_TYPE_NONE)
708 	    fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type));
709 	else {
710 	    PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value");
711 	    res = -1;
712 	}
713 
714 	for (i = 0; i < len; i++) {
715 	    PyObject *item = PyTuple_GetItem(obj, i);
716 	    char *str = PyUnicode_AsUTF8 (item);
717 	    GFlagsValue *info = g_flags_get_value_by_name(fclass, str);
718 
719 	    if (!info)
720 		info = g_flags_get_value_by_nick(fclass, str);
721 	    if (info) {
722 		*val |= info->value;
723 	    } else {
724 		PyErr_SetString(PyExc_TypeError, "could not convert string");
725 		res = -1;
726 		break;
727 	    }
728 	}
729 	g_type_class_unref(fclass);
730     } else {
731 	PyErr_SetString(PyExc_TypeError,
732 			"flag values must be strings, ints, longs, or tuples");
733 	res = -1;
734     }
735     return res;
736 }
737 
738 static GQuark pyg_type_marshal_key = 0;
739 static GQuark pyg_type_marshal_helper_key = 0;
740 
741 typedef enum _marshal_helper_data_e marshal_helper_data_e;
742 enum _marshal_helper_data_e {
743     MARSHAL_HELPER_NONE = 0,
744     MARSHAL_HELPER_RETURN_NULL,
745     MARSHAL_HELPER_IMPORT_DONE,
746 };
747 
748 PyGTypeMarshal *
pyg_type_lookup(GType type)749 pyg_type_lookup(GType type)
750 {
751     GType	ptype = type;
752     PyGTypeMarshal	*tm = NULL;
753     marshal_helper_data_e marshal_helper;
754 
755     if (type == G_TYPE_INVALID)
756 	return NULL;
757 
758     marshal_helper = GPOINTER_TO_INT (
759 	g_type_get_qdata(type, pyg_type_marshal_helper_key));
760 
761     /* If we called this function before with @type and nothing was found,
762      * return NULL early to not spend time in the loop below */
763     if (marshal_helper == MARSHAL_HELPER_RETURN_NULL)
764 	return NULL;
765 
766     /* Otherwise do recursive type lookup */
767     do {
768 	if (marshal_helper == MARSHAL_HELPER_IMPORT_DONE)
769 	    pygi_type_import_by_g_type (ptype);
770 
771 	if ((tm = g_type_get_qdata(ptype, pyg_type_marshal_key)) != NULL)
772 	    break;
773 	ptype = g_type_parent(ptype);
774     } while (ptype);
775 
776     if (marshal_helper == MARSHAL_HELPER_NONE) {
777 	marshal_helper = (tm == NULL) ?
778 	    MARSHAL_HELPER_RETURN_NULL:
779 	    MARSHAL_HELPER_IMPORT_DONE;
780 	g_type_set_qdata(type, pyg_type_marshal_helper_key,
781 	    GINT_TO_POINTER(marshal_helper));
782     }
783     return tm;
784 }
785 
786 /**
787  * pyg_register_gtype_custom:
788  * @gtype: the GType for the new type
789  * @from_func: a function to convert GValues to Python objects
790  * @to_func: a function to convert Python objects to GValues
791  *
792  * In order to handle specific conversion of gboxed types or new
793  * fundamental types, you may use this function to register conversion
794  * handlers.
795  */
796 
797 void
pyg_register_gtype_custom(GType gtype,fromvaluefunc from_func,tovaluefunc to_func)798 pyg_register_gtype_custom(GType gtype,
799 			  fromvaluefunc from_func,
800                           tovaluefunc to_func)
801 {
802     PyGTypeMarshal *tm;
803 
804     if (!pyg_type_marshal_key) {
805 	pyg_type_marshal_key = g_quark_from_static_string("PyGType::marshal");
806 	pyg_type_marshal_helper_key = g_quark_from_static_string("PyGType::marshal-helper");
807     }
808 
809     tm = g_new(PyGTypeMarshal, 1);
810     tm->fromvalue = from_func;
811     tm->tovalue = to_func;
812     g_type_set_qdata(gtype, pyg_type_marshal_key, tm);
813 }
814 
815 /* -------------- PyGClosure ----------------- */
816 
817 static void
pyg_closure_invalidate(gpointer data,GClosure * closure)818 pyg_closure_invalidate(gpointer data, GClosure *closure)
819 {
820     PyGClosure *pc = (PyGClosure *)closure;
821     PyGILState_STATE state;
822 
823     state = PyGILState_Ensure();
824     Py_XDECREF(pc->callback);
825     Py_XDECREF(pc->extra_args);
826     Py_XDECREF(pc->swap_data);
827     PyGILState_Release(state);
828 
829     pc->callback = NULL;
830     pc->extra_args = NULL;
831     pc->swap_data = NULL;
832 }
833 
834 static void
pyg_closure_marshal(GClosure * closure,GValue * return_value,guint n_param_values,const GValue * param_values,gpointer invocation_hint,gpointer marshal_data)835 pyg_closure_marshal(GClosure *closure,
836 		    GValue *return_value,
837 		    guint n_param_values,
838 		    const GValue *param_values,
839 		    gpointer invocation_hint,
840 		    gpointer marshal_data)
841 {
842     PyGILState_STATE state;
843     PyGClosure *pc = (PyGClosure *)closure;
844     PyObject *params, *ret;
845     guint i;
846 
847     state = PyGILState_Ensure();
848 
849     /* construct Python tuple for the parameter values */
850     params = PyTuple_New(n_param_values);
851     for (i = 0; i < n_param_values; i++) {
852 	/* swap in a different initial data for connect_object() */
853 	if (i == 0 && G_CCLOSURE_SWAP_DATA(closure)) {
854 	    g_return_if_fail(pc->swap_data != NULL);
855 	    Py_INCREF(pc->swap_data);
856 	    PyTuple_SetItem(params, 0, pc->swap_data);
857 	} else {
858 	    PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
859 
860 	    /* error condition */
861 	    if (!item) {
862             if (!PyErr_Occurred ())
863                 PyErr_SetString (PyExc_TypeError,
864                                  "can't convert parameter to desired type");
865 
866             if (pc->exception_handler)
867                 pc->exception_handler (return_value, n_param_values, param_values);
868             else
869                 PyErr_Print();
870 
871             goto out;
872 	    }
873 	    PyTuple_SetItem(params, i, item);
874 	}
875     }
876     /* params passed to function may have extra arguments */
877     if (pc->extra_args) {
878 	PyObject *tuple = params;
879 	params = PySequence_Concat(tuple, pc->extra_args);
880 	Py_DECREF(tuple);
881     }
882     ret = PyObject_CallObject(pc->callback, params);
883     if (ret == NULL) {
884 	if (pc->exception_handler)
885 	    pc->exception_handler(return_value, n_param_values, param_values);
886 	else
887 	    PyErr_Print();
888 	goto out;
889     }
890 
891     if (G_IS_VALUE(return_value) && pyg_value_from_pyobject(return_value, ret) != 0) {
892 	/* If we already have an exception set, use that, otherwise set a
893 	 * generic one */
894 	if (!PyErr_Occurred())
895 	    PyErr_SetString(PyExc_TypeError,
896                             "can't convert return value to desired type");
897 
898 	if (pc->exception_handler)
899 	    pc->exception_handler(return_value, n_param_values, param_values);
900 	else
901 	    PyErr_Print();
902     }
903     Py_DECREF(ret);
904 
905  out:
906     Py_DECREF(params);
907     PyGILState_Release(state);
908 }
909 
910 /**
911  * pyg_closure_new:
912  * callback: a Python callable object
913  * extra_args: a tuple of extra arguments, or None/NULL.
914  * swap_data: an alternative python object to pass first.
915  *
916  * Creates a GClosure wrapping a Python callable and optionally a set
917  * of additional function arguments.  This is needed to attach python
918  * handlers to signals, for instance.
919  *
920  * Returns: the new closure.
921  */
922 GClosure *
pyg_closure_new(PyObject * callback,PyObject * extra_args,PyObject * swap_data)923 pyg_closure_new(PyObject *callback, PyObject *extra_args, PyObject *swap_data)
924 {
925     GClosure *closure;
926 
927     g_return_val_if_fail(callback != NULL, NULL);
928     closure = g_closure_new_simple(sizeof(PyGClosure), NULL);
929     g_closure_add_invalidate_notifier(closure, NULL, pyg_closure_invalidate);
930     g_closure_set_marshal(closure, pyg_closure_marshal);
931     Py_INCREF(callback);
932     ((PyGClosure *)closure)->callback = callback;
933     if (extra_args && extra_args != Py_None) {
934 	Py_INCREF(extra_args);
935 	if (!PyTuple_Check(extra_args)) {
936 	    PyObject *tmp = PyTuple_New(1);
937 	    PyTuple_SetItem(tmp, 0, extra_args);
938 	    extra_args = tmp;
939 	}
940 	((PyGClosure *)closure)->extra_args = extra_args;
941     }
942     if (swap_data) {
943 	Py_INCREF(swap_data);
944 	((PyGClosure *)closure)->swap_data = swap_data;
945 	closure->derivative_flag = TRUE;
946     }
947     return closure;
948 }
949 
950 /**
951  * pyg_closure_set_exception_handler:
952  * @closure: a closure created with pyg_closure_new()
953  * @handler: the handler to call when an exception occurs or NULL for none
954  *
955  * Sets the handler to call when an exception occurs during closure invocation.
956  * The handler is responsible for providing a proper return value to the
957  * closure invocation. If @handler is %NULL, the default handler will be used.
958  * The default handler prints the exception to stderr and doesn't touch the
959  * closure's return value.
960  */
961 void
pyg_closure_set_exception_handler(GClosure * closure,PyClosureExceptionHandler handler)962 pyg_closure_set_exception_handler(GClosure *closure,
963 				  PyClosureExceptionHandler handler)
964 {
965     PyGClosure *pygclosure;
966 
967     g_return_if_fail(closure != NULL);
968 
969     pygclosure = (PyGClosure *)closure;
970     pygclosure->exception_handler = handler;
971 }
972 /* -------------- PySignalClassClosure ----------------- */
973 /* a closure used for the `class closure' of a signal.  As this gets
974  * all the info from the first argument to the closure and the
975  * invocation hint, we can have a single closure that handles all
976  * class closure cases.  We call a method by the name of the signal
977  * with "do_" prepended.
978  *
979  *  We also remove the first argument from the * param list, as it is
980  *  the instance object, which is passed * implicitly to the method
981  *  object. */
982 
983 static void
pyg_signal_class_closure_marshal(GClosure * closure,GValue * return_value,guint n_param_values,const GValue * param_values,gpointer invocation_hint,gpointer marshal_data)984 pyg_signal_class_closure_marshal(GClosure *closure,
985 				 GValue *return_value,
986 				 guint n_param_values,
987 				 const GValue *param_values,
988 				 gpointer invocation_hint,
989 				 gpointer marshal_data)
990 {
991     PyGILState_STATE state;
992     GObject *object;
993     PyObject *object_wrapper;
994     GSignalInvocationHint *hint = (GSignalInvocationHint *)invocation_hint;
995     gchar *method_name, *tmp;
996     PyObject *method;
997     PyObject *params, *ret;
998     Py_ssize_t py_len;
999     guint i, len;
1000 
1001     state = PyGILState_Ensure();
1002 
1003     g_return_if_fail(invocation_hint != NULL);
1004     /* get the object passed as the first argument to the closure */
1005     object = g_value_get_object(&param_values[0]);
1006     g_return_if_fail(object != NULL && G_IS_OBJECT(object));
1007 
1008     /* get the wrapper for this object */
1009     object_wrapper = pygobject_new(object);
1010     g_return_if_fail(object_wrapper != NULL);
1011 
1012     /* construct method name for this class closure */
1013     method_name = g_strconcat("do_", g_signal_name(hint->signal_id), NULL);
1014 
1015     /* convert dashes to underscores.  For some reason, g_signal_name
1016      * seems to convert all the underscores in the signal name to
1017        dashes??? */
1018     for (tmp = method_name; *tmp != '\0'; tmp++)
1019 	if (*tmp == '-') *tmp = '_';
1020 
1021     method = PyObject_GetAttrString(object_wrapper, method_name);
1022     g_free(method_name);
1023 
1024     if (!method) {
1025 	PyErr_Clear();
1026 	Py_DECREF(object_wrapper);
1027 	PyGILState_Release(state);
1028 	return;
1029     }
1030     Py_DECREF(object_wrapper);
1031 
1032     /* construct Python tuple for the parameter values; don't copy boxed values
1033        initially because we'll check after the call to see if a copy is needed. */
1034     params = PyTuple_New(n_param_values - 1);
1035     for (i = 1; i < n_param_values; i++) {
1036 	PyObject *item = pyg_value_as_pyobject(&param_values[i], FALSE);
1037 
1038 	/* error condition */
1039 	if (!item) {
1040 	    Py_DECREF(params);
1041 	    PyGILState_Release(state);
1042 	    return;
1043 	}
1044 	PyTuple_SetItem(params, i - 1, item);
1045     }
1046 
1047     ret = PyObject_CallObject(method, params);
1048 
1049     /* Copy boxed values if others ref them, this needs to be done regardless of
1050        exception status. */
1051     py_len = PyTuple_Size(params);
1052     len = (guint)py_len;
1053     for (i = 0; i < len; i++) {
1054 	PyObject *item = PyTuple_GetItem(params, i);
1055 	if (item != NULL && PyObject_TypeCheck(item, &PyGBoxed_Type)
1056 	    && Py_REFCNT (item) != 1) {
1057 	    PyGBoxed* boxed_item = (PyGBoxed*)item;
1058 	    if (!boxed_item->free_on_dealloc) {
1059 		gpointer boxed_ptr = pyg_boxed_get_ptr (boxed_item);
1060 		pyg_boxed_set_ptr (boxed_item, g_boxed_copy (boxed_item->gtype, boxed_ptr));
1061 		boxed_item->free_on_dealloc = TRUE;
1062 	    }
1063 	}
1064     }
1065 
1066     if (ret == NULL) {
1067 	PyErr_Print();
1068 	Py_DECREF(method);
1069 	Py_DECREF(params);
1070 	PyGILState_Release(state);
1071 	return;
1072     }
1073     Py_DECREF(method);
1074     Py_DECREF(params);
1075     if (G_IS_VALUE(return_value))
1076 	pyg_value_from_pyobject(return_value, ret);
1077     Py_DECREF(ret);
1078     PyGILState_Release(state);
1079 }
1080 
1081 /**
1082  * pyg_signal_class_closure_get:
1083  *
1084  * Returns the GClosure used for the class closure of signals.  When
1085  * called, it will invoke the method do_signalname (for the signal
1086  * "signalname").
1087  *
1088  * Returns: the closure.
1089  */
1090 GClosure *
pyg_signal_class_closure_get(void)1091 pyg_signal_class_closure_get(void)
1092 {
1093     static GClosure *closure;
1094 
1095     if (closure == NULL) {
1096 	closure = g_closure_new_simple(sizeof(GClosure), NULL);
1097 	g_closure_set_marshal(closure, pyg_signal_class_closure_marshal);
1098 
1099 	g_closure_ref(closure);
1100 	g_closure_sink(closure);
1101     }
1102     return closure;
1103 }
1104 
1105 /* ----- __doc__ descriptor for GObject and GInterface ----- */
1106 
1107 static void
object_doc_dealloc(PyObject * self)1108 object_doc_dealloc(PyObject *self)
1109 {
1110     PyObject_FREE(self);
1111 }
1112 
1113 /* append information about signals of a particular gtype */
1114 static void
add_signal_docs(GType gtype,GString * string)1115 add_signal_docs(GType gtype, GString *string)
1116 {
1117     GTypeClass *class = NULL;
1118     guint *signal_ids, n_ids = 0, i;
1119 
1120     if (G_TYPE_IS_CLASSED(gtype))
1121 	class = g_type_class_ref(gtype);
1122     signal_ids = g_signal_list_ids(gtype, &n_ids);
1123 
1124     if (n_ids > 0) {
1125 	g_string_append_printf(string, "Signals from %s:\n",
1126 			       g_type_name(gtype));
1127 
1128 	for (i = 0; i < n_ids; i++) {
1129 	    GSignalQuery query;
1130 	    guint j;
1131 
1132 	    g_signal_query(signal_ids[i], &query);
1133 
1134 	    g_string_append(string, "  ");
1135 	    g_string_append(string, query.signal_name);
1136 	    g_string_append(string, " (");
1137 	    for (j = 0; j < query.n_params; j++) {
1138 		g_string_append(string, g_type_name(query.param_types[j]));
1139 		if (j != query.n_params - 1)
1140 		    g_string_append(string, ", ");
1141 	    }
1142 	    g_string_append(string, ")");
1143 	    if (query.return_type && query.return_type != G_TYPE_NONE) {
1144 		g_string_append(string, " -> ");
1145 		g_string_append(string, g_type_name(query.return_type));
1146 	    }
1147 	    g_string_append(string, "\n");
1148 	}
1149 	g_free(signal_ids);
1150 	g_string_append(string, "\n");
1151     }
1152     if (class)
1153 	g_type_class_unref(class);
1154 }
1155 
1156 static void
add_property_docs(GType gtype,GString * string)1157 add_property_docs(GType gtype, GString *string)
1158 {
1159     GObjectClass *class;
1160     GParamSpec **props;
1161     guint n_props = 0, i;
1162     gboolean has_prop = FALSE;
1163     const gchar *blurb=NULL;
1164 
1165     class = g_type_class_ref(gtype);
1166     props = g_object_class_list_properties(class, &n_props);
1167 
1168     for (i = 0; i < n_props; i++) {
1169 	if (props[i]->owner_type != gtype)
1170 	    continue; /* these are from a parent type */
1171 
1172 	/* print out the heading first */
1173 	if (!has_prop) {
1174 	    g_string_append_printf(string, "Properties from %s:\n",
1175 				   g_type_name(gtype));
1176 	    has_prop = TRUE;
1177 	}
1178 	g_string_append_printf(string, "  %s -> %s: %s\n",
1179 			       g_param_spec_get_name(props[i]),
1180 			       g_type_name(props[i]->value_type),
1181 			       g_param_spec_get_nick(props[i]));
1182 
1183 	/* g_string_append_printf crashes on win32 if the third
1184 	   argument is NULL. */
1185 	blurb=g_param_spec_get_blurb(props[i]);
1186 	if (blurb)
1187 	    g_string_append_printf(string, "    %s\n",blurb);
1188     }
1189     g_free(props);
1190     if (has_prop)
1191 	g_string_append(string, "\n");
1192     g_type_class_unref(class);
1193 }
1194 
1195 static PyObject *
object_doc_descr_get(PyObject * self,PyObject * obj,PyObject * type)1196 object_doc_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1197 {
1198     GType gtype = 0;
1199     GString *string;
1200     PyObject *pystring;
1201 
1202     if (obj && pygobject_check(obj, &PyGObject_Type)) {
1203 	gtype = G_OBJECT_TYPE(pygobject_get(obj));
1204 	if (!gtype)
1205 	    PyErr_SetString(PyExc_RuntimeError, "could not get object type");
1206     } else {
1207 	gtype = pyg_type_from_object(type);
1208     }
1209     if (!gtype)
1210 	return NULL;
1211 
1212     string = g_string_new_len(NULL, 512);
1213 
1214     if (g_type_is_a(gtype, G_TYPE_INTERFACE))
1215 	g_string_append_printf(string, "Interface %s\n\n", g_type_name(gtype));
1216     else if (g_type_is_a(gtype, G_TYPE_OBJECT))
1217 	g_string_append_printf(string, "Object %s\n\n", g_type_name(gtype));
1218     else
1219 	g_string_append_printf(string, "%s\n\n", g_type_name(gtype));
1220 
1221     if (((PyTypeObject *) type)->tp_doc)
1222         g_string_append_printf(string, "%s\n\n", ((PyTypeObject *) type)->tp_doc);
1223 
1224     if (g_type_is_a(gtype, G_TYPE_OBJECT)) {
1225 	GType parent = G_TYPE_OBJECT;
1226         GArray *parents = g_array_new(FALSE, FALSE, sizeof(GType));
1227         int iparent;
1228 
1229         while (parent) {
1230             g_array_append_val(parents, parent);
1231             parent = g_type_next_base(gtype, parent);
1232         }
1233 
1234         for (iparent = parents->len - 1; iparent >= 0; --iparent) {
1235 	    GType *interfaces;
1236 	    guint n_interfaces, i;
1237 
1238             parent = g_array_index(parents, GType, iparent);
1239 	    add_signal_docs(parent, string);
1240 	    add_property_docs(parent, string);
1241 
1242 	    /* add docs for implemented interfaces */
1243 	    interfaces = g_type_interfaces(parent, &n_interfaces);
1244 	    for (i = 0; i < n_interfaces; i++)
1245 		add_signal_docs(interfaces[i], string);
1246 	    g_free(interfaces);
1247 	}
1248         g_array_free(parents, TRUE);
1249     }
1250 
1251     pystring = PyUnicode_FromStringAndSize (string->str, string->len);
1252     g_string_free(string, TRUE);
1253     return pystring;
1254 }
1255 
1256 PYGI_DEFINE_TYPE("gobject.GObject.__doc__", PyGObjectDoc_Type, PyObject);
1257 
1258 /**
1259  * pyg_object_descr_doc_get:
1260  *
1261  * Returns an object intended to be the __doc__ attribute of GObject
1262  * wrappers.  When read in the context of the object it will return
1263  * some documentation about the signals and properties of the object.
1264  *
1265  * Returns: the descriptor.
1266  */
1267 PyObject *
pyg_object_descr_doc_get(void)1268 pyg_object_descr_doc_get(void)
1269 {
1270     static PyObject *doc_descr = NULL;
1271 
1272     if (!doc_descr) {
1273 	Py_TYPE(&PyGObjectDoc_Type) = &PyType_Type;
1274 	if (PyType_Ready(&PyGObjectDoc_Type))
1275 	    return NULL;
1276 
1277 	doc_descr = PyObject_NEW(PyObject, &PyGObjectDoc_Type);
1278 	if (doc_descr == NULL)
1279 	    return NULL;
1280     }
1281     return doc_descr;
1282 }
1283 
1284 
1285 /**
1286  * pyg_pyobj_to_unichar_conv:
1287  *
1288  * Converts PyObject value to a unichar and write result to memory
1289  * pointed to by ptr.  Follows the calling convention of a ParseArgs
1290  * converter (O& format specifier) so it may be used to convert function
1291  * arguments.
1292  *
1293  * Returns: 1 if the conversion succeeds and 0 otherwise.  If the conversion
1294  *          did not succeesd, a Python exception is raised
1295  */
pyg_pyobj_to_unichar_conv(PyObject * py_obj,void * ptr)1296 int pyg_pyobj_to_unichar_conv(PyObject* py_obj, void* ptr)
1297 {
1298     if (!pygi_gunichar_from_py (py_obj, ptr))
1299         return 0;
1300     return 1;
1301 }
1302 
1303 gboolean
pyg_gtype_is_custom(GType gtype)1304 pyg_gtype_is_custom(GType gtype)
1305 {
1306     return g_type_get_qdata (gtype, pygobject_custom_key) != NULL;
1307 }
1308 
1309 static PyObject *
strv_from_gvalue(const GValue * value)1310 strv_from_gvalue(const GValue *value)
1311 {
1312     gchar **argv;
1313     PyObject  *py_argv;
1314     gsize i;
1315 
1316     argv = (gchar **) g_value_get_boxed (value);
1317     py_argv = PyList_New (0);
1318 
1319     for (i = 0; argv && argv[i]; i++) {
1320         int res;
1321         PyObject *item = pygi_utf8_to_py (argv[i]);
1322         if (item == NULL) {
1323             Py_DECREF (py_argv);
1324             return NULL;
1325         }
1326         res = PyList_Append (py_argv, item);
1327         Py_DECREF (item);
1328         if (res == -1) {
1329             Py_DECREF (py_argv);
1330             return NULL;
1331         }
1332     }
1333 
1334     return py_argv;
1335 }
1336 
1337 static int
strv_to_gvalue(GValue * value,PyObject * obj)1338 strv_to_gvalue(GValue *value, PyObject *obj)
1339 {
1340     Py_ssize_t argc, i;
1341     gchar **argv;
1342 
1343     if (!(PyTuple_Check (obj) || PyList_Check (obj)))
1344         return -1;
1345 
1346     argc = PySequence_Length (obj);
1347     argv = g_new (gchar *, argc + 1);
1348     for (i = 0; i < argc; ++i) {
1349         PyObject* item = PySequence_Fast_GET_ITEM (obj, i);
1350         if (!pygi_utf8_from_py (item, &(argv[i])))
1351             goto error;
1352     }
1353 
1354     argv[i] = NULL;
1355     g_value_take_boxed (value, argv);
1356     return 0;
1357 
1358 error:
1359     for (i = i - 1; i >= 0; i--) {
1360         g_free (argv[i]);
1361     }
1362     g_free (argv);
1363     return -1;
1364 }
1365 
1366 /**
1367  * Returns 0 on success, or -1 and sets an exception.
1368  */
1369 int
pygi_type_register_types(PyObject * d)1370 pygi_type_register_types(PyObject *d)
1371 {
1372     PyGTypeWrapper_Type.tp_dealloc = (destructor)pyg_type_wrapper_dealloc;
1373     PyGTypeWrapper_Type.tp_richcompare = pyg_type_wrapper_richcompare;
1374     PyGTypeWrapper_Type.tp_repr = (reprfunc)pyg_type_wrapper_repr;
1375     PyGTypeWrapper_Type.tp_hash = (hashfunc)pyg_type_wrapper_hash;
1376     PyGTypeWrapper_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1377     PyGTypeWrapper_Type.tp_methods = _PyGTypeWrapper_methods;
1378     PyGTypeWrapper_Type.tp_getset = _PyGTypeWrapper_getsets;
1379     PyGTypeWrapper_Type.tp_init = (initproc)pyg_type_wrapper_init;
1380     PyGTypeWrapper_Type.tp_alloc = PyType_GenericAlloc;
1381     PyGTypeWrapper_Type.tp_new = PyType_GenericNew;
1382     if (PyType_Ready(&PyGTypeWrapper_Type))
1383         return -1;
1384 
1385     PyDict_SetItemString(d, "GType", (PyObject *)&PyGTypeWrapper_Type);
1386 
1387     /* This type lazily registered in pyg_object_descr_doc_get */
1388     PyGObjectDoc_Type.tp_dealloc = (destructor)object_doc_dealloc;
1389     PyGObjectDoc_Type.tp_flags = Py_TPFLAGS_DEFAULT;
1390     PyGObjectDoc_Type.tp_descr_get = (descrgetfunc)object_doc_descr_get;
1391 
1392     pyg_register_gtype_custom (G_TYPE_STRV,
1393                                strv_from_gvalue,
1394                                strv_to_gvalue);
1395 
1396     return 0;
1397 }
1398