Imported Upstream version 3.7.3
[platform/upstream/python-gobject.git] / gi / _glib / pyglib.c
1 /* -*- Mode: C; c-set-style: python; c-basic-offset: 4  -*-
2  * pyglib - Python bindings for GLib toolkit.
3  * Copyright (C) 1998-2003  James Henstridge
4  *               2004-2008  Johan Dahlin
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19  * USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include <config.h>
24 #endif
25
26 #include <Python.h>
27 #include <pythread.h>
28 #include "pyglib.h"
29 #include "pyglib-private.h"
30 #include "pygoptioncontext.h"
31 #include "pygoptiongroup.h"
32
33 static struct _PyGLib_Functions *_PyGLib_API;
34 static int pyglib_thread_state_tls_key;
35 static PyObject *exception_table = NULL;
36
37 void
38 pyglib_init(void)
39 {
40     PyObject *glib, *cobject;
41     
42     glib = PyImport_ImportModule("gi._glib");
43     if (!glib) {
44         if (PyErr_Occurred()) {
45             PyObject *type, *value, *traceback;
46             PyObject *py_orig_exc;
47             PyErr_Fetch(&type, &value, &traceback);
48             py_orig_exc = PyObject_Repr(value);
49             Py_XDECREF(type);
50             Py_XDECREF(value);
51             Py_XDECREF(traceback);
52             PyErr_Format(PyExc_ImportError,
53                          "could not import gi._glib (error was: %s)",
54                          PYGLIB_PyUnicode_AsString(py_orig_exc));
55             Py_DECREF(py_orig_exc);
56         } else {
57             PyErr_SetString(PyExc_ImportError,
58                             "could not import gi._glib (no error given)");
59         }
60         return;
61     }
62     
63     cobject = PyObject_GetAttrString(glib, "_PyGLib_API");
64     if (cobject && PYGLIB_CPointer_Check(cobject))
65         _PyGLib_API = (struct _PyGLib_Functions *) PYGLIB_CPointer_GetPointer(cobject, "gi._glib._PyGLib_API");
66     else {
67         PyErr_SetString(PyExc_ImportError,
68                         "could not import gi._glib (could not find _PyGLib_API object)");
69         Py_DECREF(glib);
70         return;
71     }
72 }
73
74 void
75 pyglib_init_internal(PyObject *api)
76 {
77     _PyGLib_API = (struct _PyGLib_Functions *) PYGLIB_CPointer_GetPointer(api, "gi._glib._PyGLib_API");
78 }
79
80 gboolean
81 pyglib_threads_enabled(void)
82 {
83     g_return_val_if_fail (_PyGLib_API != NULL, FALSE);
84
85     return _PyGLib_API->threads_enabled;
86 }
87
88 PyGILState_STATE
89 pyglib_gil_state_ensure(void)
90 {
91     g_return_val_if_fail (_PyGLib_API != NULL, PyGILState_LOCKED);
92
93     if (!_PyGLib_API->threads_enabled)
94         return PyGILState_LOCKED;
95
96 #ifdef DISABLE_THREADING
97     return PyGILState_LOCKED;
98 #else
99     return PyGILState_Ensure();
100 #endif
101 }
102
103 void
104 pyglib_gil_state_release(PyGILState_STATE state)
105 {
106     g_return_if_fail (_PyGLib_API != NULL);
107
108     if (!_PyGLib_API->threads_enabled)
109         return;
110
111 #ifndef DISABLE_THREADING
112     PyGILState_Release(state);
113 #endif
114 }
115
116 /**
117  * pyglib_enable_threads:
118  *
119  * Returns: TRUE if threading is enabled, FALSE otherwise.
120  *
121  */
122 #ifdef DISABLE_THREADING
123 gboolean
124 pyglib_enable_threads(void)
125 {
126     PyErr_SetString(PyExc_RuntimeError,
127                     "pyglib threading disabled at compile time");
128     return FALSE;
129 }
130
131 void
132 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback)
133 {
134     /* Ignore, threads cannot be enabled. */
135 }
136
137 #else
138
139 static GSList *thread_enabling_callbacks = NULL;
140
141 /* Enable threading; note that the GIL must be held by the current
142  * thread when this function is called
143  */
144 gboolean
145 pyglib_enable_threads(void)
146 {
147     GSList *callback;
148
149     g_return_val_if_fail (_PyGLib_API != NULL, FALSE);
150
151     if (_PyGLib_API->threads_enabled)
152         return TRUE;
153   
154     PyEval_InitThreads();
155     _PyGLib_API->threads_enabled = TRUE;
156     pyglib_thread_state_tls_key = PyThread_create_key();
157
158     for (callback = thread_enabling_callbacks; callback; callback = callback->next)
159         ((PyGLibThreadsEnabledFunc) callback->data) ();
160
161     g_slist_free(thread_enabling_callbacks);
162     return TRUE;
163 }
164
165 void
166 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback)
167 {
168     if (callback && !pyglib_threads_enabled())
169         thread_enabling_callbacks = g_slist_append(thread_enabling_callbacks, callback);
170 }
171 #endif
172
173 /**
174  * pyglib_block_threads:
175  *
176  */
177 void
178 pyglib_block_threads(void)
179 {
180     g_return_if_fail (_PyGLib_API != NULL);
181
182     if (_PyGLib_API->block_threads != NULL)
183         (* _PyGLib_API->block_threads)();
184 }
185
186 /**
187  * pyglib_unblock_threads:
188  *
189  */
190 void
191 pyglib_unblock_threads(void)
192 {
193     g_return_if_fail (_PyGLib_API != NULL);
194     if (_PyGLib_API->unblock_threads != NULL)
195         (* _PyGLib_API->unblock_threads)();
196 }
197
198 /**
199  * pyglib_set_thread_block_funcs:
200  *
201  * hooks to register handlers for getting GDK threads to cooperate
202  * with python threading
203  */
204 void
205 pyglib_set_thread_block_funcs (PyGLibThreadBlockFunc block_threads_func,
206                                PyGLibThreadBlockFunc unblock_threads_func)
207 {
208     g_return_if_fail (_PyGLib_API != NULL);
209
210     _PyGLib_API->block_threads = block_threads_func;
211     _PyGLib_API->unblock_threads = unblock_threads_func;
212 }
213
214 /**
215  * pyglib_error_marshal:
216  * @error: a pointer to the GError.
217  *
218  * Checks to see if @error has been set.  If @error has been set, then a
219  * GLib.GError Python exception object is returned (but not raised).
220  *
221  * Returns: a GLib.GError Python exception object, or NULL.
222  */
223 PyObject *
224 pyglib_error_marshal (GError **error)
225 {
226     PyGILState_STATE state;
227     PyObject *exc_type;
228     PyObject *exc_instance;
229     PyObject *d;
230
231     g_return_val_if_fail(error != NULL, NULL);
232
233     if (*error == NULL)
234         return NULL;
235
236     state = pyglib_gil_state_ensure();
237
238     exc_type = _PyGLib_API->gerror_exception;
239     if (exception_table != NULL)
240     {
241         PyObject *item;
242         item = PyDict_GetItem(exception_table, PYGLIB_PyLong_FromLong((*error)->domain));
243         if (item != NULL)
244             exc_type = item;
245     }
246
247     exc_instance = PyObject_CallFunction(exc_type, "z", (*error)->message);
248
249     if ((*error)->domain) {
250         PyObject_SetAttrString(exc_instance, "domain",
251                                d=PYGLIB_PyUnicode_FromString(g_quark_to_string((*error)->domain)));
252         Py_DECREF(d);
253     }
254     else
255         PyObject_SetAttrString(exc_instance, "domain", Py_None);
256
257     PyObject_SetAttrString(exc_instance, "code",
258                            d=PYGLIB_PyLong_FromLong((*error)->code));
259     Py_DECREF(d);
260
261     if ((*error)->message) {
262         PyObject_SetAttrString(exc_instance, "message",
263                                d=PYGLIB_PyUnicode_FromString((*error)->message));
264         Py_DECREF(d);
265     } else {
266         PyObject_SetAttrString(exc_instance, "message", Py_None);
267     }
268
269     pyglib_gil_state_release(state);
270     
271     return exc_instance;
272 }
273
274 /**
275  * pyglib_error_check:
276  * @error: a pointer to the GError.
277  *
278  * Checks to see if the GError has been set.  If the error has been
279  * set, then the glib.GError Python exception will be raised, and
280  * the GError cleared.
281  *
282  * Returns: True if an error was set.
283  */
284 gboolean
285 pyglib_error_check(GError **error)
286 {
287     PyGILState_STATE state;
288     PyObject *exc_instance;
289
290     g_return_val_if_fail(error != NULL, FALSE);
291     if (*error == NULL)
292         return FALSE;
293
294     state = pyglib_gil_state_ensure();
295
296     exc_instance = pyglib_error_marshal (error);
297     PyErr_SetObject(_PyGLib_API->gerror_exception, exc_instance);
298     Py_DECREF(exc_instance);
299     g_clear_error(error);
300     
301     pyglib_gil_state_release(state);
302     
303     return TRUE;
304 }
305
306 /**
307  * pyglib_gerror_exception_check:
308  * @error: a standard GLib GError ** output parameter
309  *
310  * Checks to see if a GError exception has been raised, and if so
311  * translates the python exception to a standard GLib GError.  If the
312  * raised exception is not a GError then PyErr_Print() is called.
313  *
314  * Returns: 0 if no exception has been raised, -1 if it is a
315  * valid glib.GError, -2 otherwise.
316  */
317 gboolean
318 pyglib_gerror_exception_check(GError **error)
319 {
320     PyObject *type, *value, *traceback;
321     PyObject *py_message, *py_domain, *py_code;
322     const char *bad_gerror_message;
323
324     PyErr_Fetch(&type, &value, &traceback);
325     if (type == NULL)
326         return 0;
327     PyErr_NormalizeException(&type, &value, &traceback);
328     if (value == NULL) {
329         PyErr_Restore(type, value, traceback);
330         PyErr_Print();
331         return -2;
332     }
333     if (!value ||
334         !PyErr_GivenExceptionMatches(type,
335                                      (PyObject *) _PyGLib_API->gerror_exception)) {
336         PyErr_Restore(type, value, traceback);
337         PyErr_Print();
338         return -2;
339     }
340     Py_DECREF(type);
341     Py_XDECREF(traceback);
342
343     py_message = PyObject_GetAttrString(value, "message");
344     if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) {
345         bad_gerror_message = "gi._glib.GError instances must have a 'message' string attribute";
346         Py_XDECREF(py_message);
347         goto bad_gerror;
348     }
349
350     py_domain = PyObject_GetAttrString(value, "domain");
351     if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) {
352         bad_gerror_message = "gi._glib.GError instances must have a 'domain' string attribute";
353         Py_DECREF(py_message);
354         Py_XDECREF(py_domain);
355         goto bad_gerror;
356     }
357
358     py_code = PyObject_GetAttrString(value, "code");
359     if (!py_code || !PYGLIB_PyLong_Check(py_code)) {
360         bad_gerror_message = "gi._glib.GError instances must have a 'code' int attribute";
361         Py_DECREF(py_message);
362         Py_DECREF(py_domain);
363         Py_XDECREF(py_code);
364         goto bad_gerror;
365     }
366
367     g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)),
368                 PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message));
369
370     Py_DECREF(py_message);
371     Py_DECREF(py_code);
372     Py_DECREF(py_domain);
373     return -1;
374
375 bad_gerror:
376     Py_DECREF(value);
377     g_set_error(error, g_quark_from_static_string("pyglib"), 0, "%s", bad_gerror_message);
378     PyErr_SetString(PyExc_ValueError, bad_gerror_message);
379     PyErr_Print();
380     return -2;
381 }
382
383 /**
384  * pyglib_register_exception_for_domain:
385  * @name: name of the exception
386  * @error_domain: error domain
387  *
388  * Registers a new glib.GError exception subclass called #name for
389  * a specific #domain. This exception will be raised when a GError
390  * of the same domain is passed in to pyglib_error_check().
391  *
392  * Returns: the new exception
393  */
394 PyObject *
395 pyglib_register_exception_for_domain(gchar *name,
396                                      gint error_domain)
397 {
398     PyObject *exception;
399
400     exception = PyErr_NewException(name, _PyGLib_API->gerror_exception, NULL);
401
402     if (exception_table == NULL)
403         exception_table = PyDict_New();
404
405     PyDict_SetItem(exception_table,
406                    PYGLIB_PyLong_FromLong(error_domain),
407                    exception);
408     
409     return exception;
410 }
411
412 /**
413  * pyg_option_group_transfer_group:
414  * @group: a GOptionGroup wrapper
415  *
416  * This is used to transfer the GOptionGroup to a GOptionContext. After this
417  * is called, the calle must handle the release of the GOptionGroup.
418  *
419  * When #NULL is returned, the GOptionGroup was already transfered.
420  *
421  * Returns: Either #NULL or the wrapped GOptionGroup.
422  */
423 GOptionGroup *
424 pyglib_option_group_transfer_group(PyObject *obj)
425 {
426     PyGOptionGroup *self = (PyGOptionGroup*)obj;
427     
428     if (self->is_in_context)
429         return NULL;
430
431     self->is_in_context = TRUE;
432     
433     /* Here we increase the reference count of the PyGOptionGroup, because now
434      * the GOptionContext holds an reference to us (it is the userdata passed
435      * to g_option_group_new().
436      *
437      * The GOptionGroup is freed with the GOptionContext.
438      *
439      * We set it here because if we would do this in the init method we would
440      * hold two references and the PyGOptionGroup would never be freed.
441      */
442     Py_INCREF(self);
443     
444     return self->group;
445 }
446
447 /**
448  * pyglib_option_group_new:
449  * @group: a GOptionGroup
450  *
451  * The returned GOptionGroup can't be used to set any hooks, translation domains
452  * or add entries. It's only intend is, to use for GOptionContext.add_group().
453  *
454  * Returns: the GOptionGroup wrapper.
455  */
456 PyObject * 
457 pyglib_option_group_new (GOptionGroup *group)
458 {
459     return _PyGLib_API->option_group_new(group);
460 }
461
462 /**
463  * pyglib_option_context_new:
464  * @context: a GOptionContext
465  *
466  * Returns: A new GOptionContext wrapper.
467  */
468 PyObject * 
469 pyglib_option_context_new (GOptionContext *context)
470 {
471     return _PyGLib_API->option_context_new(context);
472 }
473
474
475 /****** Private *****/
476
477 /**
478  * _pyglib_destroy_notify:
479  * @user_data: a PyObject pointer.
480  *
481  * A function that can be used as a GDestroyNotify callback that will
482  * call Py_DECREF on the data.
483  */
484 void
485 _pyglib_destroy_notify(gpointer user_data)
486 {
487     PyObject *obj = (PyObject *)user_data;
488     PyGILState_STATE state;
489
490     g_return_if_fail (_PyGLib_API != NULL);
491
492     state = pyglib_gil_state_ensure();
493     Py_DECREF(obj);
494     pyglib_gil_state_release(state);
495 }
496
497 gboolean
498 _pyglib_handler_marshal(gpointer user_data)
499 {
500     PyObject *tuple, *ret;
501     gboolean res;
502     PyGILState_STATE state;
503
504     g_return_val_if_fail(user_data != NULL, FALSE);
505
506     state = pyglib_gil_state_ensure();
507
508     tuple = (PyObject *)user_data;
509     ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0),
510                               PyTuple_GetItem(tuple, 1));
511     if (!ret) {
512         PyErr_Print();
513         res = FALSE;
514     } else {
515         res = PyObject_IsTrue(ret);
516         Py_DECREF(ret);
517     }
518     
519     pyglib_gil_state_release(state);
520
521     return res;
522 }
523
524 PyObject*
525 _pyglib_generic_ptr_richcompare(void* a, void *b, int op)
526 {
527     PyObject *res;
528
529     switch (op) {
530
531       case Py_EQ:
532         res = (a == b) ? Py_True : Py_False;
533         break;
534
535       case Py_NE:
536         res = (a != b) ? Py_True : Py_False;
537         break;
538
539       case Py_LT:
540         res = (a < b) ? Py_True : Py_False;
541         break;
542
543       case Py_LE:
544         res = (a <= b) ? Py_True : Py_False;
545         break;
546
547       case Py_GT:
548         res = (a > b) ? Py_True : Py_False;
549         break;
550
551       case Py_GE:
552         res = (a >= b) ? Py_True : Py_False;
553         break;
554
555       default:
556         res = Py_NotImplemented;
557         break;
558     }
559
560     Py_INCREF(res);
561     return res;
562 }
563
564 PyObject*
565 _pyglib_generic_long_richcompare(long a, long b, int op)
566 {
567     PyObject *res;
568
569     switch (op) {
570
571       case Py_EQ:
572         res = (a == b) ? Py_True : Py_False;
573         Py_INCREF(res);
574         break;
575
576       case Py_NE:
577         res = (a != b) ? Py_True : Py_False;
578         Py_INCREF(res);
579         break;
580
581
582       case Py_LT:
583         res = (a < b) ? Py_True : Py_False;
584         Py_INCREF(res);
585         break;
586
587       case Py_LE:
588         res = (a <= b) ? Py_True : Py_False;
589         Py_INCREF(res);
590         break;
591
592       case Py_GT:
593         res = (a > b) ? Py_True : Py_False;
594         Py_INCREF(res);
595         break;
596
597       case Py_GE:
598         res = (a >= b) ? Py_True : Py_False;
599         Py_INCREF(res);
600         break;
601
602       default:
603         res = Py_NotImplemented;
604         Py_INCREF(res);
605         break;
606     }
607
608     return res;
609 }
610