From dca2aa52fd0a1cc95eb486ce00f330884a14dc7e Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 20 Apr 2010 17:03:38 -0400 Subject: Manually type-check the instance variable during method invocations on Python 3 --- gi/pygi-info.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/gi/pygi-info.c b/gi/pygi-info.c index 6f89e51..454b06c 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -710,6 +710,65 @@ _wrap_g_function_info_invoke (PyGIBaseInfo *self, g_assert(py_args_pos == n_py_args); } +#if PY_MAJOR_VERSION >= 3 + if (is_method) { + /* + In Python 2, type-checking of the instance is done for us by + Objects/classobject.c:instancemethod_call, which will raise + a TypeError of the form + "unbound method %s%s must be called with " + "%s instance as first argument " + "(got %s%s instead)", + + In Python 3, it appears that this checking isn't done for us, + so we do it here: + */ + GIBaseInfo *container_info; + PyObject *py_expected_type; + PyObject *py_arg; + int is_instance; + + container_info = g_base_info_get_container(self->info); + py_expected_type = _pygi_type_import_by_gi_info (container_info); + + if (py_expected_type == NULL) { + goto out; + } + + py_arg = PyTuple_GetItem(py_args, 0); + if (py_arg == NULL) { + Py_DECREF(py_expected_type); + goto out; + } + + is_instance = PyObject_IsInstance(py_arg, py_expected_type); + if (is_instance == -1) { + Py_DECREF(py_expected_type); + goto out; + } + + if (is_instance == 0) { + gchar *type_name_expected; + + type_name_expected = _pygi_g_base_info_get_fullname(container_info); + + PyErr_Format(PyExc_TypeError, + "method must be called with " + "%s instance as first argument " + "(got %s instead)", + type_name_expected, + py_arg->ob_type->tp_name + ); + + g_free(type_name_expected); + + Py_DECREF(py_expected_type); + goto out; + } + Py_DECREF(py_expected_type); + } +#endif + args = g_newa(GArgument *, n_args); in_args = g_newa(GArgument, n_in_args); out_args = g_newa(GArgument, n_out_args); -- cgit