8e4a7934b75f737c38346b74510f4a4d8f6af54f
[platform/upstream/python-gobject.git] / gi / pygi-error.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * vim: tabstop=4 shiftwidth=4 expandtab
3  *
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>
8  *
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.
13  *
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.
18  *
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/>.
21  */
22
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"
29
30
31 PyObject *PyGError = NULL;
32
33 /**
34  * pygi_error_marshal_to_py:
35  * @error: a pointer to the GError.
36  *
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).
39  *
40  * Returns: a GLib.GError Python exception object, or NULL.
41  */
42 PyObject *
43 pygi_error_marshal_to_py (GError **error)
44 {
45     PyGILState_STATE state;
46     PyObject *exc_type;
47     PyObject *exc_instance;
48     const char *domain = NULL;
49
50     g_return_val_if_fail(error != NULL, NULL);
51
52     if (*error == NULL)
53         return NULL;
54
55     state = PyGILState_Ensure();
56
57     exc_type = PyGError;
58
59     if ((*error)->domain) {
60         domain = g_quark_to_string ((*error)->domain);
61     }
62
63     exc_instance = PyObject_CallFunction (exc_type, "ssi",
64                                           (*error)->message,
65                                           domain,
66                                           (*error)->code);
67
68     PyGILState_Release(state);
69
70     return exc_instance;
71 }
72
73 /**
74  * pygi_error_check:
75  * @error: a pointer to the GError.
76  *
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.
80  *
81  * Returns: True if an error was set.
82  */
83 gboolean
84 pygi_error_check (GError **error)
85 {
86     PyGILState_STATE state;
87     PyObject *exc_instance;
88
89     g_return_val_if_fail(error != NULL, FALSE);
90     if (*error == NULL)
91         return FALSE;
92
93     state = PyGILState_Ensure();
94
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);
99
100     PyGILState_Release(state);
101
102     return TRUE;
103 }
104
105 /**
106  * pygi_error_marshal_from_py:
107  * @pyerr: A Python exception instance.
108  * @error: a standard GLib GError ** output parameter
109  *
110  * Converts from a Python implemented GError into a GError.
111  *
112  * Returns: TRUE if the conversion was successful, otherwise a Python exception
113  *          is set and FALSE is returned.
114  */
115 gboolean
116 pygi_error_marshal_from_py (PyObject *pyerr, GError **error)
117 {
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;
125
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;
130     }
131
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;
137     }
138
139     if (!pygi_utf8_from_py (py_message, &message))
140         goto cleanup;
141
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;
147     }
148
149     if (!pygi_utf8_from_py (py_domain, &domain))
150         goto cleanup;
151
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;
157     }
158
159     if (!pygi_gint_from_py (py_code, &code))
160         goto cleanup;
161
162     res = TRUE;
163     g_set_error_literal (error,
164                          g_quark_from_string (domain),
165                          code,
166                          message);
167
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;
175 }
176
177 /**
178  * pygi_gerror_exception_check:
179  * @error: a standard GLib GError ** output parameter
180  *
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.
184  *
185  * Returns: 0 if no exception has been raised, -1 if it is a
186  * valid glib.GError, -2 otherwise.
187  */
188 gboolean
189 pygi_gerror_exception_check (GError **error)
190 {
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;
201     }
202     if (!value ||
203         !PyErr_GivenExceptionMatches(type,
204                                      (PyObject *) PyGError)) {
205         PyErr_Restore(type, value, traceback);
206         PyErr_Print();
207         return -2;
208     }
209     Py_DECREF(type);
210     Py_XDECREF(traceback);
211
212     if (!pygi_error_marshal_from_py (value, error)) {
213         PyErr_Print();
214         res = -2;
215     }
216
217     Py_DECREF(value);
218     return res;
219
220 }
221
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)
229 {
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;
237     }
238 }
239
240
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)
247 {
248     if (was_processed) {
249         g_error_free ((GError *)data);
250     }
251 }
252
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)
259 {
260     GError *error = arg->v_pointer;
261     PyObject *py_obj = NULL;
262
263     py_obj = pygi_error_marshal_to_py (&error);
264
265     if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) {
266         g_error_free (error);
267     }
268
269     if (py_obj != NULL) {
270         return py_obj;
271     } else {
272         Py_RETURN_NONE;
273     }
274 }
275
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)
282 {
283     if (!pygi_arg_base_setup (arg_cache, type_info, arg_info, transfer, direction)) {
284         return FALSE;
285     }
286
287     if (direction & PYGI_DIRECTION_FROM_PYTHON) {
288         arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
289
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;
293         }
294     }
295
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;
299     }
300
301     return TRUE;
302 }
303
304 PyGIArgCache *
305 pygi_arg_gerror_new_from_info (GITypeInfo   *type_info,
306                                GIArgInfo    *arg_info,
307                                GITransfer    transfer,
308                                PyGIDirection direction)
309 {
310     gboolean res = FALSE;
311     PyGIArgCache *arg_cache;
312
313     arg_cache = pygi_arg_cache_alloc ();
314
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;
325     }
326 }
327
328 static PyObject *
329 pygerror_from_gvalue (const GValue *value)
330 {
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;
337     }
338 }
339
340 static int
341 pygerror_to_gvalue (GValue *value, PyObject *pyerror)
342 {
343     GError *gerror = NULL;
344
345     if (pygi_error_marshal_from_py (pyerror, &gerror)) {
346         g_value_take_boxed (value, gerror);
347         return 0;
348     }
349
350     return -1;
351 }
352
353 /**
354  * Returns 0 on success, or -1 and sets an exception.
355  */
356 int
357 pygi_error_register_types (PyObject *module)
358 {
359     PyObject *error_module = pygi_import_module ("gi._error");
360     if (!error_module) {
361         return -1;
362     }
363
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;
369
370     pyg_register_gtype_custom (G_TYPE_ERROR,
371                                pygerror_from_gvalue,
372                                pygerror_to_gvalue);
373
374     return 0;
375 }
376