[pygobject] [gi] make parameter check less strict when dealing with GValue params
- From: John Palmieri <johnp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] [gi] make parameter check less strict when dealing with GValue params
- Date: Mon, 25 Oct 2010 18:22:49 +0000 (UTC)
commit b483852904468722230903989e3451c7c6a24c0f
Author: John (J5) Palmieri <johnp redhat com>
Date: Tue Oct 12 12:18:33 2010 -0400
[gi] make parameter check less strict when dealing with GValue params
* Some GValue API can store a pointer to a python object for later
use but our parameter checking was too strict to allow this
* Add pyg_type_from_object_strict API which takes a strict boolean and
returns PY_TYPE_OBJECT if no other GType can be found
* Since we don't have enough info to genrically check GValue parameters
use the less strict type guessing when encountering a GValue param
* Other API stays the same and continues to do strict testing
https://bugzilla.gnome.org/show_bug.cgi?id=622987
gi/pygi-argument.c | 17 +++++---------
gobject/gobjectmodule.c | 4 +-
gobject/pygobject-private.h | 1 +
gobject/pygobject.h | 2 +
gobject/pygtype.c | 37 ++++++++++++++++++++++++++++---
tests/test_gi.py | 1 -
tests/test_overrides.py | 50 +++++++++++++++++++++++++++++++++++++++---
7 files changed, 90 insertions(+), 22 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index e3dd8c3..b768e9e 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -222,22 +222,17 @@ _pygi_g_type_interface_check_object (GIBaseInfo *info,
/* Handle special cases. */
type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *) info);
- if (g_type_is_a (type, G_TYPE_VALUE)) {
- GType object_type;
- object_type = pyg_type_from_object ( (PyObject *) object->ob_type);
- if (object_type == G_TYPE_INVALID) {
- PyErr_Format (PyExc_TypeError, "Must be of a known GType, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- } else if (g_type_is_a (type, G_TYPE_CLOSURE)) {
+ if (g_type_is_a (type, G_TYPE_CLOSURE)) {
if (!PyCallable_Check (object)) {
PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
object->ob_type->tp_name);
retval = 0;
}
break;
+ } else if (g_type_is_a (type, G_TYPE_VALUE)) {
+ /* we can't check g_values because we don't have
+ * enough context so just pass them through */
+ break;
}
/* Fallback. */
@@ -904,7 +899,7 @@ array_item_error:
GType object_type;
gint retval;
- object_type = pyg_type_from_object ( (PyObject *) object->ob_type);
+ object_type = pyg_type_from_object_strict ( (PyObject *) object->ob_type, FALSE);
if (object_type == G_TYPE_INVALID) {
PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
break;
diff --git a/gobject/gobjectmodule.c b/gobject/gobjectmodule.c
index f830251..a33ec24 100644
--- a/gobject/gobjectmodule.c
+++ b/gobject/gobjectmodule.c
@@ -2501,8 +2501,8 @@ struct _PyGObject_Functions pygobject_api_functions = {
pyg_type_register_custom_callback,
pyg_gerror_exception_check,
- pyglib_option_group_new
-
+ pyglib_option_group_new,
+ pyg_type_from_object_strict
};
/* for addon libraries ... */
diff --git a/gobject/pygobject-private.h b/gobject/pygobject-private.h
index 26cb5f2..ae4cfe1 100644
--- a/gobject/pygobject-private.h
+++ b/gobject/pygobject-private.h
@@ -98,6 +98,7 @@ gboolean pyg_gerror_exception_check(GError **error);
extern PyTypeObject PyGTypeWrapper_Type;
PyObject *pyg_type_wrapper_new (GType type);
+GType pyg_type_from_object_strict (PyObject *obj, gboolean strict);
GType pyg_type_from_object (PyObject *obj);
gint pyg_enum_get_value (GType enum_type, PyObject *obj, gint *val);
diff --git a/gobject/pygobject.h b/gobject/pygobject.h
index afbc665..21743ba 100644
--- a/gobject/pygobject.h
+++ b/gobject/pygobject.h
@@ -198,6 +198,7 @@ struct _PyGObject_Functions {
gpointer data);
gboolean (*gerror_exception_check) (GError **error);
PyObject* (*option_group_new) (GOptionGroup *group);
+ GType (* type_from_object_strict) (PyObject *obj, gboolean strict);
};
#ifndef _INSIDE_PYGOBJECT_
@@ -218,6 +219,7 @@ struct _PyGObject_Functions *_PyGObject_API;
#define pygobject_watch_closure (_PyGObject_API->object_watch_closure)
#define pyg_closure_set_exception_handler (_PyGObject_API->closure_set_exception_handler)
#define pyg_destroy_notify (_PyGObject_API->destroy_notify)
+#define pyg_type_from_object_strict (_PyGObject_API->type_from_object_strict)
#define pyg_type_from_object (_PyGObject_API->type_from_object)
#define pyg_type_wrapper_new (_PyGObject_API->type_wrapper_new)
#define pyg_enum_get_value (_PyGObject_API->enum_get_value)
diff --git a/gobject/pygtype.c b/gobject/pygtype.c
index 32f8640..a2ba55a 100644
--- a/gobject/pygtype.c
+++ b/gobject/pygtype.c
@@ -349,16 +349,20 @@ pyg_type_wrapper_new(GType type)
}
/**
- * pyg_type_from_object:
+ * pyg_type_from_object_strict:
* obj: a Python object
+ * strict: if set to TRUE, raises an exception if it can't perform the
+ * conversion
*
- * converts a python object to a GType. Raises an exception if it
- * can't perform the conversion.
+ * converts a python object to a GType. If strict is set, raises an
+ * exception if it can't perform the conversion, otherwise returns
+ * PY_TYPE_OBJECT.
*
* Returns: the corresponding GType, or 0 on error.
*/
+
GType
-pyg_type_from_object(PyObject *obj)
+pyg_type_from_object_strict(PyObject *obj, gboolean strict)
{
PyObject *gtype;
GType type;
@@ -416,10 +420,35 @@ pyg_type_from_object(PyObject *obj)
}
PyErr_Clear();
+
+ /* Some API like those that take GValues can hold a python object as
+ * a pointer. This is potentially dangerous becuase everything is
+ * passed in as a PyObject so we can't actually type check it. Only
+ * fallback to PY_TYPE_OBJECT if strict checking is disabled
+ */
+ if (!strict)
+ return PY_TYPE_OBJECT;
+
PyErr_SetString(PyExc_TypeError, "could not get typecode from object");
return 0;
}
+/**
+ * pyg_type_from_object:
+ * obj: a Python object
+ *
+ * converts a python object to a GType. Raises an exception if it
+ * can't perform the conversion.
+ *
+ * Returns: the corresponding GType, or 0 on error.
+ */
+GType
+pyg_type_from_object(PyObject *obj)
+{
+ /* Legacy call always defaults to strict type checking */
+ return pyg_type_from_object_strict(obj, TRUE);
+}
+
/* -------------- GValue marshalling ------------------ */
/**
diff --git a/tests/test_gi.py b/tests/test_gi.py
index fa9df70..cc1b7ae 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -915,7 +915,6 @@ class TestGValue(unittest.TestCase):
def test_gvalue_in(self):
GIMarshallingTests.gvalue_in(42)
- self.assertRaises(TypeError, GIMarshallingTests.gvalue_in, None)
def test_gvalue_out(self):
self.assertEquals(42, GIMarshallingTests.gvalue_out())
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index b86222b..33ec95e 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -272,12 +272,24 @@ class TestGtk(unittest.TestCase):
self.assertEquals(Gtk.TreeModel, overrides.Gtk.TreeModel)
self.assertEquals(Gtk.TreeViewColumn, overrides.Gtk.TreeViewColumn)
- tree_store = Gtk.TreeStore(int, 'gchararray', TestGtk.TestClass)
+ class TestPyObject(object):
+ pass
+
+ test_pyobj = TestPyObject()
+ test_pydict = {1:1, "2":2, "3":"3"}
+ test_pylist = [1,"2", "3"]
+ tree_store = Gtk.TreeStore(int, 'gchararray', TestGtk.TestClass, object, object, object)
+
parent = None
for i in range(100):
label = 'this is child #%d' % i
testobj = TestGtk.TestClass(self, i, label)
- parent = tree_store.append(parent, (i, label, testobj))
+ parent = tree_store.append(parent, (i,
+ label,
+ testobj,
+ test_pyobj,
+ test_pydict,
+ test_pylist))
# len gets the number of children in the root node
# since we kept appending to the previous node
@@ -293,18 +305,41 @@ class TestGtk(unittest.TestCase):
i = tree_store.get_value(treeiter, 0)
s = tree_store.get_value(treeiter, 1)
obj = tree_store.get_value(treeiter, 2)
+ i = tree_store.get_value(treeiter, 0)
+ s = tree_store.get_value(treeiter, 1)
+ obj = tree_store.get_value(treeiter, 2)
obj.check(i, s)
+
+ pyobj = tree_store.get_value(treeiter, 3)
+ self.assertEquals(pyobj, test_pyobj)
+ pydict = tree_store.get_value(treeiter, 4)
+ self.assertEquals(pydict, test_pydict)
+ pylist = tree_store.get_value(treeiter, 5)
+ self.assertEquals(pylist, test_pylist)
+
parent = treeiter
treeiter = tree_store.iter_children(parent)
self.assertEquals(i, 99)
def test_list_store(self):
- list_store = Gtk.ListStore(int, str, 'GIOverrideTreeAPITest')
+ class TestPyObject(object):
+ pass
+
+ test_pyobj = TestPyObject()
+ test_pydict = {1:1, "2":2, "3":"3"}
+ test_pylist = [1,"2", "3"]
+
+ list_store = Gtk.ListStore(int, str, 'GIOverrideTreeAPITest', object, object, object)
for i in range(100):
label = 'this is row #%d' % i
testobj = TestGtk.TestClass(self, i, label)
- parent = list_store.append((i, label, testobj))
+ parent = list_store.append((i,
+ label,
+ testobj,
+ test_pyobj,
+ test_pydict,
+ test_pylist))
self.assertEquals(len(list_store), 100)
@@ -317,6 +352,13 @@ class TestGtk(unittest.TestCase):
s = list_store.get_value(treeiter, 1)
obj = list_store.get_value(treeiter, 2)
obj.check(i, s)
+
+ pyobj = list_store.get_value(treeiter, 3)
+ self.assertEquals(pyobj, test_pyobj)
+ pydict = list_store.get_value(treeiter, 4)
+ self.assertEquals(pydict, test_pydict)
+ pylist = list_store.get_value(treeiter, 5)
+ self.assertEquals(pylist, test_pylist)
treeiter = list_store.iter_next(treeiter)
self.assertEquals(i, 99)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]