1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * Copyright (C) 1998-2003 James Henstridge
5 * 2004-2008 Johan Dahlin
6 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
7 * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "pygi-private.h"
25 #include "pygi-error.h"
29 PyObject *PyGError = NULL;
30 static PyObject *exception_table = NULL;
33 * pygi_error_marshal_to_py:
34 * @error: a pointer to the GError.
36 * Checks to see if @error has been set. If @error has been set, then a
37 * GLib.GError Python exception object is returned (but not raised).
39 * Returns: a GLib.GError Python exception object, or NULL.
42 pygi_error_marshal_to_py (GError **error)
44 PyGILState_STATE state;
46 PyObject *exc_instance;
47 const char *domain = NULL;
49 g_return_val_if_fail(error != NULL, NULL);
54 state = pyglib_gil_state_ensure();
57 if (exception_table != NULL)
60 item = PyDict_GetItem(exception_table, PYGLIB_PyLong_FromLong((*error)->domain));
65 if ((*error)->domain) {
66 domain = g_quark_to_string ((*error)->domain);
69 exc_instance = PyObject_CallFunction (exc_type, "ssi",
74 pyglib_gil_state_release(state);
81 * @error: a pointer to the GError.
83 * Checks to see if the GError has been set. If the error has been
84 * set, then the glib.GError Python exception will be raised, and
87 * Returns: True if an error was set.
90 pygi_error_check (GError **error)
92 PyGILState_STATE state;
93 PyObject *exc_instance;
95 g_return_val_if_fail(error != NULL, FALSE);
99 state = pyglib_gil_state_ensure();
101 exc_instance = pygi_error_marshal_to_py (error);
102 PyErr_SetObject(PyGError, exc_instance);
103 Py_DECREF(exc_instance);
104 g_clear_error(error);
106 pyglib_gil_state_release(state);
112 * pygi_error_marshal_from_py:
113 * @pyerr: A Python exception instance.
114 * @error: a standard GLib GError ** output parameter
116 * Converts from a Python implemented GError into a GError.
118 * Returns: TRUE if the conversion was successful, otherwise a Python exception
119 * is set and FALSE is returned.
122 pygi_error_marshal_from_py (PyObject *pyerr, GError **error)
124 gboolean res = FALSE;
125 PyObject *py_message = NULL,
129 if (PyObject_IsInstance (pyerr, PyGError) != 1) {
130 PyErr_Format (PyExc_TypeError, "Must be GLib.Error, not %s",
131 pyerr->ob_type->tp_name);
135 py_message = PyObject_GetAttrString (pyerr, "message");
136 if (!py_message || !PYGLIB_PyUnicode_Check (py_message)) {
137 PyErr_SetString (PyExc_ValueError,
138 "GLib.Error instances must have a 'message' string attribute");
142 py_domain = PyObject_GetAttrString (pyerr, "domain");
143 if (!py_domain || !PYGLIB_PyUnicode_Check (py_domain)) {
144 PyErr_SetString (PyExc_ValueError,
145 "GLib.Error instances must have a 'domain' string attribute");
149 py_code = PyObject_GetAttrString (pyerr, "code");
150 if (!py_code || !PYGLIB_PyLong_Check (py_code)) {
151 PyErr_SetString (PyExc_ValueError,
152 "GLib.Error instances must have a 'code' int attribute");
157 g_set_error_literal (error,
158 g_quark_from_string (PYGLIB_PyUnicode_AsString (py_domain)),
159 PYGLIB_PyLong_AsLong (py_code),
160 PYGLIB_PyUnicode_AsString (py_message));
163 Py_XDECREF (py_message);
164 Py_XDECREF (py_code);
165 Py_XDECREF (py_domain);
170 * pygi_gerror_exception_check:
171 * @error: a standard GLib GError ** output parameter
173 * Checks to see if a GError exception has been raised, and if so
174 * translates the python exception to a standard GLib GError. If the
175 * raised exception is not a GError then PyErr_Print() is called.
177 * Returns: 0 if no exception has been raised, -1 if it is a
178 * valid glib.GError, -2 otherwise.
181 pygi_gerror_exception_check (GError **error)
184 PyObject *type, *value, *traceback;
185 PyErr_Fetch(&type, &value, &traceback);
188 PyErr_NormalizeException(&type, &value, &traceback);
190 PyErr_Restore(type, value, traceback);
195 !PyErr_GivenExceptionMatches(type,
196 (PyObject *) PyGError)) {
197 PyErr_Restore(type, value, traceback);
202 Py_XDECREF(traceback);
204 if (!pygi_error_marshal_from_py (value, error)) {
215 * pygi_register_exception_for_domain:
216 * @name: name of the exception
217 * @error_domain: error domain
219 * Registers a new GLib.Error exception subclass called #name for
220 * a specific #domain. This exception will be raised when a GError
221 * of the same domain is passed in to pygi_error_check().
223 * Returns: the new exception
226 pygi_register_exception_for_domain (gchar *name,
231 exception = PyErr_NewException(name, PyGError, NULL);
233 if (exception_table == NULL)
234 exception_table = PyDict_New();
236 PyDict_SetItem(exception_table,
237 PYGLIB_PyLong_FromLong(error_domain),
244 _pygi_marshal_from_py_gerror (PyGIInvokeState *state,
245 PyGICallableCache *callable_cache,
246 PyGIArgCache *arg_cache,
249 gpointer *cleanup_data)
251 GError *error = NULL;
252 if (pygi_error_marshal_from_py (py_arg, &error)) {
253 arg->v_pointer = error;
254 *cleanup_data = error;
263 _pygi_marshal_from_py_gerror_cleanup (PyGIInvokeState *state,
264 PyGIArgCache *arg_cache,
267 gboolean was_processed)
270 g_error_free ((GError *)data);
275 _pygi_marshal_to_py_gerror (PyGIInvokeState *state,
276 PyGICallableCache *callable_cache,
277 PyGIArgCache *arg_cache,
280 GError *error = arg->v_pointer;
281 PyObject *py_obj = NULL;
283 py_obj = pygi_error_marshal_to_py (&error);
285 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) {
286 g_error_free (error);
289 if (py_obj != NULL) {
297 pygi_arg_gerror_setup_from_info (PyGIArgCache *arg_cache,
298 GITypeInfo *type_info,
301 PyGIDirection direction)
303 if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction)) {
307 if (direction & PYGI_DIRECTION_FROM_PYTHON) {
308 arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
310 /* Assign cleanup function if we manage memory after call completion. */
311 if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
312 arg_cache->from_py_cleanup = _pygi_marshal_from_py_gerror_cleanup;
316 if (direction & PYGI_DIRECTION_TO_PYTHON) {
317 arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
318 arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT;
325 pygi_arg_gerror_new_from_info (GITypeInfo *type_info,
328 PyGIDirection direction)
330 gboolean res = FALSE;
331 PyGIArgCache *arg_cache = NULL;
333 arg_cache = pygi_arg_cache_alloc ();
334 if (arg_cache == NULL)
337 res = pygi_arg_gerror_setup_from_info (arg_cache,
345 pygi_arg_cache_free (arg_cache);
351 pygerror_from_gvalue (const GValue *value)
353 GError *gerror = (GError *) g_value_get_boxed (value);
354 PyObject *pyerr = pygi_error_marshal_to_py (&gerror);
363 pygerror_to_gvalue (GValue *value, PyObject *pyerror)
365 GError *gerror = NULL;
367 if (pygi_error_marshal_from_py (pyerror, &gerror)) {
368 g_value_take_boxed (value, gerror);
376 pygi_error_register_types (PyObject *module)
378 PyObject *error_module = PyImport_ImportModule ("gi._error");
383 /* Stash a reference to the Python implemented gi._error.GError. */
384 PyGError = PyObject_GetAttrString (error_module, "GError");
386 pyg_register_gtype_custom (G_TYPE_ERROR,
387 pygerror_from_gvalue,