/** * 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; }
/** * 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; }
/** * pyg_value_from_pyobject: * @value: the GValue object to store the converted value in. * @obj: the Python object to convert. * * This function converts a Python object and stores the result in a * GValue. The GValue must be initialised in advance with * g_value_init(). If the Python object can't be converted to the * type of the GValue, then an error is returned. * * Returns: 0 on success, -1 on error. */ int pyg_value_from_pyobject(GValue *value, PyObject *obj) { PyObject *tmp; switch (G_TYPE_FUNDAMENTAL(G_VALUE_TYPE(value))) { case G_TYPE_INTERFACE: /* we only handle interface types that have a GObject prereq */ if (g_type_is_a(G_VALUE_TYPE(value), G_TYPE_OBJECT)) { if (obj == Py_None) g_value_set_object(value, NULL); else { if (!PyObject_TypeCheck(obj, &PyGObject_Type)) { return -1; } if (!G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj), G_VALUE_TYPE(value))) { return -1; } g_value_set_object(value, pygobject_get(obj)); } } else { return -1; } break; case G_TYPE_CHAR: #if PY_VERSION_HEX < 0x03000000 if (PyString_Check(obj)) { g_value_set_char(value, PyString_AsString(obj)[0]); } else #endif if (PyUnicode_Check(obj)) { tmp = PyUnicode_AsUTF8String(obj); g_value_set_char(value, PYGLIB_PyBytes_AsString(tmp)[0]); Py_DECREF(tmp); } else { PyErr_Clear(); return -1; } break; case G_TYPE_UCHAR: if (PYGLIB_PyLong_Check(obj)) { glong val; val = PYGLIB_PyLong_AsLong(obj); if (val >= 0 && val <= 255) g_value_set_uchar(value, (guchar)PYGLIB_PyLong_AsLong (obj)); else return -1; #if PY_VERSION_HEX < 0x03000000 } else if (PyString_Check(obj)) { g_value_set_uchar(value, PyString_AsString(obj)[0]); #endif } else if (PyUnicode_Check(obj)) { tmp = PyUnicode_AsUTF8String(obj); g_value_set_uchar(value, PYGLIB_PyBytes_AsString(tmp)[0]); Py_DECREF(tmp); } else { PyErr_Clear(); return -1; } break; case G_TYPE_BOOLEAN: g_value_set_boolean(value, PyObject_IsTrue(obj)); break; case G_TYPE_INT: g_value_set_int(value, PYGLIB_PyLong_AsLong(obj)); break; case G_TYPE_UINT: { if (PYGLIB_PyLong_Check(obj)) { glong val; val = PYGLIB_PyLong_AsLong(obj); if (val >= 0 && val <= G_MAXUINT) g_value_set_uint(value, (guint)val); else return -1; } else { g_value_set_uint(value, PyLong_AsUnsignedLong(obj)); } } break; case G_TYPE_LONG: g_value_set_long(value, PYGLIB_PyLong_AsLong(obj)); break; case G_TYPE_ULONG: #if PY_VERSION_HEX < 0x03000000 if (PyInt_Check(obj)) { long val; val = PYGLIB_PyLong_AsLong(obj); if (val < 0) { PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property"); return -1; } g_value_set_ulong(value, (gulong)val); } else #endif if (PyLong_Check(obj)) g_value_set_ulong(value, PyLong_AsUnsignedLong(obj)); else return -1; break; case G_TYPE_INT64: g_value_set_int64(value, PyLong_AsLongLong(obj)); break; case G_TYPE_UINT64: #if PY_VERSION_HEX < 0x03000000 if (PyInt_Check(obj)) { long v = PyInt_AsLong(obj); if (v < 0) { PyErr_SetString(PyExc_OverflowError, "negative value not allowed for uint64 property"); return -1; } g_value_set_uint64(value, v); } else #endif if (PyLong_Check(obj)) g_value_set_uint64(value, PyLong_AsUnsignedLongLong(obj)); else return -1; break; case G_TYPE_ENUM: { gint val = 0; if (pyg_enum_get_value(G_VALUE_TYPE(value), obj, &val) < 0) { PyErr_Clear(); return -1; } g_value_set_enum(value, val); } break; case G_TYPE_FLAGS: { gint val = 0; if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) { PyErr_Clear(); return -1; } g_value_set_flags(value, val); } break; case G_TYPE_FLOAT: g_value_set_float(value, PyFloat_AsDouble(obj)); break; case G_TYPE_DOUBLE: g_value_set_double(value, PyFloat_AsDouble(obj)); break; case G_TYPE_STRING: if (obj == Py_None) { g_value_set_string(value, NULL); #if PY_VERSION_HEX < 0x03000000 } else if (PyString_Check(obj)) { g_value_set_string(value, PyString_AsString(obj)); #endif } else if (PyUnicode_Check(obj)) { tmp = PyUnicode_AsUTF8String(obj); g_value_set_string(value, PYGLIB_PyBytes_AsString(tmp)); Py_DECREF(tmp); } else { PyErr_Clear(); return -1; } break; case G_TYPE_POINTER: if (obj == Py_None) g_value_set_pointer(value, NULL); else if (PyObject_TypeCheck(obj, &PyGPointer_Type) && G_VALUE_HOLDS(value, ((PyGPointer *)obj)->gtype)) g_value_set_pointer(value, pyg_pointer_get(obj, gpointer)); else if (PYGLIB_CPointer_Check(obj)) g_value_set_pointer(value, PYGLIB_CPointer_GetPointer(obj, NULL)); else return -1; break; case G_TYPE_BOXED: { PyGTypeMarshal *bm; if (obj == Py_None) g_value_set_boxed(value, NULL); else if (G_VALUE_HOLDS(value, PY_TYPE_OBJECT)) g_value_set_boxed(value, obj); else if (PyObject_TypeCheck(obj, &PyGBoxed_Type) && G_VALUE_HOLDS(value, ((PyGBoxed *)obj)->gtype)) g_value_set_boxed(value, pyg_boxed_get(obj, gpointer)); else if (G_VALUE_HOLDS(value, G_TYPE_VALUE)) { GType type; GValue *n_value; type = pyg_type_from_object((PyObject*)Py_TYPE(obj)); if (G_UNLIKELY (! type)) { PyErr_Clear(); return -1; } n_value = g_new0 (GValue, 1); g_value_init (n_value, type); g_value_take_boxed (value, n_value); return pyg_value_from_pyobject (n_value, obj); } else if (PySequence_Check(obj) && G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY)) return pyg_value_array_from_pyobject(value, obj, NULL); else if (PYGLIB_PyUnicode_Check(obj) && G_VALUE_HOLDS(value, G_TYPE_GSTRING)) { GString *string; char *buffer; Py_ssize_t len; if (PYGLIB_PyUnicode_AsStringAndSize(obj, &buffer, &len)) return -1; string = g_string_new_len(buffer, len); g_value_set_boxed(value, string); g_string_free (string, TRUE); break; } else if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) return bm->tovalue(value, obj); else if (PYGLIB_CPointer_Check(obj)) g_value_set_boxed(value, PYGLIB_CPointer_GetPointer(obj, NULL)); else return -1; break; } case G_TYPE_PARAM: if (PyGParamSpec_Check(obj)) g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL)); else return -1; break; case G_TYPE_OBJECT: if (obj == Py_None) { g_value_set_object(value, NULL); } else if (PyObject_TypeCheck(obj, &PyGObject_Type) && G_TYPE_CHECK_INSTANCE_TYPE(pygobject_get(obj), G_VALUE_TYPE(value))) { g_value_set_object(value, pygobject_get(obj)); } else return -1; break; default: { PyGTypeMarshal *bm; if ((bm = pyg_type_lookup(G_VALUE_TYPE(value))) != NULL) return bm->tovalue(value, obj); break; } } if (PyErr_Occurred()) { g_value_unset(value); PyErr_Clear(); return -1; } return 0; }