summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog153
-rw-r--r--NEWS11
-rw-r--r--PKG-INFO4
-rwxr-xr-xconfigure24
-rw-r--r--configure.ac2
-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
-rw-r--r--tests/Makefile.am13
-rw-r--r--tests/Makefile.in30
-rw-r--r--tests/gimarshallingtestsextra.c37
-rw-r--r--tests/gimarshallingtestsextra.h26
-rw-r--r--tests/test_error.py6
-rw-r--r--tests/test_gobject.py23
-rw-r--r--tests/test_overrides_glib.py30
20 files changed, 540 insertions, 79 deletions
diff --git a/ChangeLog b/ChangeLog
index 17088b3..82cbb84 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,156 @@
+commit a4865ef2f8c70b93f84f93236786c65ad5f973af
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Tue Mar 1 21:46:21 2016 -0800
+
+ release 3.19.91
+
+ NEWS | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+commit cc75f994a07639b9ffcc6afef757768780a076de
+Author: Thibault Saunier <tsaunier@gnome.org>
+Date: Fri Feb 5 15:00:10 2016 +0100
+
+ tests: check passing Boxed type in GValue as function parameters
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=761592
+
+ tests/Makefile.am | 13 +++++++++++--
+ tests/gimarshallingtestsextra.c | 37
+ +++++++++++++++++++++++++++++++++++++
+ tests/gimarshallingtestsextra.h | 26 ++++++++++++++++++++++++++
+ tests/test_error.py | 6 ++++++
+ 4 files changed, 80 insertions(+), 2 deletions(-)
+
+commit 5f4b08f4e8a98046eab71537c7827edde2ca8742
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Mon Feb 29 22:50:32 2016 -0800
+
+ gerror: Add special case marshaling for boxing GErrors
+
+ Transfer gtype from introspection GError class to Python GError
+ implementation.
+ Expose the PyGError pointer as an extern so other C files can pick
+ this up.
+ Add custom to/from GValue marshalers for GError.
+ Add tests for both complete and incomplete (no boxed pointer held).
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=761592
+
+ gi/overrides/GLib.py | 1 +
+ gi/pygi-error.c | 32 +++++++++++++++++++++++++++++++-
+ gi/pygi-error.h | 2 ++
+ gi/pygi-value.c | 1 +
+ tests/test_gobject.py | 17 +++++++++++++++++
+ 5 files changed, 52 insertions(+), 1 deletion(-)
+
+commit cfca1457c39e3c4c7ef97e7b46a73c19e5adf305
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Sun Feb 28 01:39:31 2016 -0800
+
+ gerror: Add support for marshaling GError from Python to C
+
+ Refactor pygi_gerror_exception_check() to use a new broken out
+ function
+ pygi_error_marshal_from_py(). This allows re-use for argument
+ marshaling
+ of a Python GError to a C GError.
+ Remove PYGI_META_ARG_TYPE_CHILD setting for GError out argument
+ marshaling.
+ This was incorrect since GError exception arguments are not specified
+ explicitly and instead uses the "throws" option.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=685197
+
+ gi/pygi-error.c | 132
+ +++++++++++++++++++++++++++++--------------
+ gi/pygi-error.h | 3 +
+ tests/test_overrides_glib.py | 30 ++++++++++
+ 3 files changed, 123 insertions(+), 42 deletions(-)
+
+commit 2fc1a689a81614649d042965997f4546b0a58ada
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Sat Feb 27 17:21:53 2016 -0800
+
+ gerror: Add "_to_py" suffix to pygi_error_marshal
+
+ This will allow for the a pygi_error_marshal_from_py function.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=685197
+
+ gi/pygi-error.c | 8 ++++----
+ gi/pygi-error.h | 2 +-
+ 2 files changed, 5 insertions(+), 5 deletions(-)
+
+commit 7e29227b6f58cfcc96118a4af83658ca1a6fa1f4
+Author: Christoph Reiter <creiter@src.gnome.org>
+Date: Sat Jul 4 22:09:46 2015 +0200
+
+ Some error handling/reporting fixes.
+
+ * Check in pyg_boxed_new() if the passed type is an actual subclass
+ * Don't replace existing exceptions in pyg_value_as_pyobject()
+ * Print an error in pyg_closure_marshal() in case marshalling
+ an argument failed.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=751956
+
+ gi/pygboxed.c | 8 +++++++-
+ gi/pygi-value.c | 15 ++++++++++-----
+ gi/pygtype.c | 11 ++++++++++-
+ 3 files changed, 27 insertions(+), 7 deletions(-)
+
+commit 49880800b35029de3731523eede1b3174f10c1db
+Author: Christoph Reiter <creiter@src.gnome.org>
+Date: Sat Jul 4 21:40:04 2015 +0200
+
+ GVariant: Don't use pyg_boxed_new as GVariant isn't a PyGBoxed but
+ a PyGIStruct.
+
+ This only worked because they share the same struct layout.
+ This adds a new constructor for creating a new PyGIStruct instance
+ from GType.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=751956
+
+ gi/pygi-struct.c | 32 ++++++++++++++++++++++++++++++++
+ gi/pygi-struct.h | 5 +++++
+ gi/pygi-value.c | 3 ++-
+ 3 files changed, 39 insertions(+), 1 deletion(-)
+
+commit f27b1976ea325fcd55359888401dd08ac8fb074a
+Author: Mikhail Fludkov <misha@pexip.com>
+Date: Tue Sep 1 17:54:17 2015 +0200
+
+ pygi-value: special case for NULL GValueArray
+
+ Don't segfault when dealing with GValue of GValueArray type containing
+ NULL. Return empty list in this case.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=754359
+
+ gi/pygi-value.c | 5 +++--
+ tests/test_gobject.py | 6 ++++++
+ 2 files changed, 9 insertions(+), 2 deletions(-)
+
+commit c8176dfabea694ce738ff4633e7522b0d1fc1c51
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Sat Feb 20 20:42:40 2016 -0800
+
+ post-release version bump to 3.19.91
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d16ae38f0a12653557bdeba17eb155144d91bff4
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date: Sat Feb 20 19:56:24 2016 -0800
+
+ release 3.19.90
+
+ NEWS | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
commit 0190fb84fc1f88ba4c0623bf1b29fe3ca4f80932
Author: Simon Feltman <sfeltman@src.gnome.org>
Date: Sat Feb 20 19:49:31 2016 -0800
diff --git a/NEWS b/NEWS
index 7a3ca39..500a962 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+3.19.91 01-Mar-2016
+ - Fix marshaling of GError stored in GValue
+ (Simon Feltman) (Thibault Saunier) (#761592)
+ - Fix marshaling or GError from Python to C from function calls
+ (Simon Feltman) (#685197)
+ - Error handling/reporting fixes (Christoph Reiter) (#751956)
+ - Fix crash due to GVariant implemented as PyGBoxed not PyGIStruct
+ (Christoph Reiter) (#751956)
+ - Fix crash with GValueArray stored in GValue
+ (Mikhail Fludkov) (#754359)
+
3.19.90 20-Feb-2016
- tests: Set the active style context state before retrieving values
(Simon Feltman)
diff --git a/PKG-INFO b/PKG-INFO
index 9e53b03..187f30d 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.0
Name: PyGObject
-Version: 3.19.90
+Version: 3.19.91
Summary: Python bindings for GObject
Home-page: http://www.pygtk.org/
Author: James Henstridge
@@ -8,7 +8,7 @@ Author-email: james@daa.com.au
Maintainer: Simon Feltman
Maintainer-email: sfeltman@src.gnome.org
License: GNU LGPL
-Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.19/pygobject-3.19.90.tar.gz
+Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.19/pygobject-3.19.91.tar.gz
Description: Python bindings for GLib and GObject
Platform: POSIX, Windows
Classifier: Development Status :: 5 - Production/Stable
diff --git a/configure b/configure
index 1fea2d3..2f6c3f9 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for pygobject 3.19.90.
+# Generated by GNU Autoconf 2.69 for pygobject 3.19.91.
#
# Report bugs to <http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject>.
#
@@ -591,8 +591,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='pygobject'
PACKAGE_TARNAME='pygobject'
-PACKAGE_VERSION='3.19.90'
-PACKAGE_STRING='pygobject 3.19.90'
+PACKAGE_VERSION='3.19.91'
+PACKAGE_STRING='pygobject 3.19.91'
PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject'
PACKAGE_URL='https://wiki.gnome.org/Projects/PyGObject/'
@@ -1398,7 +1398,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures pygobject 3.19.90 to adapt to many kinds of systems.
+\`configure' configures pygobject 3.19.91 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1468,7 +1468,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of pygobject 3.19.90:";;
+ short | recursive ) echo "Configuration of pygobject 3.19.91:";;
esac
cat <<\_ACEOF
@@ -1611,7 +1611,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-pygobject configure 3.19.90
+pygobject configure 3.19.91
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1889,7 +1889,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by pygobject $as_me 3.19.90, which was
+It was created by pygobject $as_me 3.19.91, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2253,9 +2253,9 @@ $as_echo "#define PYGOBJECT_MINOR_VERSION 19" >>confdefs.h
PYGOBJECT_MINOR_VERSION=19
-$as_echo "#define PYGOBJECT_MICRO_VERSION 90" >>confdefs.h
+$as_echo "#define PYGOBJECT_MICRO_VERSION 91" >>confdefs.h
-PYGOBJECT_MICRO_VERSION=90
+PYGOBJECT_MICRO_VERSION=91
ac_config_headers="$ac_config_headers config.h"
@@ -2777,7 +2777,7 @@ fi
# Define the identity of the package.
PACKAGE='pygobject'
- VERSION='3.19.90'
+ VERSION='3.19.91'
cat >>confdefs.h <<_ACEOF
@@ -15861,7 +15861,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by pygobject $as_me 3.19.90, which was
+This file was extended by pygobject $as_me 3.19.91, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15928,7 +15928,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-pygobject config.status 3.19.90
+pygobject config.status 3.19.91
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
diff --git a/configure.ac b/configure.ac
index 99ff6b2..3ed9aff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,7 +18,7 @@ m4_define(python3_min_ver, 3.1)
dnl the pygobject version number
m4_define(pygobject_major_version, 3)
m4_define(pygobject_minor_version, 19)
-m4_define(pygobject_micro_version, 90)
+m4_define(pygobject_micro_version, 91)
m4_define(pygobject_version, pygobject_major_version.pygobject_minor_version.pygobject_micro_version)
dnl versions of packages we require ...
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);
}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9d5db5e..233175c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -2,7 +2,14 @@ CLEANFILES =
check_LTLIBRARIES = libgimarshallingtests.la
test_typelibs = GIMarshallingTests-1.0.typelib
-nodist_libgimarshallingtests_la_SOURCES = $(GI_DATADIR)/tests/gimarshallingtests.c $(GI_DATADIR)/tests/gimarshallingtests.h
+nodist_libgimarshallingtests_la_SOURCES = \
+ $(GI_DATADIR)/tests/gimarshallingtests.c \
+ $(GI_DATADIR)/tests/gimarshallingtests.h
+
+dist_libgimarshallingtests_la_SOURCES = \
+ $(srcdir)/gimarshallingtestsextra.c \
+ $(srcdir)/gimarshallingtestsextra.h
+
libgimarshallingtests_la_CFLAGS = $(GLIB_CFLAGS)
libgimarshallingtests_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) -no-undefined
@@ -17,7 +24,9 @@ GIMarshallingTests-1.0.gir: libgimarshallingtests.la Makefile
--library=libgimarshallingtests.la \
--libtool="$(top_builddir)/libtool" \
--output $@ \
- $(nodist_libgimarshallingtests_la_SOURCES)
+ $(nodist_libgimarshallingtests_la_SOURCES) \
+ $(dist_libgimarshallingtests_la_SOURCES)
+
GIMarshallingTests-1.0.typelib: GIMarshallingTests-1.0.gir Makefile
$(AM_V_GEN) g-ir-compiler $< -o $@
diff --git a/tests/Makefile.in b/tests/Makefile.in
index 838399c..05005e4 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -106,9 +106,12 @@ CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
libgimarshallingtests_la_LIBADD =
+dist_libgimarshallingtests_la_OBJECTS = \
+ libgimarshallingtests_la-gimarshallingtestsextra.lo
nodist_libgimarshallingtests_la_OBJECTS = \
libgimarshallingtests_la-gimarshallingtests.lo
libgimarshallingtests_la_OBJECTS = \
+ $(dist_libgimarshallingtests_la_OBJECTS) \
$(nodist_libgimarshallingtests_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -169,9 +172,11 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
-SOURCES = $(nodist_libgimarshallingtests_la_SOURCES) \
+SOURCES = $(dist_libgimarshallingtests_la_SOURCES) \
+ $(nodist_libgimarshallingtests_la_SOURCES) \
$(nodist_libregress_la_SOURCES) $(testhelper_la_SOURCES)
-DIST_SOURCES = $(testhelper_la_SOURCES)
+DIST_SOURCES = $(dist_libgimarshallingtests_la_SOURCES) \
+ $(testhelper_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -371,7 +376,14 @@ CLEANFILES = Regress-1.0.gir Regress-1.0.typelib \
check_LTLIBRARIES = libgimarshallingtests.la $(am__append_1) \
testhelper.la
test_typelibs = GIMarshallingTests-1.0.typelib $(am__append_2)
-nodist_libgimarshallingtests_la_SOURCES = $(GI_DATADIR)/tests/gimarshallingtests.c $(GI_DATADIR)/tests/gimarshallingtests.h
+nodist_libgimarshallingtests_la_SOURCES = \
+ $(GI_DATADIR)/tests/gimarshallingtests.c \
+ $(GI_DATADIR)/tests/gimarshallingtests.h
+
+dist_libgimarshallingtests_la_SOURCES = \
+ $(srcdir)/gimarshallingtestsextra.c \
+ $(srcdir)/gimarshallingtestsextra.h
+
libgimarshallingtests_la_CFLAGS = $(GLIB_CFLAGS)
libgimarshallingtests_la_LDFLAGS = -module -avoid-version $(GLIB_LIBS) -no-undefined
@ENABLE_CAIRO_TRUE@nodist_libregress_la_SOURCES = $(GI_DATADIR)/tests/regress.c $(GI_DATADIR)/tests/regress.h
@@ -501,6 +513,7 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgimarshallingtests_la-gimarshallingtests.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgimarshallingtests_la-gimarshallingtestsextra.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libregress_la-regress.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testhelper_la-test-floating.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testhelper_la-test-thread.Plo@am__quote@
@@ -528,6 +541,13 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+libgimarshallingtests_la-gimarshallingtestsextra.lo: $(srcdir)/gimarshallingtestsextra.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgimarshallingtests_la_CFLAGS) $(CFLAGS) -MT libgimarshallingtests_la-gimarshallingtestsextra.lo -MD -MP -MF $(DEPDIR)/libgimarshallingtests_la-gimarshallingtestsextra.Tpo -c -o libgimarshallingtests_la-gimarshallingtestsextra.lo `test -f '$(srcdir)/gimarshallingtestsextra.c' || echo '$(srcdir)/'`$(srcdir)/gimarshallingtestsextra.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgimarshallingtests_la-gimarshallingtestsextra.Tpo $(DEPDIR)/libgimarshallingtests_la-gimarshallingtestsextra.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/gimarshallingtestsextra.c' object='libgimarshallingtests_la-gimarshallingtestsextra.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgimarshallingtests_la_CFLAGS) $(CFLAGS) -c -o libgimarshallingtests_la-gimarshallingtestsextra.lo `test -f '$(srcdir)/gimarshallingtestsextra.c' || echo '$(srcdir)/'`$(srcdir)/gimarshallingtestsextra.c
+
libgimarshallingtests_la-gimarshallingtests.lo: $(GI_DATADIR)/tests/gimarshallingtests.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgimarshallingtests_la_CFLAGS) $(CFLAGS) -MT libgimarshallingtests_la-gimarshallingtests.lo -MD -MP -MF $(DEPDIR)/libgimarshallingtests_la-gimarshallingtests.Tpo -c -o libgimarshallingtests_la-gimarshallingtests.lo `test -f '$(GI_DATADIR)/tests/gimarshallingtests.c' || echo '$(srcdir)/'`$(GI_DATADIR)/tests/gimarshallingtests.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgimarshallingtests_la-gimarshallingtests.Tpo $(DEPDIR)/libgimarshallingtests_la-gimarshallingtests.Plo
@@ -796,7 +816,9 @@ GIMarshallingTests-1.0.gir: libgimarshallingtests.la Makefile
--library=libgimarshallingtests.la \
--libtool="$(top_builddir)/libtool" \
--output $@ \
- $(nodist_libgimarshallingtests_la_SOURCES)
+ $(nodist_libgimarshallingtests_la_SOURCES) \
+ $(dist_libgimarshallingtests_la_SOURCES)
+
GIMarshallingTests-1.0.typelib: GIMarshallingTests-1.0.gir Makefile
$(AM_V_GEN) g-ir-compiler $< -o $@
diff --git a/tests/gimarshallingtestsextra.c b/tests/gimarshallingtestsextra.c
new file mode 100644
index 0000000..9624077
--- /dev/null
+++ b/tests/gimarshallingtestsextra.c
@@ -0,0 +1,37 @@
+/* gimarshallingtestsextra.c
+ *
+ * Copyright (C) 2016 Thibault Saunier <tsaunier@gnome.org>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gimarshallingtestsextra.h"
+
+void
+gi_marshalling_tests_compare_two_gerrors_in_gvalue (GValue *v, GValue *v1)
+{
+ GError *error, * error1;
+
+ g_assert_cmpstr (g_type_name (G_VALUE_TYPE (v)), ==,
+ g_type_name (G_TYPE_ERROR));
+ g_assert_cmpstr (g_type_name (G_VALUE_TYPE (v1)), ==,
+ g_type_name (G_TYPE_ERROR));
+
+ error = (GError*) g_value_get_boxed (v);
+ error1 = (GError*) g_value_get_boxed (v1);
+
+ g_assert_cmpint (error->domain, ==, error1->domain);
+ g_assert_cmpint (error->code, ==, error1->code);
+ g_assert_cmpstr (error->message, ==, error1->message);
+}
diff --git a/tests/gimarshallingtestsextra.h b/tests/gimarshallingtestsextra.h
new file mode 100644
index 0000000..6858551
--- /dev/null
+++ b/tests/gimarshallingtestsextra.h
@@ -0,0 +1,26 @@
+/* gimarshallingtestsextra.h
+ *
+ * Copyright (C) 2016 Thibault Saunier <tsaunier@gnome.org>
+ *
+ * This file is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EXTRA_TESTS
+#define EXTRA_TESTS
+
+#include <glib-object.h>
+
+void gi_marshalling_tests_compare_two_gerrors_in_gvalue (GValue *v, GValue *v1);
+
+#endif /* EXTRA_TESTS */
diff --git a/tests/test_error.py b/tests/test_error.py
index f5a89ce..5702490 100644
--- a/tests/test_error.py
+++ b/tests/test_error.py
@@ -133,6 +133,12 @@ class TestMarshalling(unittest.TestCase):
self.assertEqual(e.domain, 'mydomain')
self.assertEqual(e.code, 42)
+ def tests_compare_two_gerrors_in_gvalue(self):
+ error = GLib.Error.new_literal(1, "error", 1)
+ error1 = GLib.Error.new_literal(1, "error", 1)
+
+ GIMarshallingTests.compare_two_gerrors_in_gvalue(error, error1)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_gobject.py b/tests/test_gobject.py
index 6c15e20..e78132d 100644
--- a/tests/test_gobject.py
+++ b/tests/test_gobject.py
@@ -669,5 +669,28 @@ class TestGValue(unittest.TestCase):
value = GObject.Value(GObject.TYPE_OBJECT, obj)
self.assertEqual(value.get_value(), obj)
+ def test_value_array(self):
+ value = GObject.Value(GObject.ValueArray)
+ self.assertEqual(value.g_type, GObject.type_from_name('GValueArray'))
+ value.set_value([32, 'foo_bar', 0.3])
+ self.assertEqual(value.get_value(), [32, 'foo_bar', 0.3])
+
+ def test_gerror_boxing(self):
+ error = GLib.Error('test message', domain='mydomain', code=42)
+ value = GObject.Value(GLib.Error, error)
+ self.assertEqual(value.g_type, GObject.type_from_name('GError'))
+
+ unboxed = value.get_value()
+ self.assertEqual(unboxed.message, error.message)
+ self.assertEqual(unboxed.domain, error.domain)
+ self.assertEqual(unboxed.code, error.code)
+
+ def test_gerror_novalue(self):
+ error = GLib.Error('test message', domain='mydomain', code=42)
+ value = GObject.Value(GLib.Error)
+ self.assertEqual(value.g_type, GObject.type_from_name('GError'))
+ self.assertEqual(value.get_value(), None)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_overrides_glib.py b/tests/test_overrides_glib.py
index 4f630dc..891923e 100644
--- a/tests/test_overrides_glib.py
+++ b/tests/test_overrides_glib.py
@@ -495,6 +495,36 @@ class TestGVariant(unittest.TestCase):
v = GLib.Variant('(is)', (1, 'somestring'))
self.assertEqual(str(v), "(1, 'somestring')")
+ def test_parse_error(self):
+ # This test doubles as a test for GLib.Error marshaling.
+ source_str = 'abc'
+ with self.assertRaises(GLib.Error) as context:
+ GLib.Variant.parse(None, source_str, None, None)
+ e = context.exception
+ text = GLib.Variant.parse_error_print_context(e, source_str)
+ self.assertTrue(source_str in text)
+
+ def test_parse_error_exceptions(self):
+ source_str = 'abc'
+ self.assertRaisesRegexp(TypeError, 'Must be GLib.Error, not int',
+ GLib.Variant.parse_error_print_context,
+ 42, source_str)
+
+ gerror = GLib.Error(message=42) # not a string
+ self.assertRaisesRegexp(ValueError, ".*must have a 'message'.*",
+ GLib.Variant.parse_error_print_context,
+ gerror, source_str)
+
+ gerror = GLib.Error(domain=42) # not a string
+ self.assertRaisesRegexp(ValueError, ".*must have a 'domain'.*",
+ GLib.Variant.parse_error_print_context,
+ gerror, source_str)
+
+ gerror = GLib.Error(code='not an int')
+ self.assertRaisesRegexp(ValueError, ".*must have a 'code' int.*",
+ GLib.Variant.parse_error_print_context,
+ gerror, source_str)
+
class TestConstants(unittest.TestCase):