summaryrefslogtreecommitdiff
path: root/gi
diff options
context:
space:
mode:
Diffstat (limited to 'gi')
-rw-r--r--gi/_gobject/propertyhelper.py29
-rw-r--r--gi/_gobject/pygenum.c6
-rw-r--r--gi/_gobject/pygobject.c8
-rw-r--r--gi/_gobject/pygtype.c82
-rw-r--r--gi/gimodule.c80
-rw-r--r--gi/overrides/GObject.py127
-rw-r--r--gi/overrides/Gtk.py119
-rw-r--r--gi/pygi-argument.c20
-rw-r--r--gi/pygi-cache.c1
-rw-r--r--gi/pygi-closure.c90
-rw-r--r--gi/pygi-info.c3
-rw-r--r--gi/pygi-marshal-from-py.c40
-rw-r--r--gi/pygi-marshal-to-py.c9
-rw-r--r--gi/pygi-property.c10
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(&params[i+1])), i);
+ G_VALUE_TYPE_NAME(&params[i+1]), i);
PyErr_SetString(PyExc_TypeError, buf);
- for (i = 0; i < query.n_params + 1; i++)
- g_value_unset(&params[i]);
+ for (j = 0; j <= i; j++)
+ g_value_unset(&params[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:
{