/** * pygi_error_marshal_from_py: * @pyerr: A Python exception instance. * @error: a standard GLib GError ** output parameter * * Converts from a Python implemented GError into a GError. * * Returns: TRUE if the conversion was successful, otherwise a Python exception * is set and FALSE is returned. */ gboolean pygi_error_marshal_from_py (PyObject *pyerr, GError **error) { gboolean res = FALSE; PyObject *py_message = NULL, *py_domain = NULL, *py_code = NULL; if (PyObject_IsInstance (pyerr, PyGError) != 1) { PyErr_Format (PyExc_TypeError, "Must be GLib.Error, not %s", pyerr->ob_type->tp_name); return FALSE; } py_message = PyObject_GetAttrString (pyerr, "message"); if (!py_message || !PYGLIB_PyUnicode_Check (py_message)) { PyErr_SetString (PyExc_ValueError, "GLib.Error instances must have a 'message' string attribute"); goto cleanup; } py_domain = PyObject_GetAttrString (pyerr, "domain"); if (!py_domain || !PYGLIB_PyUnicode_Check (py_domain)) { PyErr_SetString (PyExc_ValueError, "GLib.Error instances must have a 'domain' string attribute"); goto cleanup; } py_code = PyObject_GetAttrString (pyerr, "code"); if (!py_code || !PYGLIB_PyLong_Check (py_code)) { PyErr_SetString (PyExc_ValueError, "GLib.Error instances must have a 'code' int attribute"); goto cleanup; } res = TRUE; g_set_error_literal (error, g_quark_from_string (PYGLIB_PyUnicode_AsString (py_domain)), PYGLIB_PyLong_AsLong (py_code), PYGLIB_PyUnicode_AsString (py_message)); cleanup: Py_XDECREF (py_message); Py_XDECREF (py_code); Py_XDECREF (py_domain); return res; }
/** * pyg_enum_get_value: * @enum_type: the GType of the flag. * @obj: a Python object representing the flag value * @val: a pointer to the location to store the integer representation of the flag. * * Converts a Python object to the integer equivalent. The conversion * will depend on the type of the Python object. If the object is an * integer, it is passed through directly. If it is a string, it will * be treated as a full or short enum name as defined in the GType. * * Returns: 0 on success or -1 on failure */ gint pyg_enum_get_value(GType enum_type, PyObject *obj, gint *val) { GEnumClass *eclass = NULL; gint res = -1; g_return_val_if_fail(val != NULL, -1); if (!obj) { *val = 0; res = 0; } else if (PYGLIB_PyLong_Check(obj)) { *val = PYGLIB_PyLong_AsLong(obj); res = 0; if (PyObject_TypeCheck(obj, &PyGEnum_Type) && ((PyGEnum *) obj)->gtype != enum_type) { g_warning("expected enumeration type %s, but got %s instead", g_type_name(enum_type), g_type_name(((PyGEnum *) obj)->gtype)); } /* Dumb code duplication, but probably not worth it to have yet another macro. */ } else if (PyLong_Check(obj)) { *val = PyLong_AsLong(obj); res = 0; if (PyObject_TypeCheck(obj, &PyGEnum_Type) && ((PyGEnum *) obj)->gtype != enum_type) { g_warning("expected enumeration type %s, but got %s instead", g_type_name(enum_type), g_type_name(((PyGEnum *) obj)->gtype)); } } else if (PYGLIB_PyUnicode_Check(obj)) { GEnumValue *info; char *str = PYGLIB_PyUnicode_AsString(obj); if (enum_type != G_TYPE_NONE) eclass = G_ENUM_CLASS(g_type_class_ref(enum_type)); else { PyErr_SetString(PyExc_TypeError, "could not convert string to enum because there is no GType associated to look up the value"); res = -1; } info = g_enum_get_value_by_name(eclass, str); g_type_class_unref(eclass); if (!info) info = g_enum_get_value_by_nick(eclass, str); if (info) { *val = info->value; res = 0; } else { PyErr_SetString(PyExc_TypeError, "could not convert string"); res = -1; } } else { PyErr_SetString(PyExc_TypeError,"enum values must be strings or ints"); res = -1; } return res; }
void pyglib_init(void) { PyObject *glib, *cobject; glib = PyImport_ImportModule("gi._glib"); if (!glib) { if (PyErr_Occurred()) { PyObject *type, *value, *traceback; PyObject *py_orig_exc; PyErr_Fetch(&type, &value, &traceback); py_orig_exc = PyObject_Repr(value); Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(traceback); PyErr_Format(PyExc_ImportError, "could not import gi._glib (error was: %s)", PYGLIB_PyUnicode_AsString(py_orig_exc)); Py_DECREF(py_orig_exc); } else { PyErr_SetString(PyExc_ImportError, "could not import gi._glib (no error given)"); } return; } cobject = PyObject_GetAttrString(glib, "_PyGLib_API"); if (cobject && PYGLIB_CPointer_Check(cobject)) _PyGLib_API = (struct _PyGLib_Functions *) PYGLIB_CPointer_GetPointer(cobject, "gi._glib._PyGLib_API"); else { PyErr_SetString(PyExc_ImportError, "could not import gi._glib (could not find _PyGLib_API object)"); Py_DECREF(glib); return; } }
/** * pyg_flags_get_value: * @flag_type: the GType of the flag. * @obj: a Python object representing the flag value * @val: a pointer to the location to store the integer representation of the flag. * * Converts a Python object to the integer equivalent. The conversion * will depend on the type of the Python object. If the object is an * integer, it is passed through directly. If it is a string, it will * be treated as a full or short flag name as defined in the GType. * If it is a tuple, then the items are treated as strings and ORed * together. * * Returns: 0 on success or -1 on failure */ gint pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val) { GFlagsClass *fclass = NULL; gint res = -1; g_return_val_if_fail(val != NULL, -1); if (!obj) { *val = 0; res = 0; } else if (PYGLIB_PyLong_Check(obj)) { *val = PYGLIB_PyLong_AsUnsignedLong(obj); res = 0; } else if (PyLong_Check(obj)) { *val = PyLong_AsLongLong(obj); res = 0; } else if (PYGLIB_PyUnicode_Check(obj)) { GFlagsValue *info; char *str = PYGLIB_PyUnicode_AsString(obj); if (flag_type != G_TYPE_NONE) fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type)); else { PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value"); res = -1; } info = g_flags_get_value_by_name(fclass, str); g_type_class_unref(fclass); if (!info) info = g_flags_get_value_by_nick(fclass, str); if (info) { *val = info->value; res = 0; } else { PyErr_SetString(PyExc_TypeError, "could not convert string"); res = -1; } } else if (PyTuple_Check(obj)) { int i, len; len = PyTuple_Size(obj); *val = 0; res = 0; if (flag_type != G_TYPE_NONE) fclass = G_FLAGS_CLASS(g_type_class_ref(flag_type)); else { PyErr_SetString(PyExc_TypeError, "could not convert string to flag because there is no GType associated to look up the value"); res = -1; } for (i = 0; i < len; i++) { PyObject *item = PyTuple_GetItem(obj, i); char *str = PYGLIB_PyUnicode_AsString(item); GFlagsValue *info = g_flags_get_value_by_name(fclass, str); if (!info) info = g_flags_get_value_by_nick(fclass, str); if (info) { *val |= info->value; } else { PyErr_SetString(PyExc_TypeError, "could not convert string"); res = -1; break; } } g_type_class_unref(fclass); } else { PyErr_SetString(PyExc_TypeError, "flag values must be strings, ints, longs, or tuples"); res = -1; } return res; }
GType pyg_type_from_object_strict(PyObject *obj, gboolean strict) { PyObject *gtype; GType type; /* NULL check */ if (!obj) { PyErr_SetString(PyExc_TypeError, "can't get type from NULL object"); return 0; } /* map some standard types to primitive GTypes ... */ if (obj == Py_None) return G_TYPE_NONE; if (PyType_Check(obj)) { PyTypeObject *tp = (PyTypeObject *)obj; if (tp == &PYGLIB_PyLong_Type) return G_TYPE_INT; else if (tp == &PyBool_Type) return G_TYPE_BOOLEAN; else if (tp == &PyLong_Type) return G_TYPE_LONG; else if (tp == &PyFloat_Type) return G_TYPE_DOUBLE; else if (tp == &PYGLIB_PyUnicode_Type) return G_TYPE_STRING; else if (tp == &PyBaseObject_Type) return PY_TYPE_OBJECT; } if (Py_TYPE(obj) == &PyGTypeWrapper_Type) { return ((PyGTypeWrapper *)obj)->type; } /* handle strings */ if (PYGLIB_PyUnicode_Check(obj)) { gchar *name = PYGLIB_PyUnicode_AsString(obj); type = g_type_from_name(name); if (type != 0) { return type; } } /* finally, look for a __gtype__ attribute on the object */ gtype = PyObject_GetAttrString(obj, "__gtype__"); if (gtype) { if (Py_TYPE(gtype) == &PyGTypeWrapper_Type) { type = ((PyGTypeWrapper *)gtype)->type; Py_DECREF(gtype); return type; } Py_DECREF(gtype); } PyErr_Clear(); /* Some API like those that take GValues can hold a python object as * a pointer. This is potentially dangerous becuase everything is * passed in as a PyObject so we can't actually type check it. Only * fallback to PY_TYPE_OBJECT if strict checking is disabled */ if (!strict) return PY_TYPE_OBJECT; PyErr_SetString(PyExc_TypeError, "could not get typecode from object"); return 0; }
/** * pygi_gerror_exception_check: * @error: a standard GLib GError ** output parameter * * Checks to see if a GError exception has been raised, and if so * translates the python exception to a standard GLib GError. If the * raised exception is not a GError then PyErr_Print() is called. * * Returns: 0 if no exception has been raised, -1 if it is a * valid glib.GError, -2 otherwise. */ gboolean pygi_gerror_exception_check (GError **error) { PyObject *type, *value, *traceback; PyObject *py_message, *py_domain, *py_code; const char *bad_gerror_message; PyErr_Fetch(&type, &value, &traceback); if (type == NULL) return 0; PyErr_NormalizeException(&type, &value, &traceback); if (value == NULL) { PyErr_Restore(type, value, traceback); PyErr_Print(); return -2; } if (!value || !PyErr_GivenExceptionMatches(type, (PyObject *) PyGError)) { PyErr_Restore(type, value, traceback); PyErr_Print(); return -2; } Py_DECREF(type); Py_XDECREF(traceback); py_message = PyObject_GetAttrString(value, "message"); if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) { bad_gerror_message = "GLib.Error instances must have a 'message' string attribute"; Py_XDECREF(py_message); goto bad_gerror; } py_domain = PyObject_GetAttrString(value, "domain"); if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) { bad_gerror_message = "GLib.Error instances must have a 'domain' string attribute"; Py_DECREF(py_message); Py_XDECREF(py_domain); goto bad_gerror; } py_code = PyObject_GetAttrString(value, "code"); if (!py_code || !PYGLIB_PyLong_Check(py_code)) { bad_gerror_message = "GLib.Error instances must have a 'code' int attribute"; Py_DECREF(py_message); Py_DECREF(py_domain); Py_XDECREF(py_code); goto bad_gerror; } g_set_error(error, g_quark_from_string(PYGLIB_PyUnicode_AsString(py_domain)), PYGLIB_PyLong_AsLong(py_code), "%s", PYGLIB_PyUnicode_AsString(py_message)); Py_DECREF(py_message); Py_DECREF(py_code); Py_DECREF(py_domain); return -1; bad_gerror: Py_DECREF(value); g_set_error(error, g_quark_from_static_string("pygi"), 0, "%s", bad_gerror_message); PyErr_SetString(PyExc_ValueError, bad_gerror_message); PyErr_Print(); return -2; }