1
2 /* -*- Mode: C; c-basic-offset: 4 -*-
3 * vim: tabstop=4 shiftwidth=4 expandtab
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 <Python.h>
20 #include "pygi-value.h"
21 #include "pygi-struct.h"
22 #include "pygi-basictype.h"
23 #include "pygobject-object.h"
24 #include "pygi-type.h"
25 #include "pygenum.h"
26 #include "pygpointer.h"
27 #include "pygboxed.h"
28 #include "pygflags.h"
29 #include "pygparamspec.h"
30
31
32 /* glib 2.62 has started to print warnings for these which can't be disabled selectively, so just copy them here */
33 #define PYGI_TYPE_VALUE_ARRAY (g_value_array_get_type())
34 #define PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), PYGI_TYPE_VALUE_ARRAY))
35 #define PYGI_PARAM_SPEC_VALUE_ARRAY(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), g_param_spec_types[18], GParamSpecValueArray))
36
37 GIArgument
_pygi_argument_from_g_value(const GValue * value,GITypeInfo * type_info)38 _pygi_argument_from_g_value(const GValue *value,
39 GITypeInfo *type_info)
40 {
41 GIArgument arg = { 0, };
42
43 GITypeTag type_tag = g_type_info_get_tag (type_info);
44
45 /* For the long handling: long can be equivalent to
46 int32 or int64, depending on the architecture, but
47 gi doesn't tell us (and same for ulong)
48 */
49 switch (type_tag) {
50 case GI_TYPE_TAG_BOOLEAN:
51 arg.v_boolean = g_value_get_boolean (value);
52 break;
53 case GI_TYPE_TAG_INT8:
54 arg.v_int8 = g_value_get_schar (value);
55 break;
56 case GI_TYPE_TAG_INT16:
57 case GI_TYPE_TAG_INT32:
58 if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
59 arg.v_int32 = (gint32)g_value_get_long (value);
60 else
61 arg.v_int32 = (gint32)g_value_get_int (value);
62 break;
63 case GI_TYPE_TAG_INT64:
64 if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_LONG))
65 arg.v_int64 = g_value_get_long (value);
66 else
67 arg.v_int64 = g_value_get_int64 (value);
68 break;
69 case GI_TYPE_TAG_UINT8:
70 arg.v_uint8 = g_value_get_uchar (value);
71 break;
72 case GI_TYPE_TAG_UINT16:
73 case GI_TYPE_TAG_UINT32:
74 if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
75 arg.v_uint32 = (guint32)g_value_get_ulong (value);
76 else
77 arg.v_uint32 = (guint32)g_value_get_uint (value);
78 break;
79 case GI_TYPE_TAG_UINT64:
80 if (g_type_is_a (G_VALUE_TYPE (value), G_TYPE_ULONG))
81 arg.v_uint64 = g_value_get_ulong (value);
82 else
83 arg.v_uint64 = g_value_get_uint64 (value);
84 break;
85 case GI_TYPE_TAG_UNICHAR:
86 arg.v_uint32 = g_value_get_schar (value);
87 break;
88 case GI_TYPE_TAG_FLOAT:
89 arg.v_float = g_value_get_float (value);
90 break;
91 case GI_TYPE_TAG_DOUBLE:
92 arg.v_double = g_value_get_double (value);
93 break;
94 case GI_TYPE_TAG_GTYPE:
95 arg.v_size = g_value_get_gtype (value);
96 break;
97 case GI_TYPE_TAG_UTF8:
98 case GI_TYPE_TAG_FILENAME:
99 /* Callers are responsible for ensuring the GValue stays alive
100 * long enough for the string to be copied. */
101 arg.v_string = (char *)g_value_get_string (value);
102 break;
103 case GI_TYPE_TAG_GLIST:
104 case GI_TYPE_TAG_GSLIST:
105 case GI_TYPE_TAG_ARRAY:
106 case GI_TYPE_TAG_GHASH:
107 if (G_VALUE_HOLDS_BOXED (value))
108 arg.v_pointer = g_value_get_boxed (value);
109 else
110 /* e. g. GSettings::change-event */
111 arg.v_pointer = g_value_get_pointer (value);
112 break;
113 case GI_TYPE_TAG_INTERFACE:
114 {
115 GIBaseInfo *info;
116 GIInfoType info_type;
117
118 info = g_type_info_get_interface (type_info);
119 info_type = g_base_info_get_type (info);
120
121 g_base_info_unref (info);
122
123 switch (info_type) {
124 case GI_INFO_TYPE_FLAGS:
125 arg.v_uint = g_value_get_flags (value);
126 break;
127 case GI_INFO_TYPE_ENUM:
128 arg.v_int = g_value_get_enum (value);
129 break;
130 case GI_INFO_TYPE_INTERFACE:
131 case GI_INFO_TYPE_OBJECT:
132 if (G_VALUE_HOLDS_PARAM (value))
133 arg.v_pointer = g_value_get_param (value);
134 else
135 arg.v_pointer = g_value_get_object (value);
136 break;
137 case GI_INFO_TYPE_BOXED:
138 case GI_INFO_TYPE_STRUCT:
139 case GI_INFO_TYPE_UNION:
140 if (G_VALUE_HOLDS (value, G_TYPE_BOXED)) {
141 arg.v_pointer = g_value_get_boxed (value);
142 } else if (G_VALUE_HOLDS (value, G_TYPE_VARIANT)) {
143 arg.v_pointer = g_value_get_variant (value);
144 } else if (G_VALUE_HOLDS (value, G_TYPE_POINTER)) {
145 arg.v_pointer = g_value_get_pointer (value);
146 } else {
147 PyErr_Format (PyExc_NotImplementedError,
148 "Converting GValue's of type '%s' is not implemented.",
149 g_type_name (G_VALUE_TYPE (value)));
150 }
151 break;
152 default:
153 PyErr_Format (PyExc_NotImplementedError,
154 "Converting GValue's of type '%s' is not implemented.",
155 g_info_type_to_string (info_type));
156 break;
157 }
158 break;
159 }
160 case GI_TYPE_TAG_ERROR:
161 arg.v_pointer = g_value_get_boxed (value);
162 break;
163 case GI_TYPE_TAG_VOID:
164 arg.v_pointer = g_value_get_pointer (value);
165 break;
166 default:
167 break;
168 }
169
170 return arg;
171 }
172
173
174 /* Ignore g_value_array deprecations. Although they are deprecated,
175 * we still need to support the marshaling of them in PyGObject.
176 */
177 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
178
179 static int
pyg_value_array_from_pyobject(GValue * value,PyObject * obj,const GParamSpecValueArray * pspec)180 pyg_value_array_from_pyobject(GValue *value,
181 PyObject *obj,
182 const GParamSpecValueArray *pspec)
183 {
184 Py_ssize_t seq_len;
185 GValueArray *value_array;
186 guint len, i;
187
188 seq_len = PySequence_Length(obj);
189 if (seq_len == -1) {
190 PyErr_Clear();
191 return -1;
192 }
193 len = (guint)seq_len;
194
195 if (pspec && pspec->fixed_n_elements > 0 && len != pspec->fixed_n_elements)
196 return -1;
197
198 value_array = g_value_array_new(len);
199
200 for (i = 0; i < len; ++i) {
201 PyObject *item = PySequence_GetItem(obj, i);
202 GType type;
203
204 if (! item) {
205 PyErr_Clear();
206 g_value_array_free(value_array);
207 return -1;
208 }
209
210 if (pspec && pspec->element_spec)
211 type = G_PARAM_SPEC_VALUE_TYPE(pspec->element_spec);
212 else if (item == Py_None)
213 type = G_TYPE_POINTER; /* store None as NULL */
214 else {
215 type = pyg_type_from_object((PyObject*)Py_TYPE(item));
216 if (! type) {
217 PyErr_Clear();
218 g_value_array_free(value_array);
219 Py_DECREF(item);
220 return -1;
221 }
222 }
223
224 if (type == G_TYPE_VALUE) {
225 const GValue * item_value = pyg_boxed_get(item, GValue);
226 g_value_array_append(value_array, item_value);
227 } else {
228 GValue item_value = { 0, };
229 int status;
230
231 g_value_init(&item_value, type);
232 status = (pspec && pspec->element_spec)
233 ? pyg_param_gvalue_from_pyobject(&item_value, item, pspec->element_spec)
234 : pyg_value_from_pyobject(&item_value, item);
235 Py_DECREF(item);
236
237 if (status == -1) {
238 g_value_array_free(value_array);
239 g_value_unset(&item_value);
240 return -1;
241 }
242 g_value_array_append(value_array, &item_value);
243 g_value_unset(&item_value);
244 }
245 }
246
247 g_value_take_boxed(value, value_array);
248 return 0;
249 }
250
251 G_GNUC_END_IGNORE_DEPRECATIONS
252
253 static int
pyg_array_from_pyobject(GValue * value,PyObject * obj)254 pyg_array_from_pyobject(GValue *value,
255 PyObject *obj)
256 {
257 Py_ssize_t len, i;
258 GArray *array;
259
260 len = PySequence_Length(obj);
261 if (len == -1) {
262 PyErr_Clear();
263 return -1;
264 }
265
266 array = g_array_new(FALSE, TRUE, sizeof(GValue));
267
268 for (i = 0; i < len; ++i) {
269 PyObject *item = PySequence_GetItem(obj, i);
270 GType type;
271 GValue item_value = { 0, };
272 int status;
273
274 if (! item) {
275 PyErr_Clear();
276 g_array_free(array, FALSE);
277 return -1;
278 }
279
280 if (item == Py_None)
281 type = G_TYPE_POINTER; /* store None as NULL */
282 else {
283 type = pyg_type_from_object((PyObject*)Py_TYPE(item));
284 if (! type) {
285 PyErr_Clear();
286 g_array_free(array, FALSE);
287 Py_DECREF(item);
288 return -1;
289 }
290 }
291
292 g_value_init(&item_value, type);
293 status = pyg_value_from_pyobject(&item_value, item);
294 Py_DECREF(item);
295
296 if (status == -1) {
297 g_array_free(array, FALSE);
298 g_value_unset(&item_value);
299 return -1;
300 }
301
302 g_array_append_val(array, item_value);
303 }
304
305 g_value_take_boxed(value, array);
306 return 0;
307 }
308
309 /**
310 * pyg_value_from_pyobject_with_error:
311 * @value: the GValue object to store the converted value in.
312 * @obj: the Python object to convert.
313 *
314 * This function converts a Python object and stores the result in a
315 * GValue. The GValue must be initialised in advance with
316 * g_value_init(). If the Python object can't be converted to the
317 * type of the GValue, then an error is returned.
318 *
319 * Returns: 0 on success, -1 on error.
320 */
321 int
pyg_value_from_pyobject_with_error(GValue * value,PyObject * obj)322 pyg_value_from_pyobject_with_error(GValue *value, PyObject *obj)
323 {
324 GType value_type = G_VALUE_TYPE(value);
325
326 switch (G_TYPE_FUNDAMENTAL(value_type)) {
327 case G_TYPE_INTERFACE:
328 /* we only handle interface types that have a GObject prereq */
329 if (g_type_is_a(value_type, G_TYPE_OBJECT)) {
330 if (obj == Py_None)
331 g_value_set_object(value, NULL);
332 else {
333 if (!PyObject_TypeCheck(obj, &PyGObject_Type)) {
334 PyErr_SetString(PyExc_TypeError, "GObject is required");
335 return -1;
336 }
337 if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
338 value_type)) {
339 PyErr_SetString(PyExc_TypeError, "Invalid GObject type for assignment");
340 return -1;
341 }
342 g_value_set_object(value, pygobject_get(obj));
343 }
344 } else {
345 PyErr_SetString(PyExc_TypeError, "Unsupported conversion");
346 return -1;
347 }
348 break;
349 case G_TYPE_CHAR:
350 {
351 gint8 temp;
352 if (pygi_gschar_from_py (obj, &temp)) {
353 g_value_set_schar (value, temp);
354 return 0;
355 } else
356 return -1;
357 }
358 case G_TYPE_UCHAR:
359 {
360 guchar temp;
361 if (pygi_guchar_from_py (obj, &temp)) {
362 g_value_set_uchar (value, temp);
363 return 0;
364 } else
365 return -1;
366 }
367 case G_TYPE_BOOLEAN:
368 {
369 gboolean temp;
370 if (pygi_gboolean_from_py (obj, &temp)) {
371 g_value_set_boolean (value, temp);
372 return 0;
373 } else
374 return -1;
375 }
376 case G_TYPE_INT:
377 {
378 gint temp;
379 if (pygi_gint_from_py (obj, &temp)) {
380 g_value_set_int (value, temp);
381 return 0;
382 } else
383 return -1;
384 }
385 case G_TYPE_UINT:
386 {
387 guint temp;
388 if (pygi_guint_from_py (obj, &temp)) {
389 g_value_set_uint (value, temp);
390 return 0;
391 } else
392 return -1;
393 }
394 case G_TYPE_LONG:
395 {
396 glong temp;
397 if (pygi_glong_from_py (obj, &temp)) {
398 g_value_set_long (value, temp);
399 return 0;
400 } else
401 return -1;
402 }
403 case G_TYPE_ULONG:
404 {
405 gulong temp;
406 if (pygi_gulong_from_py (obj, &temp)) {
407 g_value_set_ulong (value, temp);
408 return 0;
409 } else
410 return -1;
411 }
412 case G_TYPE_INT64:
413 {
414 gint64 temp;
415 if (pygi_gint64_from_py (obj, &temp)) {
416 g_value_set_int64 (value, temp);
417 return 0;
418 } else
419 return -1;
420 }
421 case G_TYPE_UINT64:
422 {
423 guint64 temp;
424 if (pygi_guint64_from_py (obj, &temp)) {
425 g_value_set_uint64 (value, temp);
426 return 0;
427 } else
428 return -1;
429 }
430 case G_TYPE_ENUM:
431 {
432 gint val = 0;
433 if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
434 return -1;
435 }
436 g_value_set_enum(value, val);
437 }
438 break;
439 case G_TYPE_FLAGS:
440 {
441 guint val = 0;
442 if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
443 return -1;
444 }
445 g_value_set_flags(value, val);
446 return 0;
447 }
448 break;
449 case G_TYPE_FLOAT:
450 {
451 gfloat temp;
452 if (pygi_gfloat_from_py (obj, &temp)) {
453 g_value_set_float (value, temp);
454 return 0;
455 } else
456 return -1;
457 }
458 case G_TYPE_DOUBLE:
459 {
460 gdouble temp;
461 if (pygi_gdouble_from_py (obj, &temp)) {
462 g_value_set_double (value, temp);
463 return 0;
464 } else
465 return -1;
466 }
467 case G_TYPE_STRING:
468 {
469 gchar *temp;
470 if (pygi_utf8_from_py (obj, &temp)) {
471 g_value_take_string (value, temp);
472 return 0;
473 } else {
474 /* also allows setting anything implementing __str__ */
475 PyObject* str;
476 PyErr_Clear ();
477 str = PyObject_Str (obj);
478 if (str == NULL)
479 return -1;
480 if (pygi_utf8_from_py (str, &temp)) {
481 Py_DECREF (str);
482 g_value_take_string (value, temp);
483 return 0;
484 }
485 Py_DECREF (str);
486 return -1;
487 }
488 }
489 case G_TYPE_POINTER:
490 if (obj == Py_None)
491 g_value_set_pointer(value, NULL);
492 else if (PyObject_TypeCheck(obj, &PyGPointer_Type) &&
493 G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype))
494 g_value_set_pointer(value, pyg_pointer_get(obj, gpointer));
495 else if (PyCapsule_CheckExact (obj))
496 g_value_set_pointer(value, PyCapsule_GetPointer (obj, NULL));
497 else if (G_VALUE_HOLDS_GTYPE (value))
498 g_value_set_gtype (value, pyg_type_from_object (obj));
499 else {
500 PyErr_SetString(PyExc_TypeError, "Expected pointer");
501 return -1;
502 }
503 break;
504 case G_TYPE_BOXED: {
505 PyGTypeMarshal *bm;
506 gboolean holds_value_array;
507
508 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
509 holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
510 G_GNUC_END_IGNORE_DEPRECATIONS
511
512 if (obj == Py_None)
513 g_value_set_boxed(value, NULL);
514 else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT))
515 g_value_set_boxed(value, obj);
516 else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) &&
517 G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype))
518 g_value_set_boxed(value, pyg_boxed_get(obj, gpointer));
519 else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
520 GType type;
521 GValue *n_value;
522
523 type = pyg_type_from_object((PyObject*)Py_TYPE(obj));
524 if (G_UNLIKELY (! type)) {
525 return -1;
526 }
527 n_value = g_new0 (GValue, 1);
528 g_value_init (n_value, type);
529 g_value_take_boxed (value, n_value);
530 return pyg_value_from_pyobject_with_error (n_value, obj);
531 }
532 else if (PySequence_Check(obj) && holds_value_array)
533 return pyg_value_array_from_pyobject(value, obj, NULL);
534
535 else if (PySequence_Check(obj) &&
536 G_VALUE_HOLDS(value, G_TYPE_ARRAY))
537 return pyg_array_from_pyobject(value, obj);
538 else if (PyUnicode_Check (obj) &&
539 G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
540 GString *string;
541 char *buffer;
542 Py_ssize_t len;
543 buffer = PyUnicode_AsUTF8AndSize (obj, &len);
544 if (buffer == NULL)
545 return -1;
546 string = g_string_new_len(buffer, len);
547 g_value_set_boxed(value, string);
548 g_string_free (string, TRUE);
549 break;
550 }
551 else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL)
552 return bm->tovalue(value, obj);
553 else if (PyCapsule_CheckExact (obj))
554 g_value_set_boxed(value, PyCapsule_GetPointer (obj, NULL));
555 else {
556 PyErr_SetString(PyExc_TypeError, "Expected Boxed");
557 return -1;
558 }
559 break;
560 }
561 case G_TYPE_PARAM:
562 /* we need to support both the wrapped _gi.GParamSpec and the GI
563 * GObject.ParamSpec */
564 if (G_IS_PARAM_SPEC (pygobject_get (obj)))
565 g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
566 else if (pyg_param_spec_check (obj))
567 g_value_set_param(value, PyCapsule_GetPointer (obj, NULL));
568 else {
569 PyErr_SetString(PyExc_TypeError, "Expected ParamSpec");
570 return -1;
571 }
572 break;
573 case G_TYPE_OBJECT:
574 if (obj == Py_None) {
575 g_value_set_object(value, NULL);
576 } else if (PyObject_TypeCheck(obj, &PyGObject_Type) &&
577 G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj),
578 G_VALUE_TYPE(value))) {
579 g_value_set_object(value, pygobject_get(obj));
580 } else {
581 PyErr_SetString(PyExc_TypeError, "Expected GObject");
582 return -1;
583 }
584 break;
585 case G_TYPE_VARIANT:
586 {
587 if (obj == Py_None)
588 g_value_set_variant(value, NULL);
589 else if (pyg_type_from_object_strict(obj, FALSE) == G_TYPE_VARIANT)
590 g_value_set_variant(value, pyg_boxed_get(obj, GVariant));
591 else {
592 PyErr_SetString(PyExc_TypeError, "Expected Variant");
593 return -1;
594 }
595 break;
596 }
597 default:
598 {
599 PyGTypeMarshal *bm;
600 if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) {
601 return bm->tovalue(value, obj);
602 } else {
603 PyErr_SetString(PyExc_TypeError, "Unknown value type");
604 return -1;
605 }
606 break;
607 }
608 }
609
610 /* If an error occurred, unset the GValue but don't clear the Python error. */
611 if (PyErr_Occurred()) {
612 g_value_unset(value);
613 return -1;
614 }
615
616 return 0;
617 }
618
619 /**
620 * pyg_value_from_pyobject:
621 * @value: the GValue object to store the converted value in.
622 * @obj: the Python object to convert.
623 *
624 * Same basic function as pyg_value_from_pyobject_with_error but clears
625 * any Python errors before returning.
626 *
627 * Returns: 0 on success, -1 on error.
628 */
629 int
pyg_value_from_pyobject(GValue * value,PyObject * obj)630 pyg_value_from_pyobject(GValue *value, PyObject *obj)
631 {
632 int res = pyg_value_from_pyobject_with_error (value, obj);
633
634 if (PyErr_Occurred()) {
635 PyErr_Clear();
636 return -1;
637 }
638 return res;
639 }
640
641 /**
642 * pygi_value_to_py_basic_type:
643 * @value: the GValue object.
644 * @handled: (out): TRUE if the return value is defined
645 *
646 * This function creates/returns a Python wrapper object that
647 * represents the GValue passed as an argument limited to supporting basic types
648 * like ints, bools, and strings.
649 *
650 * Returns: a PyObject representing the value.
651 */
652 PyObject *
pygi_value_to_py_basic_type(const GValue * value,GType fundamental,gboolean * handled)653 pygi_value_to_py_basic_type (const GValue *value, GType fundamental, gboolean *handled)
654 {
655 *handled = TRUE;
656 switch (fundamental) {
657 case G_TYPE_CHAR:
658 return PyLong_FromLong (g_value_get_schar (value));
659 case G_TYPE_UCHAR:
660 return PyLong_FromLong (g_value_get_uchar (value));
661 case G_TYPE_BOOLEAN:
662 return pygi_gboolean_to_py (g_value_get_boolean (value));
663 case G_TYPE_INT:
664 return pygi_gint_to_py (g_value_get_int (value));
665 case G_TYPE_UINT:
666 return pygi_guint_to_py (g_value_get_uint (value));
667 case G_TYPE_LONG:
668 return pygi_glong_to_py (g_value_get_long(value));
669 case G_TYPE_ULONG:
670 return pygi_gulong_to_py (g_value_get_ulong (value));
671 case G_TYPE_INT64:
672 return pygi_gint64_to_py (g_value_get_int64 (value));
673 case G_TYPE_UINT64:
674 return pygi_guint64_to_py (g_value_get_uint64 (value));
675 case G_TYPE_ENUM:
676 return pyg_enum_from_gtype (G_VALUE_TYPE (value),
677 g_value_get_enum (value));
678 case G_TYPE_FLAGS:
679 return pyg_flags_from_gtype (G_VALUE_TYPE (value),
680 g_value_get_flags (value));
681 case G_TYPE_FLOAT:
682 return pygi_gfloat_to_py (g_value_get_float (value));
683 case G_TYPE_DOUBLE:
684 return pygi_gdouble_to_py (g_value_get_double (value));
685 case G_TYPE_STRING:
686 return pygi_utf8_to_py (g_value_get_string (value));
687 default:
688 *handled = FALSE;
689 return NULL;
690 }
691 }
692
693 /**
694 * value_to_py_structured_type:
695 * @value: the GValue object.
696 * @copy_boxed: true if boxed values should be copied.
697 *
698 * This function creates/returns a Python wrapper object that
699 * represents the GValue passed as an argument.
700 *
701 * Returns: a PyObject representing the value or NULL and sets an error;
702 */
703 static PyObject *
value_to_py_structured_type(const GValue * value,GType fundamental,gboolean copy_boxed)704 value_to_py_structured_type (const GValue *value, GType fundamental, gboolean copy_boxed)
705 {
706 const gchar *type_name;
707
708 switch (fundamental) {
709 case G_TYPE_INTERFACE:
710 if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT))
711 return pygobject_new(g_value_get_object(value));
712 else
713 break;
714
715 case G_TYPE_POINTER:
716 if (G_VALUE_HOLDS_GTYPE (value))
717 return pyg_type_wrapper_new (g_value_get_gtype (value));
718 else
719 return pyg_pointer_new(G_VALUE_TYPE(value),
720 g_value_get_pointer(value));
721 case G_TYPE_BOXED: {
722 PyGTypeMarshal *bm;
723 gboolean holds_value_array;
724
725 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
726 holds_value_array = G_VALUE_HOLDS(value, PYGI_TYPE_VALUE_ARRAY);
727 G_GNUC_END_IGNORE_DEPRECATIONS
728
729 if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) {
730 PyObject *ret = (PyObject *)g_value_dup_boxed(value);
731 if (ret == NULL) {
732 Py_INCREF(Py_None);
733 return Py_None;
734 }
735 return ret;
736 } else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) {
737 GValue *n_value = g_value_get_boxed (value);
738 return pyg_value_as_pyobject(n_value, copy_boxed);
739 } else if (holds_value_array) {
740 GValueArray *array = (GValueArray *) g_value_get_boxed(value);
741 Py_ssize_t n_values = array ? array->n_values : 0;
742 PyObject *ret = PyList_New(n_values);
743 int i;
744 for (i = 0; i < n_values; ++i)
745 PyList_SET_ITEM(ret, i, pyg_value_as_pyobject
746 (array->values + i, copy_boxed));
747 return ret;
748 } else if (G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
749 GString *string = (GString *) g_value_get_boxed(value);
750 PyObject *ret = PyUnicode_FromStringAndSize (string->str, string->len);
751 return ret;
752 }
753 bm = pyg_type_lookup(G_VALUE_TYPE(value));
754 if (bm) {
755 return bm->fromvalue(value);
756 } else {
757 if (copy_boxed)
758 return pygi_gboxed_new(G_VALUE_TYPE(value),
759 g_value_get_boxed(value), TRUE, TRUE);
760 else
761 return pygi_gboxed_new(G_VALUE_TYPE(value),
762 g_value_get_boxed(value),FALSE,FALSE);
763 }
764 }
765 case G_TYPE_PARAM:
766 return pyg_param_spec_new(g_value_get_param(value));
767 case G_TYPE_OBJECT:
768 return pygobject_new(g_value_get_object(value));
769 case G_TYPE_VARIANT:
770 {
771 GVariant *v = g_value_get_variant(value);
772 if (v == NULL) {
773 Py_INCREF(Py_None);
774 return Py_None;
775 }
776 return pygi_struct_new_from_g_type (G_TYPE_VARIANT, g_variant_ref(v), FALSE);
777 }
778 default:
779 {
780 PyGTypeMarshal *bm;
781 if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))))
782 return bm->fromvalue(value);
783 break;
784 }
785 }
786
787 type_name = g_type_name (G_VALUE_TYPE (value));
788 if (type_name == NULL) {
789 type_name = "(null)";
790 }
791 PyErr_Format (PyExc_TypeError, "unknown type %s", type_name);
792 return NULL;
793 }
794
795
796 /**
797 * pyg_value_as_pyobject:
798 * @value: the GValue object.
799 * @copy_boxed: true if boxed values should be copied.
800 *
801 * This function creates/returns a Python wrapper object that
802 * represents the GValue passed as an argument.
803 *
804 * Returns: a PyObject representing the value or %NULL and sets an exception.
805 */
806 PyObject *
pyg_value_as_pyobject(const GValue * value,gboolean copy_boxed)807 pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed)
808 {
809 PyObject *pyobj;
810 gboolean handled;
811 GType fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value));
812
813 /* HACK: special case char and uchar to return PyBytes intstead of integers
814 * in the general case. Property access will skip this by calling
815 * pygi_value_to_py_basic_type() directly.
816 * See: https://bugzilla.gnome.org/show_bug.cgi?id=733893 */
817 if (fundamental == G_TYPE_CHAR) {
818 gint8 val = g_value_get_schar(value);
819 return PyUnicode_FromStringAndSize ((char *)&val, 1);
820 } else if (fundamental == G_TYPE_UCHAR) {
821 guint8 val = g_value_get_uchar(value);
822 return PyBytes_FromStringAndSize ((char *)&val, 1);
823 }
824
825 pyobj = pygi_value_to_py_basic_type (value, fundamental, &handled);
826 if (handled)
827 return pyobj;
828
829 pyobj = value_to_py_structured_type (value, fundamental, copy_boxed);
830 return pyobj;
831 }
832
833
834 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
835 int
pyg_param_gvalue_from_pyobject(GValue * value,PyObject * py_obj,const GParamSpec * pspec)836 pyg_param_gvalue_from_pyobject(GValue* value,
837 PyObject* py_obj,
838 const GParamSpec* pspec)
839 {
840 if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
841 gunichar u;
842
843 if (!pyg_pyobj_to_unichar_conv(py_obj, &u)) {
844 PyErr_Clear();
845 return -1;
846 }
847 g_value_set_uint(value, u);
848 return 0;
849 }
850 else if (PYGI_IS_PARAM_SPEC_VALUE_ARRAY(pspec))
851 return pyg_value_array_from_pyobject(value, py_obj,
852 PYGI_PARAM_SPEC_VALUE_ARRAY(pspec));
853 else {
854 return pyg_value_from_pyobject(value, py_obj);
855 }
856 }
857
858 G_GNUC_END_IGNORE_DEPRECATIONS
859
860 PyObject*
pyg_param_gvalue_as_pyobject(const GValue * gvalue,gboolean copy_boxed,const GParamSpec * pspec)861 pyg_param_gvalue_as_pyobject(const GValue* gvalue,
862 gboolean copy_boxed,
863 const GParamSpec* pspec)
864 {
865 if (G_IS_PARAM_SPEC_UNICHAR(pspec)) {
866 gunichar u;
867 gchar *encoded;
868 PyObject *retval;
869
870 u = g_value_get_uint (gvalue);
871 encoded = g_ucs4_to_utf8 (&u, 1, NULL, NULL, NULL);
872 if (encoded == NULL) {
873 PyErr_SetString (PyExc_ValueError, "Failed to decode");
874 return NULL;
875 }
876 retval = PyUnicode_FromString (encoded);
877 g_free (encoded);
878 return retval;
879 }
880 else {
881 return pyg_value_as_pyobject(gvalue, copy_boxed);
882 }
883 }
884
885 PyObject *
pyg__gvalue_get(PyObject * module,PyObject * pygvalue)886 pyg__gvalue_get(PyObject *module, PyObject *pygvalue)
887 {
888 if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
889 PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
890 return NULL;
891 }
892
893 return pyg_value_as_pyobject (pyg_boxed_get(pygvalue, GValue),
894 /*copy_boxed=*/ TRUE);
895 }
896
897 PyObject *
pyg__gvalue_get_type(PyObject * module,PyObject * pygvalue)898 pyg__gvalue_get_type(PyObject *module, PyObject *pygvalue)
899 {
900 GValue *value;
901 GType type;
902
903 if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
904 PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
905 return NULL;
906 }
907
908 value = pyg_boxed_get (pygvalue, GValue);
909 type = G_VALUE_TYPE (value);
910 return pyg_type_wrapper_new (type);
911 }
912
913 PyObject *
pyg__gvalue_set(PyObject * module,PyObject * args)914 pyg__gvalue_set(PyObject *module, PyObject *args)
915 {
916 PyObject *pygvalue;
917 PyObject *pyobject;
918
919 if (!PyArg_ParseTuple (args, "OO:_gi._gvalue_set",
920 &pygvalue, &pyobject))
921 return NULL;
922
923 if (!pyg_boxed_check (pygvalue, G_TYPE_VALUE)) {
924 PyErr_SetString (PyExc_TypeError, "Expected GValue argument.");
925 return NULL;
926 }
927
928 if (pyg_value_from_pyobject_with_error (pyg_boxed_get (pygvalue, GValue),
929 pyobject) == -1)
930 return NULL;
931
932 Py_RETURN_NONE;
933 }
934