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