Remove a duplicate entry in gio.defs
[pygobject.git] / glib / pyglib.c
bloba1bdbb902d16ef7563a596fa7f4e556f8cd52e0b
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
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.
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.
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
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
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"
34 static struct _PyGLib_Functions *_PyGLib_API;
35 static int pyglib_thread_state_tls_key;
36 static PyObject *exception_table = NULL;
38 static PyTypeObject *_PyGMainContext_Type;
39 #define PyGMainContext_Type (*_PyGMainContext_Type)
41 static PyTypeObject *_PyGOptionGroup_Type;
42 #define PyGOptionGroup_Type (*_PyGOptionGroup_Type)
44 static PyTypeObject *_PyGOptionContext_Type;
45 #define PyGOptionContext_Type (*_PyGOptionContext_Type)
47 void
48 pyglib_init(void)
50 PyObject *glib, *cobject;
52 glib = PyImport_ImportModule("glib");
53 if (!glib) {
54 if (PyErr_Occurred()) {
55 PyObject *type, *value, *traceback;
56 PyObject *py_orig_exc;
57 PyErr_Fetch(&type, &value, &traceback);
58 py_orig_exc = PyObject_Repr(value);
59 Py_XDECREF(type);
60 Py_XDECREF(value);
61 Py_XDECREF(traceback);
62 PyErr_Format(PyExc_ImportError,
63 "could not import glib (error was: %s)",
64 _PyUnicode_AsString(py_orig_exc));
65 Py_DECREF(py_orig_exc);
66 } else {
67 PyErr_SetString(PyExc_ImportError,
68 "could not import glib (no error given)");
70 return;
73 cobject = PyObject_GetAttrString(glib, "_PyGLib_API");
74 if (cobject && PyCObject_Check(cobject))
75 _PyGLib_API = (struct _PyGLib_Functions *) PyCObject_AsVoidPtr(cobject);
76 else {
77 PyErr_SetString(PyExc_ImportError,
78 "could not import glib (could not find _PyGLib_API object)");
79 Py_DECREF(glib);
80 return;
83 _PyGMainContext_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "MainContext");
84 _PyGOptionGroup_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "OptionGroup");
85 _PyGOptionContext_Type = (PyTypeObject*)PyObject_GetAttrString(glib, "OptionContext");
88 void
89 pyglib_init_internal(PyObject *api)
91 _PyGLib_API = (struct _PyGLib_Functions *) PyCObject_AsVoidPtr(api);
94 gboolean
95 pyglib_threads_enabled(void)
97 g_return_val_if_fail (_PyGLib_API != NULL, FALSE);
99 return _PyGLib_API->threads_enabled;
102 PyGILState_STATE
103 pyglib_gil_state_ensure(void)
105 g_return_val_if_fail (_PyGLib_API != NULL, PyGILState_LOCKED);
107 if (!_PyGLib_API->threads_enabled)
108 return PyGILState_LOCKED;
110 return PyGILState_Ensure();
113 void
114 pyglib_gil_state_release(PyGILState_STATE state)
116 g_return_if_fail (_PyGLib_API != NULL);
118 if (!_PyGLib_API->threads_enabled)
119 return;
121 PyGILState_Release(state);
125 * pyglib_enable_threads:
127 * Returns: TRUE if threading is enabled, FALSE otherwise.
130 #ifdef DISABLE_THREADING
131 gboolean
132 pyglib_enable_threads(void)
134 PyErr_SetString(PyExc_RuntimeError,
135 "pyglib threading disabled at compile time");
136 return FALSE;
139 void
140 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback)
142 /* Ignore, threads cannot be enabled. */
145 #else
147 static GSList *thread_enabling_callbacks = NULL;
149 /* Enable threading; note that the GIL must be held by the current
150 * thread when this function is called
152 gboolean
153 pyglib_enable_threads(void)
155 GSList *callback;
157 g_return_val_if_fail (_PyGLib_API != NULL, FALSE);
159 if (_PyGLib_API->threads_enabled)
160 return TRUE;
162 PyEval_InitThreads();
163 if (!g_threads_got_initialized)
164 g_thread_init(NULL);
166 _PyGLib_API->threads_enabled = TRUE;
167 pyglib_thread_state_tls_key = PyThread_create_key();
169 for (callback = thread_enabling_callbacks; callback; callback = callback->next)
170 ((PyGLibThreadsEnabledFunc) callback->data) ();
172 g_slist_free(thread_enabling_callbacks);
173 return TRUE;
176 void
177 _pyglib_notify_on_enabling_threads(PyGLibThreadsEnabledFunc callback)
179 if (callback && !pyglib_threads_enabled())
180 thread_enabling_callbacks = g_slist_append(thread_enabling_callbacks, callback);
182 #endif
185 pyglib_gil_state_ensure_py23 (void)
187 return PyGILState_Ensure();
190 void
191 pyglib_gil_state_release_py23 (int flag)
193 PyGILState_Release(flag);
197 * pyglib_block_threads:
200 void
201 pyglib_block_threads(void)
203 g_return_if_fail (_PyGLib_API != NULL);
205 if (_PyGLib_API->block_threads != NULL)
206 (* _PyGLib_API->block_threads)();
210 * pyglib_unblock_threads:
213 void
214 pyglib_unblock_threads(void)
216 g_return_if_fail (_PyGLib_API != NULL);
217 if (_PyGLib_API->unblock_threads != NULL)
218 (* _PyGLib_API->unblock_threads)();
222 * pyglib_set_thread_block_funcs:
224 * hooks to register handlers for getting GDK threads to cooperate
225 * with python threading
227 void
228 pyglib_set_thread_block_funcs (PyGLibThreadBlockFunc block_threads_func,
229 PyGLibThreadBlockFunc unblock_threads_func)
231 g_return_if_fail (_PyGLib_API != NULL);
233 _PyGLib_API->block_threads = block_threads_func;
234 _PyGLib_API->unblock_threads = unblock_threads_func;
239 * pyglib_error_check:
240 * @error: a pointer to the GError.
242 * Checks to see if the GError has been set. If the error has been
243 * set, then the glib.GError Python exception will be raised, and
244 * the GError cleared.
246 * Returns: True if an error was set.
248 gboolean
249 pyglib_error_check(GError **error)
251 PyGILState_STATE state;
252 PyObject *exc_type;
253 PyObject *exc_instance;
254 PyObject *d;
256 g_return_val_if_fail(error != NULL, FALSE);
258 if (*error == NULL)
259 return FALSE;
261 state = pyglib_gil_state_ensure();
263 exc_type = _PyGLib_API->gerror_exception;
264 if (exception_table != NULL)
266 PyObject *item;
267 item = PyDict_GetItem(exception_table, _PyLong_FromLong((*error)->domain));
268 if (item != NULL)
269 exc_type = item;
272 exc_instance = PyObject_CallFunction(exc_type, "z", (*error)->message);
274 if ((*error)->domain) {
275 PyObject_SetAttrString(exc_instance, "domain",
276 d=_PyUnicode_FromString(g_quark_to_string((*error)->domain)));
277 Py_DECREF(d);
279 else
280 PyObject_SetAttrString(exc_instance, "domain", Py_None);
282 PyObject_SetAttrString(exc_instance, "code",
283 d=_PyLong_FromLong((*error)->code));
284 Py_DECREF(d);
286 if ((*error)->message) {
287 PyObject_SetAttrString(exc_instance, "message",
288 d=_PyUnicode_FromString((*error)->message));
289 Py_DECREF(d);
290 } else {
291 PyObject_SetAttrString(exc_instance, "message", Py_None);
294 PyErr_SetObject(_PyGLib_API->gerror_exception, exc_instance);
295 Py_DECREF(exc_instance);
296 g_clear_error(error);
298 pyglib_gil_state_release(state);
300 return TRUE;
304 * pyglib_gerror_exception_check:
305 * @error: a standard GLib GError ** output parameter
307 * Checks to see if a GError exception has been raised, and if so
308 * translates the python exception to a standard GLib GError. If the
309 * raised exception is not a GError then PyErr_Print() is called.
311 * Returns: 0 if no exception has been raised, -1 if it is a
312 * valid glib.GError, -2 otherwise.
314 gboolean
315 pyglib_gerror_exception_check(GError **error)
317 PyObject *type, *value, *traceback;
318 PyObject *py_message, *py_domain, *py_code;
319 const char *bad_gerror_message;
321 PyErr_Fetch(&type, &value, &traceback);
322 if (type == NULL)
323 return 0;
324 PyErr_NormalizeException(&type, &value, &traceback);
325 if (value == NULL) {
326 PyErr_Restore(type, value, traceback);
327 PyErr_Print();
328 return -2;
330 if (!value ||
331 !PyErr_GivenExceptionMatches(type,
332 (PyObject *) _PyGLib_API->gerror_exception)) {
333 PyErr_Restore(type, value, traceback);
334 PyErr_Print();
335 return -2;
337 Py_DECREF(type);
338 Py_XDECREF(traceback);
340 py_message = PyObject_GetAttrString(value, "message");
341 if (!py_message || !_PyUnicode_Check(py_message)) {
342 bad_gerror_message = "glib.GError instances must have a 'message' string attribute";
343 goto bad_gerror;
346 py_domain = PyObject_GetAttrString(value, "domain");
347 if (!py_domain || !_PyUnicode_Check(py_domain)) {
348 bad_gerror_message = "glib.GError instances must have a 'domain' string attribute";
349 Py_DECREF(py_message);
350 goto bad_gerror;
353 py_code = PyObject_GetAttrString(value, "code");
354 if (!py_code || !_PyLong_Check(py_code)) {
355 bad_gerror_message = "glib.GError instances must have a 'code' int attribute";
356 Py_DECREF(py_message);
357 Py_DECREF(py_domain);
358 goto bad_gerror;
361 g_set_error(error, g_quark_from_string(_PyUnicode_AsString(py_domain)),
362 _PyLong_AsLong(py_code), _PyUnicode_AsString(py_message));
364 Py_DECREF(py_message);
365 Py_DECREF(py_code);
366 Py_DECREF(py_domain);
367 return -1;
369 bad_gerror:
370 Py_DECREF(value);
371 g_set_error(error, g_quark_from_static_string("pyglib"), 0, bad_gerror_message);
372 PyErr_SetString(PyExc_ValueError, bad_gerror_message);
373 PyErr_Print();
374 return -2;
378 * pyglib_register_exception_for_domain:
379 * @name: name of the exception
380 * @error_domain: error domain
382 * Registers a new glib.GError exception subclass called #name for
383 * a specific #domain. This exception will be raised when a GError
384 * of the same domain is passed in to pyglib_error_check().
386 * Returns: the new exception
388 PyObject *
389 pyglib_register_exception_for_domain(gchar *name,
390 gint error_domain)
392 PyObject *exception;
394 exception = PyErr_NewException(name, _PyGLib_API->gerror_exception, NULL);
396 if (exception_table == NULL)
397 exception_table = PyDict_New();
399 PyDict_SetItem(exception_table,
400 _PyLong_FromLong(error_domain),
401 exception);
403 return exception;
407 * pyglib_main_context_new:
408 * @context: a GMainContext.
410 * Creates a wrapper for a GMainContext.
412 * Returns: the GMainContext wrapper.
414 PyObject *
415 pyglib_main_context_new(GMainContext *context)
417 PyGMainContext *self;
419 self = (PyGMainContext *)PyObject_NEW(PyGMainContext,
420 &PyGMainContext_Type);
421 if (self == NULL)
422 return NULL;
424 self->context = g_main_context_ref(context);
425 return (PyObject *)self;
429 * pyg_option_group_transfer_group:
430 * @group: a GOptionGroup wrapper
432 * This is used to transfer the GOptionGroup to a GOptionContext. After this
433 * is called, the calle must handle the release of the GOptionGroup.
435 * When #NULL is returned, the GOptionGroup was already transfered.
437 * Returns: Either #NULL or the wrapped GOptionGroup.
439 GOptionGroup *
440 pyglib_option_group_transfer_group(PyObject *obj)
442 PyGOptionGroup *self = (PyGOptionGroup*)obj;
444 if (self->is_in_context)
445 return NULL;
447 self->is_in_context = TRUE;
449 /* Here we increase the reference count of the PyGOptionGroup, because now
450 * the GOptionContext holds an reference to us (it is the userdata passed
451 * to g_option_group_new().
453 * The GOptionGroup is freed with the GOptionContext.
455 * We set it here because if we would do this in the init method we would
456 * hold two references and the PyGOptionGroup would never be freed.
458 Py_INCREF(self);
460 return self->group;
464 * pyglib_option_group_new:
465 * @group: a GOptionGroup
467 * The returned GOptionGroup can't be used to set any hooks, translation domains
468 * or add entries. It's only intend is, to use for GOptionContext.add_group().
470 * Returns: the GOptionGroup wrapper.
472 PyObject *
473 pyglib_option_group_new (GOptionGroup *group)
475 PyGOptionGroup *self;
477 self = (PyGOptionGroup *)PyObject_NEW(PyGOptionGroup,
478 &PyGOptionGroup_Type);
479 if (self == NULL)
480 return NULL;
482 self->group = group;
483 self->other_owner = TRUE;
484 self->is_in_context = FALSE;
486 return (PyObject *)self;
490 * pyglib_option_context_new:
491 * @context: a GOptionContext
493 * Returns: A new GOptionContext wrapper.
495 PyObject *
496 pyglib_option_context_new (GOptionContext *context)
498 PyGOptionContext *self;
500 self = (PyGOptionContext *)PyObject_NEW(PyGOptionContext,
501 &PyGOptionContext_Type);
502 if (self == NULL)
503 return NULL;
505 self->context = context;
506 self->main_group = NULL;
508 return (PyObject *)self;
512 * pyglib_option_context_new:
513 * @context: a GTimeVal struct
515 * Converts a GTimeVal struct to a python float
517 * Returns: a float representing the timeval
519 PyObject *
520 pyglib_float_from_timeval(GTimeVal timeval)
522 double ret;
523 ret = (double)timeval.tv_sec + (double)timeval.tv_usec * 0.000001;
524 return PyFloat_FromDouble(ret);
528 /****** Private *****/
531 * _pyglib_destroy_notify:
532 * @user_data: a PyObject pointer.
534 * A function that can be used as a GDestroyNotify callback that will
535 * call Py_DECREF on the data.
537 void
538 _pyglib_destroy_notify(gpointer user_data)
540 PyObject *obj = (PyObject *)user_data;
541 PyGILState_STATE state;
543 g_return_if_fail (_PyGLib_API != NULL);
545 state = pyglib_gil_state_ensure();
546 Py_DECREF(obj);
547 pyglib_gil_state_release(state);
550 gboolean
551 _pyglib_handler_marshal(gpointer user_data)
553 PyObject *tuple, *ret;
554 gboolean res;
555 PyGILState_STATE state;
557 g_return_val_if_fail(user_data != NULL, FALSE);
559 state = pyglib_gil_state_ensure();
561 tuple = (PyObject *)user_data;
562 ret = PyObject_CallObject(PyTuple_GetItem(tuple, 0),
563 PyTuple_GetItem(tuple, 1));
564 if (!ret) {
565 PyErr_Print();
566 res = FALSE;
567 } else {
568 res = PyObject_IsTrue(ret);
569 Py_DECREF(ret);
572 pyglib_gil_state_release(state);
574 return res;