[pygobject] Check the type of the instance object
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Check the type of the instance object
- Date: Fri, 17 Sep 2010 10:50:00 +0000 (UTC)
commit 98f54f9d33996baeaa8c8c1240310f5396d03a1d
Author: John (J5) Palmieri <johnp redhat com>
Date: Tue Sep 14 14:10:49 2010 -0400
Check the type of the instance object
* in python 2 methods were added to classes as unbound methods and they would
check the instance type to make sure it was correct
* in python 3 for perfomance reasons methods are added to classes as simple
functions which treat the instance as an untyped argument so no checks
are made.
* this patch adds a type check so that the correct errors are thrown in
python 3 (python 2 this just adds another layer of redundancy should
something change with type checking in the future)
* since GI handles regular args and the instance arg slightly differently
we had to split out the interface checks in _pygi_g_type_info_check_object
in order to not duplicate code
https://bugzilla.gnome.org/show_bug.cgi?id=615872
gi/pygi-argument.c | 182 +++++++++++++++++++++++++++------------------------
gi/pygi-argument.h | 2 +
gi/pygi-invoke.c | 14 ++++
3 files changed, 112 insertions(+), 86 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 301a767..82d5855 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -161,6 +161,101 @@ _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
}
gint
+_pygi_g_type_interface_check_object (GIBaseInfo *info,
+ PyObject *object)
+{
+ gint retval = 1;
+ GIInfoType info_type;
+
+ info_type = g_base_info_get_type (info);
+ switch (info_type) {
+ case GI_INFO_TYPE_CALLBACK:
+ if (!PyCallable_Check (object)) {
+ PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
+ object->ob_type->tp_name);
+ retval = 0;
+ }
+ break;
+ case GI_INFO_TYPE_ENUM:
+ retval = 0;
+ if (PyNumber_Check (object)) {
+ PyObject *number = PYGLIB_PyNumber_Long (object);
+ if (number == NULL)
+ PyErr_Clear();
+ else {
+ glong value = PYGLIB_PyLong_AsLong (number);
+ int i;
+ for (i = 0; i < g_enum_info_get_n_values (info); i++) {
+ GIValueInfo *value_info = g_enum_info_get_value (info, i);
+ glong enum_value = g_value_info_get_value (value_info);
+ if (value == enum_value) {
+ retval = 1;
+ break;
+ }
+ }
+ }
+ }
+ if (retval < 1)
+ retval = _pygi_g_registered_type_info_check_object (
+ (GIRegisteredTypeInfo *) info, TRUE, object);
+ break;
+ case GI_INFO_TYPE_FLAGS:
+ if (PyNumber_Check (object)) {
+ /* Accept 0 as a valid flag value */
+ PyObject *number = PYGLIB_PyNumber_Long (object);
+ if (number == NULL)
+ PyErr_Clear();
+ else {
+ long value = PYGLIB_PyLong_AsLong (number);
+ if (value == 0)
+ break;
+ else if (value == -1)
+ PyErr_Clear();
+ }
+ }
+ retval = _pygi_g_registered_type_info_check_object (
+ (GIRegisteredTypeInfo *) info, TRUE, object);
+ break;
+ case GI_INFO_TYPE_STRUCT:
+ {
+ GType type;
+
+ /* 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 (!PyCallable_Check (object)) {
+ PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
+ object->ob_type->tp_name);
+ retval = 0;
+ }
+ break;
+ }
+
+ /* Fallback. */
+ }
+ case GI_INFO_TYPE_BOXED:
+ case GI_INFO_TYPE_INTERFACE:
+ case GI_INFO_TYPE_OBJECT:
+ case GI_INFO_TYPE_UNION:
+ retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return retval;
+}
+
+gint
_pygi_g_type_info_check_object (GITypeInfo *type_info,
PyObject *object,
gboolean allow_none)
@@ -346,96 +441,11 @@ check_number_release:
case GI_TYPE_TAG_INTERFACE:
{
GIBaseInfo *info;
- GIInfoType info_type;
info = g_type_info_get_interface (type_info);
g_assert (info != NULL);
- info_type = g_base_info_get_type (info);
-
- switch (info_type) {
- case GI_INFO_TYPE_CALLBACK:
- if (!PyCallable_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- case GI_INFO_TYPE_ENUM:
- retval = 0;
- if (PyNumber_Check (object)) {
- PyObject *number = PYGLIB_PyNumber_Long (object);
- if (number == NULL)
- PyErr_Clear();
- else {
- glong value = PYGLIB_PyLong_AsLong (number);
- int i;
- for (i = 0; i < g_enum_info_get_n_values (info); i++) {
- GIValueInfo *value_info = g_enum_info_get_value (info, i);
- glong enum_value = g_value_info_get_value (value_info);
- if (value == enum_value) {
- retval = 1;
- break;
- }
- }
- }
- }
- if (retval < 1)
- retval = _pygi_g_registered_type_info_check_object (
- (GIRegisteredTypeInfo *) info, TRUE, object);
- break;
- case GI_INFO_TYPE_FLAGS:
- if (PyNumber_Check (object)) {
- /* Accept 0 as a valid flag value */
- PyObject *number = PYGLIB_PyNumber_Long (object);
- if (number == NULL)
- PyErr_Clear();
- else {
- long value = PYGLIB_PyLong_AsLong (number);
- if (value == 0)
- break;
- else if (value == -1)
- PyErr_Clear();
- }
- }
- retval = _pygi_g_registered_type_info_check_object (
- (GIRegisteredTypeInfo *) info, TRUE, object);
- break;
- case GI_INFO_TYPE_STRUCT:
- {
- GType type;
-
- /* 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 (!PyCallable_Check (object)) {
- PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
- object->ob_type->tp_name);
- retval = 0;
- }
- break;
- }
-
- /* Fallback. */
- }
- case GI_INFO_TYPE_BOXED:
- case GI_INFO_TYPE_INTERFACE:
- case GI_INFO_TYPE_OBJECT:
- case GI_INFO_TYPE_UNION:
- retval = _pygi_g_registered_type_info_check_object ( (GIRegisteredTypeInfo *) info, TRUE, object);
- break;
- default:
- g_assert_not_reached();
- }
+ retval = _pygi_g_type_interface_check_object(info, object);
g_base_info_unref (info);
break;
diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h
index ee5d661..d932e8f 100644
--- a/gi/pygi-argument.h
+++ b/gi/pygi-argument.h
@@ -30,6 +30,8 @@ G_BEGIN_DECLS
/* Private */
+gint _pygi_g_type_interface_check_object (GIBaseInfo *info,
+ PyObject *object);
gint _pygi_g_type_info_check_object (GITypeInfo *type_info,
PyObject *object,
diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c
index 52fddcf..014164e 100644
--- a/gi/pygi-invoke.c
+++ b/gi/pygi-invoke.c
@@ -379,6 +379,7 @@ _prepare_invocation_state (struct invocation_state *state,
GIBaseInfo *container_info;
GIInfoType container_info_type;
PyObject *py_arg;
+ gint check_val;
container_info = g_base_info_get_container (function_info);
container_info_type = g_base_info_get_type (container_info);
@@ -386,6 +387,19 @@ _prepare_invocation_state (struct invocation_state *state,
g_assert (py_args_pos < state->n_py_args);
py_arg = PyTuple_GET_ITEM (py_args, py_args_pos);
+ /* In python 2 python takes care of checking the type
+ * of the self instance. In python 3 it does not
+ * so we have to check it here
+ */
+ check_val = _pygi_g_type_interface_check_object(container_info,
+ py_arg);
+ if (check_val < 0) {
+ return FALSE;
+ } else if (!check_val) {
+ _PyGI_ERROR_PREFIX ("instance: ");
+ return FALSE;
+ }
+
switch (container_info_type) {
case GI_INFO_TYPE_UNION:
case GI_INFO_TYPE_STRUCT:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]