summaryrefslogtreecommitdiff
path: root/gi
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:44:38 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2017-07-12 08:44:42 +0900
commit1676d45a3ca971e18e44c9d5cf2972b3c858a528 (patch)
treecc6cc17c74ca19a11e24be6255845b5646b9e95e /gi
parentb34b5d5be117c5f7bf0bdc90f927dddada3b6118 (diff)
downloadpygobject2-1676d45a3ca971e18e44c9d5cf2972b3c858a528.tar.gz
pygobject2-1676d45a3ca971e18e44c9d5cf2972b3c858a528.tar.bz2
pygobject2-1676d45a3ca971e18e44c9d5cf2972b3c858a528.zip
Imported Upstream version 3.19.91
Change-Id: I1db218cf8c13ceaf96e044a7bd2a6f9a285854b3 Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
Diffstat (limited to 'gi')
-rw-r--r--gi/overrides/GLib.py1
-rw-r--r--gi/pygboxed.c8
-rw-r--r--gi/pygi-error.c172
-rw-r--r--gi/pygi-error.h7
-rw-r--r--gi/pygi-struct.c32
-rw-r--r--gi/pygi-struct.h5
-rw-r--r--gi/pygi-value.c24
-rw-r--r--gi/pygtype.c11
8 files changed, 202 insertions, 58 deletions
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index 455ea84..c12b4d8 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -74,6 +74,7 @@ def gerror_new_literal(domain, message, code):
# Monkey patch methods that rely on GLib introspection to be loaded at runtime.
Error.__name__ = 'Error'
Error.__module__ = 'GLib'
+Error.__gtype__ = GLib.Error.__gtype__
Error.matches = gerror_matches
Error.new_literal = staticmethod(gerror_new_literal)
diff --git a/gi/pygboxed.c b/gi/pygboxed.c
index 30ab423..cdb766c 100644
--- a/gi/pygboxed.c
+++ b/gi/pygboxed.c
@@ -189,7 +189,7 @@ pyg_register_boxed(PyObject *dict, const gchar *class_name,
* wrapper will be freed when the wrapper is deallocated. If
* @copy_boxed is True, then @own_ref must also be True.
*
- * Returns: the boxed wrapper.
+ * Returns: the boxed wrapper or %NULL and sets an exception.
*/
PyObject *
pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed,
@@ -218,6 +218,12 @@ pyg_boxed_new(GType boxed_type, gpointer boxed, gboolean copy_boxed,
if (!tp)
tp = (PyTypeObject *)&PyGBoxed_Type; /* fallback */
+ if (!PyType_IsSubtype (tp, &PyGBoxed_Type)) {
+ PyErr_Format (PyExc_RuntimeError, "%s isn't a GBoxed", tp->tp_name);
+ pyglib_gil_state_release (state);
+ return NULL;
+ }
+
self = (PyGBoxed *)tp->tp_alloc(tp, 0);
if (self == NULL) {
diff --git a/gi/pygi-error.c b/gi/pygi-error.c
index b019a09..d86021c 100644
--- a/gi/pygi-error.c
+++ b/gi/pygi-error.c
@@ -23,13 +23,14 @@
#include "pyglib.h"
#include "pygi-private.h"
#include "pygi-error.h"
+#include "pygtype.h"
-static PyObject *PyGError = NULL;
+PyObject *PyGError = NULL;
static PyObject *exception_table = NULL;
/**
- * pygi_error_marshal:
+ * pygi_error_marshal_to_py:
* @error: a pointer to the GError.
*
* Checks to see if @error has been set. If @error has been set, then a
@@ -38,7 +39,7 @@ static PyObject *exception_table = NULL;
* Returns: a GLib.GError Python exception object, or NULL.
*/
PyObject *
-pygi_error_marshal (GError **error)
+pygi_error_marshal_to_py (GError **error)
{
PyGILState_STATE state;
PyObject *exc_type;
@@ -97,7 +98,7 @@ pygi_error_check (GError **error)
state = pyglib_gil_state_ensure();
- exc_instance = pygi_error_marshal (error);
+ exc_instance = pygi_error_marshal_to_py (error);
PyErr_SetObject(PyGError, exc_instance);
Py_DECREF(exc_instance);
g_clear_error(error);
@@ -108,6 +109,64 @@ pygi_error_check (GError **error)
}
/**
+ * 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;
+}
+
+/**
* pygi_gerror_exception_check:
* @error: a standard GLib GError ** output parameter
*
@@ -121,10 +180,8 @@ pygi_error_check (GError **error)
gboolean
pygi_gerror_exception_check (GError **error)
{
+ int res = -1;
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;
@@ -144,44 +201,14 @@ pygi_gerror_exception_check (GError **error)
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;
+ if (!pygi_error_marshal_from_py (value, error)) {
+ PyErr_Print();
+ res = -2;
}
- 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;
+ return res;
+
}
/**
@@ -221,9 +248,27 @@ _pygi_marshal_from_py_gerror (PyGIInvokeState *state,
GIArgument *arg,
gpointer *cleanup_data)
{
- PyErr_Format (PyExc_NotImplementedError,
- "Marshalling for GErrors is not implemented");
- return FALSE;
+ GError *error = NULL;
+ if (pygi_error_marshal_from_py (py_arg, &error)) {
+ arg->v_pointer = error;
+ *cleanup_data = error;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+static void
+_pygi_marshal_from_py_gerror_cleanup (PyGIInvokeState *state,
+ PyGIArgCache *arg_cache,
+ PyObject *py_arg,
+ gpointer data,
+ gboolean was_processed)
+{
+ if (was_processed) {
+ g_error_free ((GError *)data);
+ }
}
static PyObject *
@@ -235,7 +280,7 @@ _pygi_marshal_to_py_gerror (PyGIInvokeState *state,
GError *error = arg->v_pointer;
PyObject *py_obj = NULL;
- py_obj = pygi_error_marshal (&error);
+ py_obj = pygi_error_marshal_to_py (&error);
if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) {
g_error_free (error);
@@ -261,7 +306,11 @@ pygi_arg_gerror_setup_from_info (PyGIArgCache *arg_cache,
if (direction & PYGI_DIRECTION_FROM_PYTHON) {
arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
- arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+
+ /* Assign cleanup function if we manage memory after call completion. */
+ if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+ arg_cache->from_py_cleanup = _pygi_marshal_from_py_gerror_cleanup;
+ }
}
if (direction & PYGI_DIRECTION_TO_PYTHON) {
@@ -298,6 +347,31 @@ pygi_arg_gerror_new_from_info (GITypeInfo *type_info,
}
}
+static PyObject *
+pygerror_from_gvalue (const GValue *value)
+{
+ GError *gerror = (GError *) g_value_get_boxed (value);
+ PyObject *pyerr = pygi_error_marshal_to_py (&gerror);
+ if (pyerr == NULL) {
+ Py_RETURN_NONE;
+ } else {
+ return pyerr;
+ }
+}
+
+static int
+pygerror_to_gvalue (GValue *value, PyObject *pyerror)
+{
+ GError *gerror = NULL;
+
+ if (pygi_error_marshal_from_py (pyerror, &gerror)) {
+ g_value_take_boxed (value, gerror);
+ return 0;
+ }
+
+ return -1;
+}
+
void
pygi_error_register_types (PyObject *module)
{
@@ -308,5 +382,9 @@ pygi_error_register_types (PyObject *module)
/* Stash a reference to the Python implemented gi._error.GError. */
PyGError = PyObject_GetAttrString (error_module, "GError");
+
+ pyg_register_gtype_custom (G_TYPE_ERROR,
+ pygerror_from_gvalue,
+ pygerror_to_gvalue);
}
diff --git a/gi/pygi-error.h b/gi/pygi-error.h
index 72d2be0..e7cc05f 100644
--- a/gi/pygi-error.h
+++ b/gi/pygi-error.h
@@ -27,9 +27,14 @@
G_BEGIN_DECLS
+extern PyObject *PyGError;
+
gboolean pygi_error_check (GError **error);
-PyObject* pygi_error_marshal (GError **error);
+PyObject* pygi_error_marshal_to_py (GError **error);
+
+gboolean pygi_error_marshal_from_py (PyObject *pyerr,
+ GError **error);
gboolean pygi_gerror_exception_check (GError **error);
diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c
index d84eed5..c379a88 100644
--- a/gi/pygi-struct.c
+++ b/gi/pygi-struct.c
@@ -132,6 +132,38 @@ _struct_init (PyObject *self,
PYGLIB_DEFINE_TYPE("gi.Struct", PyGIStruct_Type, PyGIStruct);
+
+PyObject *
+_pygi_struct_new_from_g_type (GType g_type,
+ gpointer pointer,
+ gboolean free_on_dealloc)
+{
+ PyGIStruct *self;
+ PyTypeObject *type;
+
+ type = (PyTypeObject *)pygi_type_import_by_g_type (g_type);
+
+ if (!type)
+ type = (PyTypeObject *)&PyGIStruct_Type; /* fallback */
+
+ if (!PyType_IsSubtype (type, &PyGIStruct_Type)) {
+ PyErr_SetString (PyExc_TypeError, "must be a subtype of gi.Struct");
+ return NULL;
+ }
+
+ self = (PyGIStruct *) type->tp_alloc (type, 0);
+ if (self == NULL) {
+ return NULL;
+ }
+
+ pyg_pointer_set_ptr (self, pointer);
+ ( (PyGPointer *) self)->gtype = g_type;
+ self->free_on_dealloc = free_on_dealloc;
+
+ return (PyObject *) self;
+}
+
+
PyObject *
_pygi_struct_new (PyTypeObject *type,
gpointer pointer,
diff --git a/gi/pygi-struct.h b/gi/pygi-struct.h
index ab303e0..347c55f 100644
--- a/gi/pygi-struct.h
+++ b/gi/pygi-struct.h
@@ -31,6 +31,11 @@ _pygi_struct_new (PyTypeObject *type,
gpointer pointer,
gboolean free_on_dealloc);
+PyObject *
+_pygi_struct_new_from_g_type (GType g_type,
+ gpointer pointer,
+ gboolean free_on_dealloc);
+
void _pygi_struct_register_types (PyObject *m);
G_END_DECLS
diff --git a/gi/pygi-value.c b/gi/pygi-value.c
index 2cf567d..9da87a5 100644
--- a/gi/pygi-value.c
+++ b/gi/pygi-value.c
@@ -18,6 +18,7 @@
#include <Python.h>
#include "pygi-value.h"
+#include "pygi-struct.h"
#include "pyglib-python-compat.h"
#include "pygobject-private.h"
#include "pygtype.h"
@@ -775,9 +776,10 @@ pygi_value_to_py_structured_type (const GValue *value, GType fundamental, gboole
return pyg_value_as_pyobject(n_value, copy_boxed);
} else if (holds_value_array) {
GValueArray *array = (GValueArray *) g_value_get_boxed(value);
- PyObject *ret = PyList_New(array->n_values);
+ Py_ssize_t n_values = array ? array->n_values : 0;
+ PyObject *ret = PyList_New(n_values);
int i;
- for (i = 0; i < array->n_values; ++i)
+ for (i = 0; i < n_values; ++i)
PyList_SET_ITEM(ret, i, pyg_value_as_pyobject
(array->values + i, copy_boxed));
return ret;
@@ -809,7 +811,7 @@ pygi_value_to_py_structured_type (const GValue *value, GType fundamental, gboole
Py_INCREF(Py_None);
return Py_None;
}
- return pyg_boxed_new(G_TYPE_VARIANT, g_variant_ref(v), FALSE, FALSE);
+ return _pygi_struct_new_from_g_type (G_TYPE_VARIANT, g_variant_ref(v), FALSE);
}
default:
{
@@ -832,13 +834,13 @@ pygi_value_to_py_structured_type (const GValue *value, GType fundamental, gboole
* This function creates/returns a Python wrapper object that
* represents the GValue passed as an argument.
*
- * Returns: a PyObject representing the value.
+ * Returns: a PyObject representing the value or %NULL and sets an exception.
*/
PyObject *
pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed)
{
- gchar buf[128];
PyObject *pyobj;
+ const gchar *type_name;
GType fundamental = G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value));
/* HACK: special case char and uchar to return PyBytes intstead of integers
@@ -863,10 +865,16 @@ pyg_value_as_pyobject (const GValue *value, gboolean copy_boxed)
return pyobj;
}
- g_snprintf(buf, sizeof(buf), "unknown type %s",
- g_type_name(G_VALUE_TYPE(value)));
- PyErr_SetString(PyExc_TypeError, buf);
+ if (!PyErr_Occurred ()) {
+ type_name = g_type_name (G_VALUE_TYPE (value));
+ if (type_name == NULL) {
+ type_name = "(null)";
+ }
+ PyErr_Format (PyExc_TypeError, "unknown type %s", type_name);
+ }
+
return NULL;
+
}
diff --git a/gi/pygtype.c b/gi/pygtype.c
index 985e969..a3784c8 100644
--- a/gi/pygtype.c
+++ b/gi/pygtype.c
@@ -704,7 +704,16 @@ pyg_closure_marshal(GClosure *closure,
/* error condition */
if (!item) {
- goto out;
+ if (!PyErr_Occurred ())
+ PyErr_SetString (PyExc_TypeError,
+ "can't convert parameter to desired type");
+
+ if (pc->exception_handler)
+ pc->exception_handler (return_value, n_param_values, param_values);
+ else
+ PyErr_Print();
+
+ goto out;
}
PyTuple_SetItem(params, i, item);
}