diff options
author | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:44:38 +0900 |
---|---|---|
committer | DongHun Kwak <dh0128.kwak@samsung.com> | 2017-07-12 08:44:42 +0900 |
commit | 1676d45a3ca971e18e44c9d5cf2972b3c858a528 (patch) | |
tree | cc6cc17c74ca19a11e24be6255845b5646b9e95e /gi | |
parent | b34b5d5be117c5f7bf0bdc90f927dddada3b6118 (diff) | |
download | pygobject2-1676d45a3ca971e18e44c9d5cf2972b3c858a528.tar.gz pygobject2-1676d45a3ca971e18e44c9d5cf2972b3c858a528.tar.bz2 pygobject2-1676d45a3ca971e18e44c9d5cf2972b3c858a528.zip |
Imported Upstream version 3.19.91
Change-Id: I1db218cf8c13ceaf96e044a7bd2a6f9a285854b3
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi')
-rw-r--r-- | gi/overrides/GLib.py | 1 | ||||
-rw-r--r-- | gi/pygboxed.c | 8 | ||||
-rw-r--r-- | gi/pygi-error.c | 172 | ||||
-rw-r--r-- | gi/pygi-error.h | 7 | ||||
-rw-r--r-- | gi/pygi-struct.c | 32 | ||||
-rw-r--r-- | gi/pygi-struct.h | 5 | ||||
-rw-r--r-- | gi/pygi-value.c | 24 | ||||
-rw-r--r-- | gi/pygtype.c | 11 |
8 files changed, 202 insertions, 58 deletions
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py index 455ea84..c12b4d8 100644 --- a/gi/overrides/GLib.py +++ b/gi/overrides/GLib.py @@ -74,6 +74,7 @@ def gerror_new_literal(domain, message, code): # Monkey patch methods that rely on GLib introspection to be loaded at runtime. Error.__name__ = 'Error' Error.__module__ = 'GLib' +Error.__gtype__ = GLib.Error.__gtype__ Error.matches = gerror_matches Error.new_literal = staticmethod(gerror_new_literal) diff --git a/gi/pygboxed.c b/gi/pygboxed.c index 30ab423..cdb766c 100644 --- a/gi/pygboxed.c +++ b/gi/pygboxed.c @@ -189,7 +189,7 @@ pyg_register_boxed(PyObject *dict, const gchar *class_name, * wrapper will be freed when the wrapper is deallocated. If * @copy_boxed is True, then @own_ref must also be True. * - * Returns: the boxed wrapper. + * Returns: the boxed wrapper or %NULL and sets an exception. */ PyObject * pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed, @@ -218,6 +218,12 @@ pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed, if (!tp) tp = (PyTypeObject *)&PyGBoxed_Type; /* fallback */ + if (!PyType_IsSubtype (tp, &PyGBoxed_Type)) { + PyErr_Format (PyExc_RuntimeError, "%s isn't a GBoxed", tp->tp_name); + pyglib_gil_state_release (state); + return NULL; + } + self = (PyGBoxed *)tp->tp_alloc(tp, 0); if (self == NULL) { diff --git a/gi/pygi-error.c b/gi/pygi-error.c index b019a09..d86021c 100644 --- a/gi/pygi-error.c +++ b/gi/pygi-error.c @@ -23,13 +23,14 @@ #include "pyglib.h" #include "pygi-private.h" #include "pygi-error.h" +#include "pygtype.h" -static PyObject *PyGError = NULL; +PyObject *PyGError = NULL; static PyObject *exception_table = NULL; /** - * pygi_error_marshal: + * pygi_error_marshal_to_py: * @error: a pointer to the GError. * * Checks to see if @error has been set. If @error has been set, then a @@ -38,7 +39,7 @@ static PyObject *exception_table = NULL; * Returns: a GLib.GError Python exception object, or NULL. */ PyObject * -pygi_error_marshal (GError **error) +pygi_error_marshal_to_py (GError **error) { PyGILState_STATE state; PyObject *exc_type; @@ -97,7 +98,7 @@ pygi_error_check (GError **error) state = pyglib_gil_state_ensure(); - exc_instance = pygi_error_marshal (error); + exc_instance = pygi_error_marshal_to_py (error); PyErr_SetObject(PyGError, exc_instance); Py_DECREF(exc_instance); g_clear_error(error); @@ -108,6 +109,64 @@ pygi_error_check (GError **error) } /** + * pygi_error_marshal_from_py: + * @pyerr: A Python exception instance. + * @error: a standard GLib GError ** output parameter + * + * Converts from a Python implemented GError into a GError. + * + * Returns: TRUE if the conversion was successful, otherwise a Python exception + * is set and FALSE is returned. + */ +gboolean +pygi_error_marshal_from_py (PyObject *pyerr, GError **error) +{ + gboolean res = FALSE; + PyObject *py_message = NULL, + *py_domain = NULL, + *py_code = NULL; + + if (PyObject_IsInstance (pyerr, PyGError) != 1) { + PyErr_Format (PyExc_TypeError, "Must be GLib.Error, not %s", + pyerr->ob_type->tp_name); + return FALSE; + } + + py_message = PyObject_GetAttrString (pyerr, "message"); + if (!py_message || !PYGLIB_PyUnicode_Check (py_message)) { + PyErr_SetString (PyExc_ValueError, + "GLib.Error instances must have a 'message' string attribute"); + goto cleanup; + } + + py_domain = PyObject_GetAttrString (pyerr, "domain"); + if (!py_domain || !PYGLIB_PyUnicode_Check (py_domain)) { + PyErr_SetString (PyExc_ValueError, + "GLib.Error instances must have a 'domain' string attribute"); + goto cleanup; + } + + py_code = PyObject_GetAttrString (pyerr, "code"); + if (!py_code || !PYGLIB_PyLong_Check (py_code)) { + PyErr_SetString (PyExc_ValueError, + "GLib.Error instances must have a 'code' int attribute"); + goto cleanup; + } + + res = TRUE; + g_set_error_literal (error, + g_quark_from_string (PYGLIB_PyUnicode_AsString (py_domain)), + PYGLIB_PyLong_AsLong (py_code), + PYGLIB_PyUnicode_AsString (py_message)); + +cleanup: + Py_XDECREF (py_message); + Py_XDECREF (py_code); + Py_XDECREF (py_domain); + return res; +} + +/** * pygi_gerror_exception_check: * @error: a standard GLib GError ** output parameter * @@ -121,10 +180,8 @@ pygi_error_check (GError **error) gboolean pygi_gerror_exception_check (GError **error) { + int res = -1; PyObject *type, *value, *traceback; - PyObject *py_message, *py_domain, *py_code; - const char *bad_gerror_message; - PyErr_Fetch(&type, &value, &traceback); if (type == NULL) return 0; @@ -144,44 +201,14 @@ pygi_gerror_exception_check (GError **error) Py_DECREF(type); Py_XDECREF(traceback); - py_message = PyObject_GetAttrString(value, "message"); - if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) { - bad_gerror_message = "GLib.Error instances must have a 'message' string attribute"; - Py_XDECREF(py_message); - goto bad_gerror; - } - - py_domain = PyObject_GetAttrString(value, "domain"); - if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) { - bad_gerror_message = "GLib.Error instances must have a 'domain' string attribute"; - Py_DECREF(py_message); - Py_XDECREF(py_domain); - goto bad_gerror; - } - - py_code = PyObject_GetAttrString(value, "code"); - if (!py_code || !PYGLIB_PyLong_Check(py_code)) { - bad_gerror_message = "GLib.Error instances must have a 'code' int attribute"; - Py_DECREF(py_message); - Py_DECREF(py_domain); - Py_XDECREF(py_code); - goto bad_gerror; + if (!pygi_error_marshal_from_py (value, error)) { + PyErr_Print(); + res = -2; } - g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)), - PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message)); - - Py_DECREF(py_message); - Py_DECREF(py_code); - Py_DECREF(py_domain); - return -1; - -bad_gerror: Py_DECREF(value); - g_set_error(error, g_quark_from_static_string("pygi"), 0, "%s", bad_gerror_message); - PyErr_SetString(PyExc_ValueError, bad_gerror_message); - PyErr_Print(); - return -2; + return res; + } /** @@ -221,9 +248,27 @@ _pygi_marshal_from_py_gerror (PyGIInvokeState *state, GIArgument *arg, gpointer *cleanup_data) { - PyErr_Format (PyExc_NotImplementedError, - "Marshalling for GErrors is not implemented"); - return FALSE; + GError *error = NULL; + if (pygi_error_marshal_from_py (py_arg, &error)) { + arg->v_pointer = error; + *cleanup_data = error; + return TRUE; + } else { + return FALSE; + } +} + + +static void +_pygi_marshal_from_py_gerror_cleanup (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *py_arg, + gpointer data, + gboolean was_processed) +{ + if (was_processed) { + g_error_free ((GError *)data); + } } static PyObject * @@ -235,7 +280,7 @@ _pygi_marshal_to_py_gerror (PyGIInvokeState *state, GError *error = arg->v_pointer; PyObject *py_obj = NULL; - py_obj = pygi_error_marshal (&error); + py_obj = pygi_error_marshal_to_py (&error); if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) { g_error_free (error); @@ -261,7 +306,11 @@ pygi_arg_gerror_setup_from_info (PyGIArgCache *arg_cache, if (direction & PYGI_DIRECTION_FROM_PYTHON) { arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror; - arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD; + + /* Assign cleanup function if we manage memory after call completion. */ + if (arg_cache->transfer == GI_TRANSFER_NOTHING) { + arg_cache->from_py_cleanup = _pygi_marshal_from_py_gerror_cleanup; + } } if (direction & PYGI_DIRECTION_TO_PYTHON) { @@ -298,6 +347,31 @@ pygi_arg_gerror_new_from_info (GITypeInfo *type_info, } } +static PyObject * +pygerror_from_gvalue (const GValue *value) +{ + GError *gerror = (GError *) g_value_get_boxed (value); + PyObject *pyerr = pygi_error_marshal_to_py (&gerror); + if (pyerr == NULL) { + Py_RETURN_NONE; + } else { + return pyerr; + } +} + +static int +pygerror_to_gvalue (GValue *value, PyObject *pyerror) +{ + GError *gerror = NULL; + + if (pygi_error_marshal_from_py (pyerror, &gerror)) { + g_value_take_boxed (value, gerror); + return 0; + } + + return -1; +} + void pygi_error_register_types (PyObject *module) { @@ -308,5 +382,9 @@ pygi_error_register_types (PyObject *module) /* Stash a reference to the Python implemented gi._error.GError. */ PyGError = PyObject_GetAttrString (error_module, "GError"); + + pyg_register_gtype_custom (G_TYPE_ERROR, + pygerror_from_gvalue, + pygerror_to_gvalue); } diff --git a/gi/pygi-error.h b/gi/pygi-error.h index 72d2be0..e7cc05f 100644 --- a/gi/pygi-error.h +++ b/gi/pygi-error.h @@ -27,9 +27,14 @@ G_BEGIN_DECLS +extern PyObject *PyGError; + gboolean pygi_error_check (GError **error); -PyObject* pygi_error_marshal (GError **error); +PyObject* pygi_error_marshal_to_py (GError **error); + +gboolean pygi_error_marshal_from_py (PyObject *pyerr, + GError **error); gboolean pygi_gerror_exception_check (GError **error); diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c index d84eed5..c379a88 100644 --- a/gi/pygi-struct.c +++ b/gi/pygi-struct.c @@ -132,6 +132,38 @@ _struct_init (PyObject *self, PYGLIB_DEFINE_TYPE("gi.Struct", PyGIStruct_Type, PyGIStruct); + +PyObject * +_pygi_struct_new_from_g_type (GType g_type, + gpointer pointer, + gboolean free_on_dealloc) +{ + PyGIStruct *self; + PyTypeObject *type; + + type = (PyTypeObject *)pygi_type_import_by_g_type (g_type); + + if (!type) + type = (PyTypeObject *)&PyGIStruct_Type; /* fallback */ + + if (!PyType_IsSubtype (type, &PyGIStruct_Type)) { + PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Struct"); + return NULL; + } + + self = (PyGIStruct *) type->tp_alloc (type, 0); + if (self == NULL) { + return NULL; + } + + pyg_pointer_set_ptr (self, pointer); + ( (PyGPointer *) self)->gtype = g_type; + self->free_on_dealloc = free_on_dealloc; + + return (PyObject *) self; +} + + PyObject * _pygi_struct_new (PyTypeObject *type, gpointer pointer, diff --git a/gi/pygi-struct.h b/gi/pygi-struct.h index ab303e0..347c55f 100644 --- a/gi/pygi-struct.h +++ b/gi/pygi-struct.h @@ -31,6 +31,11 @@ _pygi_struct_new (PyTypeObject *type, gpointer pointer, gboolean free_on_dealloc); +PyObject * +_pygi_struct_new_from_g_type (GType g_type, + gpointer pointer, + gboolean free_on_dealloc); + void _pygi_struct_register_types (PyObject *m); G_END_DECLS diff --git a/gi/pygi-value.c b/gi/pygi-value.c index 2cf567d..9da87a5 100644 --- a/gi/pygi-value.c +++ b/gi/pygi-value.c @@ -18,6 +18,7 @@ #include <Python.h> #include "pygi-value.h" +#include "pygi-struct.h" #include "pyglib-python-compat.h" #include "pygobject-private.h" #include "pygtype.h" @@ -775,9 +776,10 @@ pygi_value_to_py_structured_type (const GValue *value, GType fundamental, gboole return pyg_value_as_pyobject(n_value, copy_boxed); } else if (holds_value_array) { GValueArray *array = (GValueArray *) g_value_get_boxed(value); - PyObject *ret = PyList_New(array->n_values); + Py_ssize_t n_values = array ? array->n_values : 0; + PyObject *ret = PyList_New(n_values); int i; - for (i = 0; i < array->n_values; ++i) + for (i = 0; i < n_values; ++i) PyList_SET_ITEM(ret, i, pyg_value_as_pyobject (array->values + i, copy_boxed)); return ret; @@ -809,7 +811,7 @@ pygi_value_to_py_structured_type (const GValue *value, GType fundamental, gboole Py_INCREF(Py_None); return Py_None; } - return pyg_boxed_new(G_TYPE_VARIANT, g_variant_ref(v), FALSE, FALSE); + return _pygi_struct_new_from_g_type (G_TYPE_VARIANT, g_variant_ref(v), FALSE); } default: { @@ -832,13 +834,13 @@ pygi_value_to_py_structured_type (const GValue *value, GType fundamental, gboole * This function creates/returns a Python wrapper object that * represents the GValue passed as an argument. * - * Returns: a PyObject representing the value. + * Returns: a PyObject representing the value or %NULL and sets an exception. */ PyObject * pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed) { - gchar buf[128]; PyObject *pyobj; + const gchar *type_name; GType fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)); /* HACK: special case char and uchar to return PyBytes intstead of integers @@ -863,10 +865,16 @@ pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed) return pyobj; } - g_snprintf(buf, sizeof(buf), "unknown type %s", - g_type_name(G_VALUE_TYPE(value))); - PyErr_SetString(PyExc_TypeError, buf); + if (!PyErr_Occurred ()) { + type_name = g_type_name (G_VALUE_TYPE (value)); + if (type_name == NULL) { + type_name = "(null)"; + } + PyErr_Format (PyExc_TypeError, "unknown type %s", type_name); + } + return NULL; + } diff --git a/gi/pygtype.c b/gi/pygtype.c index 985e969..a3784c8 100644 --- a/gi/pygtype.c +++ b/gi/pygtype.c @@ -704,7 +704,16 @@ pyg_closure_marshal(GClosure *closure, /* error condition */ if (!item) { - goto out; + if (!PyErr_Occurred ()) + PyErr_SetString (PyExc_TypeError, + "can't convert parameter to desired type"); + + if (pc->exception_handler) + pc->exception_handler (return_value, n_param_values, param_values); + else + PyErr_Print(); + + goto out; } PyTuple_SetItem(params, i, item); } |