diff options
Diffstat (limited to 'gi')
-rw-r--r-- | gi/_gobject/propertyhelper.py | 29 | ||||
-rw-r--r-- | gi/_gobject/pygenum.c | 6 | ||||
-rw-r--r-- | gi/_gobject/pygobject.c | 8 | ||||
-rw-r--r-- | gi/_gobject/pygtype.c | 82 | ||||
-rw-r--r-- | gi/gimodule.c | 80 | ||||
-rw-r--r-- | gi/overrides/GObject.py | 127 | ||||
-rw-r--r-- | gi/overrides/Gtk.py | 119 | ||||
-rw-r--r-- | gi/pygi-argument.c | 20 | ||||
-rw-r--r-- | gi/pygi-cache.c | 1 | ||||
-rw-r--r-- | gi/pygi-closure.c | 90 | ||||
-rw-r--r-- | gi/pygi-info.c | 3 | ||||
-rw-r--r-- | gi/pygi-marshal-from-py.c | 40 | ||||
-rw-r--r-- | gi/pygi-marshal-to-py.c | 9 | ||||
-rw-r--r-- | gi/pygi-property.c | 10 |
14 files changed, 430 insertions, 194 deletions
diff --git a/gi/_gobject/propertyhelper.py b/gi/_gobject/propertyhelper.py index a038f1b..d5a1852 100644 --- a/gi/_gobject/propertyhelper.py +++ b/gi/_gobject/propertyhelper.py @@ -149,6 +149,8 @@ class Property(object): @keyword maximum: maximum allowed value (int, float, long only) """ + self.name = None + if type is None: type = object self.type = self._type_from_python(type) @@ -180,7 +182,9 @@ class Property(object): getter = self._default_getter setter = self._default_setter self.getter(getter) - self.setter(setter) + # do not call self.setter() here, as this defines the property name + # already + self.fset = setter if minimum is not None: if minimum < self._get_minimum(): @@ -199,8 +203,6 @@ class Property(object): maximum = self._get_maximum() self.maximum = maximum - self.name = None - self._exc = None def __repr__(self): @@ -248,6 +250,11 @@ class Property(object): def setter(self, fset): """Set the setter function to fset. For use as a decorator.""" self.fset = fset + # with a setter decorator, we must ignore the name of the method in + # install_properties, as this does not need to be a valid property name + # and does not define the property name. So set the name here. + if not self.name: + self.name = self.fget.__name__ return self def _type_from_python(self, type_): @@ -364,10 +371,18 @@ def install_properties(cls): props = [] for name, prop in cls.__dict__.items(): if isinstance(prop, Property): # not same as the built-in - if name in gproperties: - raise ValueError('Property %s was already found in __gproperties__' % name) - prop.name = name - gproperties[name] = prop.get_pspec_args() + # if a property was defined with a decorator, it may already have + # a name; if it was defined with an assignment (prop = Property(...)) + # we set the property's name to the member name + if not prop.name: + prop.name = name + # we will encounter the same property multiple times in case of + # custom setter methods + if prop.name in gproperties: + if gproperties[prop.name] == prop.get_pspec_args(): + continue + raise ValueError('Property %s was already found in __gproperties__' % prop.name) + gproperties[prop.name] = prop.get_pspec_args() props.append(prop) if not props: diff --git a/gi/_gobject/pygenum.c b/gi/_gobject/pygenum.c index 9c3c455..89e3a06 100644 --- a/gi/_gobject/pygenum.c +++ b/gi/_gobject/pygenum.c @@ -216,9 +216,9 @@ pyg_enum_add (PyObject * module, int i; g_return_val_if_fail(typename != NULL, NULL); - if (!g_type_is_a(gtype, G_TYPE_ENUM)) { - g_warning("Trying to register gtype '%s' as enum when in fact it is of type '%s'", - g_type_name(gtype), g_type_name(G_TYPE_FUNDAMENTAL(gtype))); + if (!g_type_is_a (gtype, G_TYPE_ENUM)) { + PyErr_Format (PyExc_TypeError, "Trying to register gtype '%s' as enum when in fact it is of type '%s'", + g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype))); return NULL; } diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c index 3d0c819..00444bd 100644 --- a/gi/_gobject/pygobject.c +++ b/gi/_gobject/pygobject.c @@ -1872,7 +1872,7 @@ pygobject_handler_unblock(PyGObject *self, PyObject *args) static PyObject * pygobject_emit(PyGObject *self, PyObject *args) { - guint signal_id, i; + guint signal_id, i, j; Py_ssize_t len; GQuark detail; PyObject *first, *py_ret, *repr = NULL; @@ -1929,11 +1929,11 @@ pygobject_emit(PyGObject *self, PyObject *args) g_snprintf(buf, sizeof(buf), "could not convert type %s to %s required for parameter %d", Py_TYPE(item)->tp_name, - g_type_name(G_VALUE_TYPE(¶ms[i+1])), i); + G_VALUE_TYPE_NAME(¶ms[i+1]), i); PyErr_SetString(PyExc_TypeError, buf); - for (i = 0; i < query.n_params + 1; i++) - g_value_unset(¶ms[i]); + for (j = 0; j <= i; j++) + g_value_unset(¶ms[j]); g_free(params); return NULL; diff --git a/gi/_gobject/pygtype.c b/gi/_gobject/pygtype.c index 79c8387..227178f 100644 --- a/gi/_gobject/pygtype.c +++ b/gi/_gobject/pygtype.c @@ -727,6 +727,63 @@ pyg_value_array_from_pyobject(GValue *value, return 0; } +static int +pyg_array_from_pyobject(GValue *value, + PyObject *obj) +{ + int len; + GArray *array; + int i; + + len = PySequence_Length(obj); + if (len == -1) { + PyErr_Clear(); + return -1; + } + + array = g_array_new(FALSE, TRUE, sizeof(GValue)); + + for (i = 0; i < len; ++i) { + PyObject *item = PySequence_GetItem(obj, i); + GType type; + GValue item_value = { 0, }; + int status; + + if (! item) { + PyErr_Clear(); + g_array_free(array, FALSE); + return -1; + } + + if (item == Py_None) + type = G_TYPE_POINTER; /* store None as NULL */ + else { + type = pyg_type_from_object((PyObject*)Py_TYPE(item)); + if (! type) { + PyErr_Clear(); + g_array_free(array, FALSE); + Py_DECREF(item); + return -1; + } + } + + g_value_init(&item_value, type); + status = pyg_value_from_pyobject(&item_value, item); + Py_DECREF(item); + + if (status == -1) { + g_array_free(array, FALSE); + g_value_unset(&item_value); + return -1; + } + + g_array_append_val(array, item_value); + } + + g_value_take_boxed(value, array); + return 0; +} + /** * pyg_value_from_pyobject: * @value: the GValue object to store the converted value in. @@ -766,12 +823,20 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) } break; case G_TYPE_CHAR: + if (PYGLIB_PyLong_Check(obj)) { + glong val; + val = PYGLIB_PyLong_AsLong(obj); + if (val >= -128 && val <= 127) + g_value_set_schar(value, (gchar) val); + else + return -1; + } #if PY_VERSION_HEX < 0x03000000 - if (PyString_Check(obj)) { + else if (PyString_Check(obj)) { g_value_set_schar(value, PyString_AsString(obj)[0]); - } else + } #endif - if (PyUnicode_Check(obj)) { + else if (PyUnicode_Check(obj)) { tmp = PyUnicode_AsUTF8String(obj); g_value_set_schar(value, PYGLIB_PyBytes_AsString(tmp)[0]); Py_DECREF(tmp); @@ -786,7 +851,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) glong val; val = PYGLIB_PyLong_AsLong(obj); if (val >= 0 && val <= 255) - g_value_set_uchar(value, (guchar)PYGLIB_PyLong_AsLong (obj)); + g_value_set_uchar(value, (guchar) val); else return -1; #if PY_VERSION_HEX < 0x03000000 @@ -959,6 +1024,9 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) else if (PySequence_Check(obj) && G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY)) return pyg_value_array_from_pyobject(value, obj, NULL); + else if (PySequence_Check(obj) && + G_VALUE_HOLDS(value, G_TYPE_ARRAY)) + return pyg_array_from_pyobject(value, obj); else if (PYGLIB_PyUnicode_Check(obj) && G_VALUE_HOLDS(value, G_TYPE_GSTRING)) { GString *string; @@ -980,7 +1048,11 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) break; } case G_TYPE_PARAM: - if (PyGParamSpec_Check(obj)) + /* we need to support both the wrapped _gobject.GParamSpec and the GI + * GObject.ParamSpec */ + if (G_IS_PARAM_SPEC (pygobject_get (obj))) + g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj))); + else if (PyGParamSpec_Check(obj)) g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL)); else return -1; diff --git a/gi/gimodule.c b/gi/gimodule.c index 76530f1..bb5c306 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -62,7 +62,9 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, gint n_values; GEnumValue *g_enum_values; int i; + const gchar *namespace; const gchar *type_name; + gchar *full_name; GType g_type; if (!PyArg_ParseTupleAndKeywords (args, kwargs, @@ -79,6 +81,10 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, info = (GIEnumInfo *)py_info->info; n_values = g_enum_info_get_n_values (info); + + /* The new memory is zero filled which fulfills the registration + * function requirement that the last item is zeroed out as a terminator. + */ g_enum_values = g_new0 (GEnumValue, n_values + 1); for (i = 0; i < n_values; i++) { @@ -105,14 +111,36 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, g_base_info_unref ((GIBaseInfo *) value_info); } - g_enum_values[n_values].value = 0; - g_enum_values[n_values].value_nick = NULL; - g_enum_values[n_values].value_name = NULL; - + namespace = g_base_info_get_namespace ((GIBaseInfo *) info); type_name = g_base_info_get_name ((GIBaseInfo *) info); - type_name = g_strdup (type_name); - g_type = g_enum_register_static (type_name, g_enum_values); + full_name = g_strconcat (namespace, type_name, NULL); + + /* If enum registration fails, free all the memory allocated + * for the values array. This needs to leak when successful + * as GObject keeps a reference to the data as specified in the docs. + */ + g_type = g_enum_register_static (full_name, g_enum_values); + if (g_type == G_TYPE_INVALID) { + for (i = 0; i < n_values; i++) { + GEnumValue *enum_value = &g_enum_values[i]; + + /* Only free value_name if it is different from value_nick to avoid + * a double free. The pointer might have been is re-used in the case + * c_identifier was NULL in the above loop. + */ + if (enum_value->value_name != enum_value->value_nick) + g_free ((gchar *) enum_value->value_name); + g_free ((gchar *) enum_value->value_nick); + } + + PyErr_Format (PyExc_RuntimeError, "Unable to register enum '%s'", full_name); + + g_free (g_enum_values); + g_free (full_name); + return NULL; + } + g_free (full_name); return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type); } @@ -150,7 +178,9 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, gint n_values; GFlagsValue *g_flags_values; int i; + const gchar *namespace; const gchar *type_name; + gchar *full_name; GType g_type; if (!PyArg_ParseTupleAndKeywords (args, kwargs, @@ -167,6 +197,10 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, info = (GIEnumInfo *)py_info->info; n_values = g_enum_info_get_n_values (info); + + /* The new memory is zero filled which fulfills the registration + * function requirement that the last item is zeroed out as a terminator. + */ g_flags_values = g_new0 (GFlagsValue, n_values + 1); for (i = 0; i < n_values; i++) { @@ -193,14 +227,36 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, g_base_info_unref ((GIBaseInfo *) value_info); } - g_flags_values[n_values].value = 0; - g_flags_values[n_values].value_nick = NULL; - g_flags_values[n_values].value_name = NULL; - + namespace = g_base_info_get_namespace ((GIBaseInfo *) info); type_name = g_base_info_get_name ((GIBaseInfo *) info); - type_name = g_strdup (type_name); - g_type = g_flags_register_static (type_name, g_flags_values); + full_name = g_strconcat (namespace, type_name, NULL); + + /* If enum registration fails, free all the memory allocated + * for the values array. This needs to leak when successful + * as GObject keeps a reference to the data as specified in the docs. + */ + g_type = g_flags_register_static (full_name, g_flags_values); + if (g_type == G_TYPE_INVALID) { + for (i = 0; i < n_values; i++) { + GFlagsValue *flags_value = &g_flags_values[i]; + + /* Only free value_name if it is different from value_nick to avoid + * a double free. The pointer might have been is re-used in the case + * c_identifier was NULL in the above loop. + */ + if (flags_value->value_name != flags_value->value_nick) + g_free ((gchar *) flags_value->value_name); + g_free ((gchar *) flags_value->value_nick); + } + + PyErr_Format (PyExc_RuntimeError, "Unable to register flags '%s'", full_name); + + g_free (g_flags_values); + g_free (full_name); + return NULL; + } + g_free (full_name); return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type); } diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py index c0198b3..41062e2 100644 --- a/gi/overrides/GObject.py +++ b/gi/overrides/GObject.py @@ -4,6 +4,7 @@ # Copyright (C) 2012 Canonical Ltd. # Author: Martin Pitt <martin.pitt@ubuntu.com> # Copyright (C) 2012 Simon Feltman <sfeltman@src.gnome.org> +# Copyright (C) 2012 Bastian Winkler <buz@netbuz.org> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -205,10 +206,134 @@ __all__ += ['add_emission_hook', 'features', 'list_properties', class Value(GObjectModule.Value): + def __new__(cls, *args, **kwargs): + return GObjectModule.Value.__new__(cls) + + def __init__(self, value_type=None, py_value=None): + GObjectModule.Value.__init__(self) + if value_type is not None: + self.init(value_type) + if py_value is not None: + self.set_value(py_value) + def __del__(self): - if self._free_on_dealloc: + if self._free_on_dealloc and self.g_type != TYPE_INVALID: self.unset() + def set_value(self, py_value): + if self.g_type == _gobject.TYPE_INVALID: + raise TypeError("GObject.Value needs to be initialized first") + elif self.g_type == TYPE_BOOLEAN: + self.set_boolean(py_value) + elif self.g_type == TYPE_CHAR: + self.set_char(py_value) + elif self.g_type == TYPE_UCHAR: + self.set_uchar(py_value) + elif self.g_type == TYPE_INT: + self.set_int(py_value) + elif self.g_type == TYPE_UINT: + self.set_uint(py_value) + elif self.g_type == TYPE_LONG: + self.set_long(py_value) + elif self.g_type == TYPE_ULONG: + self.set_ulong(py_value) + elif self.g_type == TYPE_INT64: + self.set_int64(py_value) + elif self.g_type == TYPE_UINT64: + self.set_uint64(py_value) + elif self.g_type == TYPE_FLOAT: + self.set_float(py_value) + elif self.g_type == TYPE_DOUBLE: + self.set_double(py_value) + elif self.g_type == TYPE_STRING: + if isinstance(py_value, str): + py_value = str(py_value) + elif sys.version_info < (3, 0): + if isinstance(py_value, unicode): + py_value = py_value.encode('UTF-8') + else: + raise ValueError("Expected string or unicode but got %s%s" % + (py_value, type(py_value))) + else: + raise ValueError("Expected string but got %s%s" % + (py_value, type(py_value))) + self.set_string(py_value) + elif self.g_type == TYPE_PARAM: + self.set_param(py_value) + elif self.g_type.is_a(TYPE_ENUM): + self.set_enum(py_value) + elif self.g_type.is_a(TYPE_FLAGS): + self.set_flags(py_value) + elif self.g_type.is_a(TYPE_BOXED): + self.set_boxed(py_value) + elif self.g_type == TYPE_POINTER: + self.set_pointer(py_value) + elif self.g_type.is_a(TYPE_OBJECT): + self.set_object(py_value) + elif self.g_type == TYPE_UNICHAR: + self.set_uint(int(py_value)) + # elif self.g_type == TYPE_OVERRIDE: + # pass + elif self.g_type == TYPE_GTYPE: + self.set_gtype(py_value) + elif self.g_type == TYPE_VARIANT: + self.set_variant(py_value) + elif self.g_type == TYPE_PYOBJECT: + self.set_boxed(py_value) + else: + raise TypeError("Unknown value type %s" % self.g_type) + + def get_value(self): + if self.g_type == TYPE_BOOLEAN: + return self.get_boolean() + elif self.g_type == TYPE_CHAR: + return self.get_char() + elif self.g_type == TYPE_UCHAR: + return self.get_uchar() + elif self.g_type == TYPE_INT: + return self.get_int() + elif self.g_type == TYPE_UINT: + return self.get_uint() + elif self.g_type == TYPE_LONG: + return self.get_long() + elif self.g_type == TYPE_ULONG: + return self.get_ulong() + elif self.g_type == TYPE_INT64: + return self.get_int64() + elif self.g_type == TYPE_UINT64: + return self.get_uint64() + elif self.g_type == TYPE_FLOAT: + return self.get_float() + elif self.g_type == TYPE_DOUBLE: + return self.get_double() + elif self.g_type == TYPE_STRING: + return self.get_string() + elif self.g_type == TYPE_PARAM: + return self.get_param() + elif self.g_type.is_a(TYPE_ENUM): + return self.get_enum() + elif self.g_type.is_a(TYPE_FLAGS): + return self.get_flags() + elif self.g_type.is_a(TYPE_BOXED): + return self.get_boxed() + elif self.g_type == TYPE_POINTER: + return self.get_pointer() + elif self.g_type.is_a(TYPE_OBJECT): + return self.get_object() + elif self.g_type == TYPE_UNICHAR: + return self.get_uint() + elif self.g_type == TYPE_GTYPE: + return self.get_gtype() + elif self.g_type == TYPE_VARIANT: + return self.get_variant() + elif self.g_type == TYPE_PYOBJECT: + pass + else: + return None + + def __repr__(self): + return '<Value (%s) %s>' % (self.g_type.name, self.get_value()) + Value = override(Value) __all__.append('Value') diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index 78bbd36..15c0ae6 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -294,7 +294,7 @@ class UIManager(Gtk.UIManager): if not isinstance(buffer, _basestring): raise TypeError('buffer must be a string') - length = len(buffer) + length = len(buffer.encode('UTF-8')) return Gtk.UIManager.add_ui_from_string(self, buffer, length) @@ -780,6 +780,12 @@ class TreeModel(Gtk.TreeModel): raise IndexError("could not find tree path '%s'" % key) return aiter + def _coerce_path(self, path): + if isinstance(path, Gtk.TreePath): + return path + else: + return TreePath(path) + def __getitem__(self, key): aiter = self._getiter(key) return TreeModelRow(self, aiter) @@ -796,9 +802,7 @@ class TreeModel(Gtk.TreeModel): return TreeModelRowIter(self, self.get_iter_first()) def get_iter(self, path): - if not isinstance(path, Gtk.TreePath): - path = TreePath(path) - + path = self._coerce_path(path) success, aiter = super(TreeModel, self).get_iter(path) if not success: raise ValueError("invalid tree path '%s'" % path) @@ -872,84 +876,11 @@ class TreeModel(Gtk.TreeModel): self.set_value(treeiter, column, value) def _convert_value(self, column, value): - if value is None: - return None + '''Convert value to a GObject.Value of the expected type''' - # we may need to convert to a basic type - type_ = self.get_column_type(column) - if type_ == GObject.TYPE_STRING: - if isinstance(value, str): - value = str(value) - elif sys.version_info < (3, 0): - if isinstance(value, unicode): - value = value.encode('UTF-8') - else: - raise ValueError('Expected string or unicode for column %i but got %s%s' % (column, value, type(value))) - else: - raise ValueError('Expected a string for column %i but got %s' % (column, type(value))) - elif type_ == GObject.TYPE_FLOAT or type_ == GObject.TYPE_DOUBLE: - if isinstance(value, float): - value = float(value) - else: - raise ValueError('Expected a float for column %i but got %s' % (column, type(value))) - elif type_ == GObject.TYPE_LONG or type_ == GObject.TYPE_INT: - if isinstance(value, int): - value = int(value) - elif sys.version_info < (3, 0): - if isinstance(value, long): - value = long(value) - else: - raise ValueError('Expected an long for column %i but got %s' % (column, type(value))) - else: - raise ValueError('Expected an integer for column %i but got %s' % (column, type(value))) - elif type_ == GObject.TYPE_BOOLEAN: - cmp_classes = [int] - if sys.version_info < (3, 0): - cmp_classes.append(long) - - if isinstance(value, tuple(cmp_classes)): - value = bool(value) - else: - raise ValueError('Expected a bool for column %i but got %s' % (column, type(value))) - else: - # use GValues directly to marshal to the correct type - # standard object checks should take care of validation - # so we don't have to do it here - value_container = GObject.Value() - value_container.init(type_) - if type_ == GObject.TYPE_CHAR: - value_container.set_char(value) - value = value_container - elif type_ == GObject.TYPE_UCHAR: - value_container.set_uchar(value) - value = value_container - elif type_ == GObject.TYPE_UNICHAR: - cmp_classes = [str] - if sys.version_info < (3, 0): - cmp_classes.append(unicode) - - if isinstance(value, tuple(cmp_classes)): - value = ord(value[0]) - - value_container.set_uint(value) - value = value_container - elif type_ == GObject.TYPE_UINT: - value_container.set_uint(value) - value = value_container - elif type_ == GObject.TYPE_ULONG: - value_container.set_ulong(value) - value = value_container - elif type_ == GObject.TYPE_INT64: - value_container.set_int64(value) - value = value_container - elif type_ == GObject.TYPE_UINT64: - value_container.set_uint64(value) - value = value_container - elif type_ == GObject.TYPE_PYOBJECT: - value_container.set_boxed(value) - value = value_container - - return value + if isinstance(value, GObject.Value): + return value + return GObject.Value(self.get_column_type(column), value) def get(self, treeiter, *columns): n_columns = self.get_n_columns() @@ -969,6 +900,27 @@ class TreeModel(Gtk.TreeModel): def filter_new(self, root=None): return super(TreeModel, self).filter_new(root) + # + # Signals supporting python iterables as tree paths + # + def row_changed(self, path, iter): + return super(TreeModel, self).row_changed(self._coerce_path(path), iter) + + def row_inserted(self, path, iter): + return super(TreeModel, self).row_inserted(self._coerce_path(path), iter) + + def row_has_child_toggled(self, path, iter): + return super(TreeModel, self).row_has_child_toggled(self._coerce_path(path), + iter) + + def row_deleted(self, path): + return super(TreeModel, self).row_deleted(self._coerce_path(path)) + + def rows_reordered(self, path, iter, new_order): + return super(TreeModel, self).rows_reordered(self._coerce_path(path), + iter, new_order) + + TreeModel = override(TreeModel) __all__.append('TreeModel') @@ -1592,6 +1544,11 @@ class TreeModelFilter(Gtk.TreeModelFilter): def set_visible_func(self, func, data=None): super(TreeModelFilter, self).set_visible_func(func, data) + def set_value(self, iter, column, value): + # Delegate to child model + iter = self.convert_iter_to_child_iter(iter) + self.get_model().set_value(iter, column, value) + TreeModelFilter = override(TreeModelFilter) __all__.append('TreeModelFilter') diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 4e3c464..34c4970 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -410,7 +410,8 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info, /* No check; every Python object has a truth value. */ break; case GI_TYPE_TAG_UINT8: - /* UINT8 types can be characters */ + case GI_TYPE_TAG_INT8: + /* (U)INT8 types can be characters */ if (PYGLIB_PyBytes_Check(object)) { if (PYGLIB_PyBytes_Size(object) != 1) { PyErr_Format (PyExc_TypeError, "Must be a single character"); @@ -420,7 +421,6 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info, break; } - case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: @@ -811,22 +811,18 @@ _pygi_argument_to_array (GIArgument *arg, return g_array; } gint length_arg_pos; - GIArgInfo *length_arg_info; - GITypeInfo *length_type_info; + GIArgInfo length_arg_info; + GITypeInfo length_type_info; length_arg_pos = g_type_info_get_array_length (type_info); g_assert (length_arg_pos >= 0); g_assert (callable_info); - length_arg_info = g_callable_info_get_arg (callable_info, length_arg_pos); - length_type_info = g_arg_info_get_type (length_arg_info); - g_base_info_unref ( (GIBaseInfo *) length_arg_info); + g_callable_info_load_arg (callable_info, length_arg_pos, &length_arg_info); + g_arg_info_load_type (&length_arg_info, &length_type_info); if (!gi_argument_to_gssize (args[length_arg_pos], - g_type_info_get_tag (length_type_info), - &length)) { - g_base_info_unref ( (GIBaseInfo *) length_type_info); + g_type_info_get_tag (&length_type_info), + &length)) return NULL; - } - g_base_info_unref ( (GIBaseInfo *) length_type_info); } } diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index 2a44c02..0848ccf 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -480,6 +480,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache, child_cache = _arg_cache_alloc (); } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD || child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) { + arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array; return TRUE; } diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c index 0e49c72..f2f21f0 100644 --- a/gi/pygi-closure.c +++ b/gi/pygi-closure.c @@ -154,8 +154,8 @@ static GIArgument * _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) { gint num_args, i; - GIArgInfo *arg_info; - GITypeInfo *arg_type; + GIArgInfo arg_info; + GITypeInfo arg_type; GITypeTag tag; GIDirection direction; GIArgument *g_args; @@ -164,10 +164,10 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) g_args = g_new0 (GIArgument, num_args); for (i = 0; i < num_args; i++) { - arg_info = g_callable_info_get_arg (callable_info, i); - arg_type = g_arg_info_get_type (arg_info); - tag = g_type_info_get_tag (arg_type); - direction = g_arg_info_get_direction (arg_info); + g_callable_info_load_arg (callable_info, i, &arg_info); + g_arg_info_load_type (&arg_info, &arg_type); + tag = g_type_info_get_tag (&arg_type); + direction = g_arg_info_get_direction (&arg_info); if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { g_args[i].v_pointer = * (gpointer *) args[i]; @@ -214,7 +214,7 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) GIBaseInfo *interface; GIInfoType interface_type; - interface = g_type_info_get_interface (arg_type); + interface = g_type_info_get_interface (&arg_type); interface_type = g_base_info_get_type (interface); if (interface_type == GI_INFO_TYPE_OBJECT || @@ -249,8 +249,6 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) g_args[i].v_pointer = 0; } } - g_base_info_unref ( (GIBaseInfo *) arg_info); - g_base_info_unref ( (GIBaseInfo *) arg_type); } return g_args; } @@ -283,19 +281,21 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, if (i == user_data_arg || i == destroy_notify_arg) continue; - GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i); - GIDirection direction = g_arg_info_get_direction (arg_info); + GIArgInfo arg_info; + g_callable_info_load_arg (callable_info, i, &arg_info); + GIDirection direction = g_arg_info_get_direction (&arg_info); if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { - GITypeInfo *arg_type = g_arg_info_get_type (arg_info); - GITypeTag arg_tag = g_type_info_get_tag (arg_type); - GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); + GITypeInfo arg_type; + g_arg_info_load_type (&arg_info, &arg_type); + GITypeTag arg_tag = g_type_info_get_tag (&arg_type); + GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info); PyObject *value; GIArgument *arg; gboolean free_array = FALSE; if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID && - g_type_info_is_pointer (arg_type)) { + g_type_info_is_pointer (&arg_type)) { if (user_data == NULL) { Py_INCREF (Py_None); @@ -310,7 +310,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, GIBaseInfo *info; GIInfoType info_type; - info = g_type_info_get_interface (arg_type); + info = g_type_info_get_interface (&arg_type); info_type = g_base_info_get_type (info); arg = (GIArgument*) &g_args[i]; @@ -318,10 +318,10 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, if (info_type == GI_INFO_TYPE_CALLBACK) { gpointer user_data = NULL; GDestroyNotify destroy_notify = NULL; - GIScopeType scope = g_arg_info_get_scope(arg_info); + GIScopeType scope = g_arg_info_get_scope(&arg_info); - user_data_arg = g_arg_info_get_closure(arg_info); - destroy_notify_arg = g_arg_info_get_destroy(arg_info); + user_data_arg = g_arg_info_get_closure(&arg_info); + destroy_notify_arg = g_arg_info_get_destroy(&arg_info); if (user_data_arg != -1) user_data = g_args[user_data_arg].v_pointer; @@ -335,39 +335,31 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, (GIFunctionInfo *) info, destroy_notify); } else - value = _pygi_argument_to_object (arg, arg_type, transfer); + value = _pygi_argument_to_object (arg, &arg_type, transfer); g_base_info_unref (info); - if (value == NULL) { - g_base_info_unref (arg_type); - g_base_info_unref (arg_info); + if (value == NULL) goto error; - } } else { if (direction == GI_DIRECTION_IN) arg = (GIArgument*) &g_args[i]; else arg = (GIArgument*) g_args[i].v_pointer; - if (g_type_info_get_tag (arg_type) == GI_TYPE_TAG_ARRAY) + if (g_type_info_get_tag (&arg_type) == GI_TYPE_TAG_ARRAY) arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, - callable_info, arg_type, &free_array); + callable_info, &arg_type, &free_array); - value = _pygi_argument_to_object (arg, arg_type, transfer); + value = _pygi_argument_to_object (arg, &arg_type, transfer); if (free_array) g_array_free (arg->v_pointer, FALSE); - if (value == NULL) { - g_base_info_unref (arg_type); - g_base_info_unref (arg_info); + if (value == NULL) goto error; - } } PyTuple_SET_ITEM (*py_args, n_in_args, value); n_in_args++; - - g_base_info_unref (arg_type); } if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { @@ -375,7 +367,6 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, n_out_args++; } - g_base_info_unref (arg_info); } if (_PyTuple_Resize (py_args, n_in_args) == -1) @@ -399,37 +390,38 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, void *resp) { int n_args, i, i_py_retval, i_out_args; - GITypeInfo *return_type_info; + GITypeInfo return_type_info; GITypeTag return_type_tag; i_py_retval = 0; - return_type_info = g_callable_info_get_return_type (callable_info); - return_type_tag = g_type_info_get_tag (return_type_info); + g_callable_info_load_return_type (callable_info, &return_type_info); + return_type_tag = g_type_info_get_tag (&return_type_info); if (return_type_tag != GI_TYPE_TAG_VOID) { GITransfer transfer = g_callable_info_get_caller_owns (callable_info); if (PyTuple_Check (py_retval)) { PyObject *item = PyTuple_GET_ITEM (py_retval, 0); _pygi_closure_assign_pyobj_to_retval (resp, item, - return_type_info, transfer); + &return_type_info, transfer); } else { _pygi_closure_assign_pyobj_to_retval (resp, py_retval, - return_type_info, transfer); + &return_type_info, transfer); } i_py_retval++; } - g_base_info_unref (return_type_info); i_out_args = 0; n_args = g_callable_info_get_n_args (callable_info); - for (i = 1; i < n_args; i++) { - GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i); - GITypeInfo *type_info = g_arg_info_get_type (arg_info); - GIDirection direction = g_arg_info_get_direction (arg_info); + for (i = 0; i < n_args; i++) { + GIArgInfo arg_info; + g_callable_info_load_arg (callable_info, i, &arg_info); + GITypeInfo type_info; + g_arg_info_load_type (&arg_info, &type_info); + GIDirection direction = g_arg_info_get_direction (&arg_info); if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { - GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); + GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info); - if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ERROR) { + if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ERROR) { /* TODO: check if an exception has been set and convert it to a GError */ out_args[i_out_args].v_pointer = NULL; i_out_args++; @@ -439,10 +431,10 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, if (PyTuple_Check (py_retval)) { PyObject *item = PyTuple_GET_ITEM (py_retval, i_py_retval); _pygi_closure_assign_pyobj_to_out_argument ( - out_args[i_out_args].v_pointer, item, type_info, transfer); + out_args[i_out_args].v_pointer, item, &type_info, transfer); } else if (i_py_retval == 0) { _pygi_closure_assign_pyobj_to_out_argument ( - out_args[i_out_args].v_pointer, py_retval, type_info, + out_args[i_out_args].v_pointer, py_retval, &type_info, transfer); } else g_assert_not_reached(); @@ -450,8 +442,6 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, i_out_args++; i_py_retval++; } - g_base_info_unref (type_info); - g_base_info_unref (arg_info); } } diff --git a/gi/pygi-info.c b/gi/pygi-info.c index e726b2d..cd3d97d 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -1510,7 +1510,8 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self, g_base_info_unref (info); } else if (g_type_info_is_pointer (field_type_info) - && g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID) { + && (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID + || g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_UTF8)) { value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING); if (PyErr_Occurred()) { diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index dc14ca5..4ddfbb4 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -262,22 +262,30 @@ _pygi_marshal_from_py_int8 (PyGIInvokeState *state, PyObject *py_long; long long_; - if (!PyNumber_Check (py_arg)) { - PyErr_Format (PyExc_TypeError, "Must be number, not %s", - py_arg->ob_type->tp_name); - return FALSE; - } + if (PYGLIB_PyBytes_Check (py_arg)) { - py_long = PYGLIB_PyNumber_Long (py_arg); - if (!py_long) - return FALSE; + if (PYGLIB_PyBytes_Size (py_arg) != 1) { + PyErr_Format (PyExc_TypeError, "Must be a single character"); + return FALSE; + } - long_ = PYGLIB_PyLong_AsLong (py_long); - Py_DECREF (py_long); + long_ = (char)(PYGLIB_PyBytes_AsString (py_arg)[0]); + } else if (PyNumber_Check (py_arg)) { + py_long = PYGLIB_PyNumber_Long (py_arg); + if (!py_long) + return FALSE; - if (PyErr_Occurred ()) { - PyErr_Clear (); - PyErr_Format (PyExc_ValueError, "%ld not in range %d to %d", long_, -128, 127); + long_ = PYGLIB_PyLong_AsLong (py_long); + Py_DECREF (py_long); + + if (PyErr_Occurred ()) { + PyErr_Clear (); + PyErr_Format (PyExc_ValueError, "%ld not in range %d to %d", long_, -128, 127); + return FALSE; + } + } else { + PyErr_Format (PyExc_TypeError, "Must be number or single byte string, not %s", + py_arg->ob_type->tp_name); return FALSE; } @@ -1009,6 +1017,12 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state, if (from_py_cleanup) from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE); } + } else if (is_boxed && !item_iface_cache->arg_cache.is_pointer) { + /* The array elements are not expected to be pointers, but the + * elements obtained are boxed pointers themselves, so insert + * the pointed to data. + */ + g_array_insert_vals (array_, i, item.v_pointer, 1); } else { g_array_insert_val (array_, i, item); } diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c index 950895d..d5a0734 100644 --- a/gi/pygi-marshal-to-py.c +++ b/gi/pygi-marshal-to-py.c @@ -434,13 +434,14 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, item_arg.v_pointer = g_variant_ref_sink (g_array_index (array_, gpointer, i)); else item_arg.v_pointer = g_array_index (array_, gpointer, i); - } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) { + } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && !item_arg_cache->is_pointer) { + /* array elements are structs */ gpointer *_struct = g_malloc (item_size); memcpy (_struct, array_->data + i * item_size, item_size); item_arg.v_pointer = _struct; } else if (item_arg_cache->is_pointer) - /* this is the case for GAtom* arrays */ + /* array elements are pointers to values */ item_arg.v_pointer = g_array_index (array_, gpointer, i); else item_arg.v_pointer = array_->data + i * item_size; @@ -814,7 +815,9 @@ _pygi_marshal_to_py_interface_struct (PyGIInvokeState *state, arg->v_pointer); } else if (g_type_is_a (type, G_TYPE_BOXED)) { py_obj = _pygi_boxed_new ( (PyTypeObject *)iface_cache->py_type, arg->v_pointer, - arg_cache->transfer == GI_TRANSFER_EVERYTHING); + arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->is_caller_allocates); + if (arg_cache->is_caller_allocates) + ((PyGIBoxed *)py_obj)->slice_allocated = TRUE; } else if (g_type_is_a (type, G_TYPE_POINTER)) { if (iface_cache->py_type == NULL || !PyType_IsSubtype ( (PyTypeObject *)iface_cache->py_type, &PyGIStruct_Type)) { diff --git a/gi/pygi-property.c b/gi/pygi-property.c index 6079efc..2e32fea 100644 --- a/gi/pygi-property.c +++ b/gi/pygi-property.c @@ -217,7 +217,10 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec) break; case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: - arg.v_pointer = g_value_get_pointer (&value); + if (G_VALUE_HOLDS_BOXED(&value)) + arg.v_pointer = g_value_get_boxed (&value); + else + arg.v_pointer = g_value_get_pointer (&value); break; case GI_TYPE_TAG_ARRAY: { @@ -384,7 +387,10 @@ pygi_set_property_value_real (PyGObject *instance, g_value_set_boxed (&value, arg.v_pointer); break; case GI_TYPE_TAG_GLIST: - g_value_set_pointer (&value, arg.v_pointer); + if (G_VALUE_HOLDS_BOXED(&value)) + g_value_set_boxed (&value, arg.v_pointer); + else + g_value_set_pointer (&value, arg.v_pointer); break; case GI_TYPE_TAG_ARRAY: { |