tests: don't test for specific device labels
[pygobject.git] / gi / pygi-error.c
blob8e4a7934b75f737c38346b74510f4a4d8f6af54f
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/>.
23 #include <Python.h>
24 #include "pygi-error.h"
25 #include "pygi-type.h"
26 #include "pygi-python-compat.h"
27 #include "pygi-util.h"
28 #include "pygi-basictype.h"
31 PyObject *PyGError = NULL;
33 /**
34 * pygi_error_marshal_to_py:
35 * @error: a pointer to the GError.
37 * Checks to see if @error has been set. If @error has been set, then a
38 * GLib.GError Python exception object is returned (but not raised).
40 * Returns: a GLib.GError Python exception object, or NULL.
42 PyObject *
43 pygi_error_marshal_to_py (GError **error)
45 PyGILState_STATE state;
46 PyObject *exc_type;
47 PyObject *exc_instance;
48 const char *domain = NULL;
50 g_return_val_if_fail(error != NULL, NULL);
52 if (*error == NULL)
53 return NULL;
55 state = PyGILState_Ensure();
57 exc_type = PyGError;
59 if ((*error)->domain) {
60 domain = g_quark_to_string ((*error)->domain);
63 exc_instance = PyObject_CallFunction (exc_type, "ssi",
64 (*error)->message,
65 domain,
66 (*error)->code);
68 PyGILState_Release(state);
70 return exc_instance;
73 /**
74 * pygi_error_check:
75 * @error: a pointer to the GError.
77 * Checks to see if the GError has been set. If the error has been
78 * set, then the glib.GError Python exception will be raised, and
79 * the GError cleared.
81 * Returns: True if an error was set.
83 gboolean
84 pygi_error_check (GError **error)
86 PyGILState_STATE state;
87 PyObject *exc_instance;
89 g_return_val_if_fail(error != NULL, FALSE);
90 if (*error == NULL)
91 return FALSE;
93 state = PyGILState_Ensure();
95 exc_instance = pygi_error_marshal_to_py (error);
96 PyErr_SetObject(PyGError, exc_instance);
97 Py_DECREF(exc_instance);
98 g_clear_error(error);
100 PyGILState_Release(state);
102 return TRUE;
106 * pygi_error_marshal_from_py:
107 * @pyerr: A Python exception instance.
108 * @error: a standard GLib GError ** output parameter
110 * Converts from a Python implemented GError into a GError.
112 * Returns: TRUE if the conversion was successful, otherwise a Python exception
113 * is set and FALSE is returned.
115 gboolean
116 pygi_error_marshal_from_py (PyObject *pyerr, GError **error)
118 gint code;
119 gchar *message = NULL;
120 gchar *domain = NULL;
121 gboolean res = FALSE;
122 PyObject *py_message = NULL,
123 *py_domain = NULL,
124 *py_code = NULL;
126 if (PyObject_IsInstance (pyerr, PyGError) != 1) {
127 PyErr_Format (PyExc_TypeError, "Must be GLib.Error, not %s",
128 Py_TYPE (pyerr)->tp_name);
129 return FALSE;
132 py_message = PyObject_GetAttrString (pyerr, "message");
133 if (!py_message) {
134 PyErr_SetString (PyExc_ValueError,
135 "GLib.Error instances must have a 'message' string attribute");
136 goto cleanup;
139 if (!pygi_utf8_from_py (py_message, &message))
140 goto cleanup;
142 py_domain = PyObject_GetAttrString (pyerr, "domain");
143 if (!py_domain) {
144 PyErr_SetString (PyExc_ValueError,
145 "GLib.Error instances must have a 'domain' string attribute");
146 goto cleanup;
149 if (!pygi_utf8_from_py (py_domain, &domain))
150 goto cleanup;
152 py_code = PyObject_GetAttrString (pyerr, "code");
153 if (!py_code) {
154 PyErr_SetString (PyExc_ValueError,
155 "GLib.Error instances must have a 'code' int attribute");
156 goto cleanup;
159 if (!pygi_gint_from_py (py_code, &code))
160 goto cleanup;
162 res = TRUE;
163 g_set_error_literal (error,
164 g_quark_from_string (domain),
165 code,
166 message);
168 cleanup:
169 g_free (message);
170 g_free (domain);
171 Py_XDECREF (py_message);
172 Py_XDECREF (py_code);
173 Py_XDECREF (py_domain);
174 return res;
178 * pygi_gerror_exception_check:
179 * @error: a standard GLib GError ** output parameter
181 * Checks to see if a GError exception has been raised, and if so
182 * translates the python exception to a standard GLib GError. If the
183 * raised exception is not a GError then PyErr_Print() is called.
185 * Returns: 0 if no exception has been raised, -1 if it is a
186 * valid glib.GError, -2 otherwise.
188 gboolean
189 pygi_gerror_exception_check (GError **error)
191 int res = -1;
192 PyObject *type, *value, *traceback;
193 PyErr_Fetch(&type, &value, &traceback);
194 if (type == NULL)
195 return 0;
196 PyErr_NormalizeException(&type, &value, &traceback);
197 if (value == NULL) {
198 PyErr_Restore(type, value, traceback);
199 PyErr_Print();
200 return -2;
202 if (!value ||
203 !PyErr_GivenExceptionMatches(type,
204 (PyObject *) PyGError)) {
205 PyErr_Restore(type, value, traceback);
206 PyErr_Print();
207 return -2;
209 Py_DECREF(type);
210 Py_XDECREF(traceback);
212 if (!pygi_error_marshal_from_py (value, error)) {
213 PyErr_Print();
214 res = -2;
217 Py_DECREF(value);
218 return res;
222 static gboolean
223 _pygi_marshal_from_py_gerror (PyGIInvokeState *state,
224 PyGICallableCache *callable_cache,
225 PyGIArgCache *arg_cache,
226 PyObject *py_arg,
227 GIArgument *arg,
228 gpointer *cleanup_data)
230 GError *error = NULL;
231 if (pygi_error_marshal_from_py (py_arg, &error)) {
232 arg->v_pointer = error;
233 *cleanup_data = error;
234 return TRUE;
235 } else {
236 return FALSE;
241 static void
242 _pygi_marshal_from_py_gerror_cleanup (PyGIInvokeState *state,
243 PyGIArgCache *arg_cache,
244 PyObject *py_arg,
245 gpointer data,
246 gboolean was_processed)
248 if (was_processed) {
249 g_error_free ((GError *)data);
253 static PyObject *
254 _pygi_marshal_to_py_gerror (PyGIInvokeState *state,
255 PyGICallableCache *callable_cache,
256 PyGIArgCache *arg_cache,
257 GIArgument *arg,
258 gpointer *cleanup_data)
260 GError *error = arg->v_pointer;
261 PyObject *py_obj = NULL;
263 py_obj = pygi_error_marshal_to_py (&error);
265 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) {
266 g_error_free (error);
269 if (py_obj != NULL) {
270 return py_obj;
271 } else {
272 Py_RETURN_NONE;
276 static gboolean
277 pygi_arg_gerror_setup_from_info (PyGIArgCache *arg_cache,
278 GITypeInfo *type_info,
279 GIArgInfo *arg_info,
280 GITransfer transfer,
281 PyGIDirection direction)
283 if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction)) {
284 return FALSE;
287 if (direction & PYGI_DIRECTION_FROM_PYTHON) {
288 arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
290 /* Assign cleanup function if we manage memory after call completion. */
291 if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
292 arg_cache->from_py_cleanup = _pygi_marshal_from_py_gerror_cleanup;
296 if (direction & PYGI_DIRECTION_TO_PYTHON) {
297 arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
298 arg_cache->meta_type = PYGI_META_ARG_TYPE_PARENT;
301 return TRUE;
304 PyGIArgCache *
305 pygi_arg_gerror_new_from_info (GITypeInfo *type_info,
306 GIArgInfo *arg_info,
307 GITransfer transfer,
308 PyGIDirection direction)
310 gboolean res = FALSE;
311 PyGIArgCache *arg_cache;
313 arg_cache = pygi_arg_cache_alloc ();
315 res = pygi_arg_gerror_setup_from_info (arg_cache,
316 type_info,
317 arg_info,
318 transfer,
319 direction);
320 if (res) {
321 return arg_cache;
322 } else {
323 pygi_arg_cache_free (arg_cache);
324 return NULL;
328 static PyObject *
329 pygerror_from_gvalue (const GValue *value)
331 GError *gerror = (GError *) g_value_get_boxed (value);
332 PyObject *pyerr = pygi_error_marshal_to_py (&gerror);
333 if (pyerr == NULL) {
334 Py_RETURN_NONE;
335 } else {
336 return pyerr;
340 static int
341 pygerror_to_gvalue (GValue *value, PyObject *pyerror)
343 GError *gerror = NULL;
345 if (pygi_error_marshal_from_py (pyerror, &gerror)) {
346 g_value_take_boxed (value, gerror);
347 return 0;
350 return -1;
354 * Returns 0 on success, or -1 and sets an exception.
357 pygi_error_register_types (PyObject *module)
359 PyObject *error_module = pygi_import_module ("gi._error");
360 if (!error_module) {
361 return -1;
364 /* Stash a reference to the Python implemented gi._error.GError. */
365 PyGError = PyObject_GetAttrString (error_module, "GError");
366 Py_DECREF (error_module);
367 if (PyGError == NULL)
368 return -1;
370 pyg_register_gtype_custom (G_TYPE_ERROR,
371 pygerror_from_gvalue,
372 pygerror_to_gvalue);
374 return 0;