diff options
-rw-r--r-- | ChangeLog | 447 | ||||
-rw-r--r-- | NEWS | 33 | ||||
-rw-r--r-- | PKG-INFO | 4 | ||||
-rwxr-xr-x | configure | 30 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | gi/_glib/pygiochannel.c | 2 | ||||
-rw-r--r-- | gi/_glib/pyglib.c | 51 | ||||
-rw-r--r-- | gi/_glib/pyglib.h | 1 | ||||
-rw-r--r-- | gi/_glib/pygmainloop.c | 7 | ||||
-rw-r--r-- | gi/_gobject/gobjectmodule.c | 2 | ||||
-rw-r--r-- | gi/_gobject/pygobject.c | 2 | ||||
-rw-r--r-- | gi/gimodule.c | 10 | ||||
-rw-r--r-- | gi/overrides/GLib.py | 41 | ||||
-rw-r--r-- | gi/overrides/Gtk.py | 10 | ||||
-rw-r--r-- | gi/pygi-argument.c | 36 | ||||
-rw-r--r-- | gi/pygi-closure.c | 5 | ||||
-rw-r--r-- | gi/pygi-foreign-cairo.c | 2 | ||||
-rw-r--r-- | gi/pygi-marshal-cleanup.c | 34 | ||||
-rw-r--r-- | gi/pygi-marshal-from-py.c | 8 | ||||
-rw-r--r-- | gi/pygi-marshal-to-py.c | 25 | ||||
-rw-r--r-- | gi/pygi-property.c | 48 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/Makefile.in | 6 | ||||
-rw-r--r-- | tests/runtests-windows.py | 44 | ||||
-rw-r--r-- | tests/test_everything.py | 68 | ||||
-rw-r--r-- | tests/test_gi.py | 110 | ||||
-rw-r--r-- | tests/test_overrides.py | 101 |
27 files changed, 970 insertions, 162 deletions
@@ -1,53 +1,420 @@ -commit e65d2fe75310a478e09eef1ab942ece09516d7d9 +commit 8ac474c15199ca00c729a73af9c926172657b842 Author: Sebastian Pölsterl <sebp@k-d-w.org> -Date: Thu Feb 9 10:02:14 2012 +0100 +Date: Mon Feb 6 19:11:52 2012 +0100 - Prepare 3.0.4 release + Prepare 3.1.0 release - NEWS | 5 +++++ - 1 files changed, 5 insertions(+), 0 deletions(-) + NEWS | 34 ++++++++++++++++++++++++++++++++++ + 1 files changed, 34 insertions(+), 0 deletions(-) -commit f24b5a4306fb83f6ff46920ecd7adc201d105b16 -Author: Martin Pitt <martin.pitt@ubuntu.com> -Date: Sat Jan 7 09:47:24 2012 +0100 +commit 18996ae455fb01a1e53a3826f0a1e79d06097c5b +Author: Sebastian Pölsterl <sebp@k-d-w.org> +Date: Mon Feb 6 19:04:41 2012 +0100 + + Updated DOAP file to only include people currently actively working + on the project + + Removed obsolete MAINTAINERS file + + MAINTAINERS | 19 ------------------- + pygobject.doap | 44 +++++++++++++++----------------------------- + 2 files changed, 15 insertions(+), 48 deletions(-) + +commit 0285e107be581c4d594127dc06cd05df1f02fb3f +Author: Sebastian Pölsterl <sebp@k-d-w.org> +Date: Mon Feb 6 18:57:01 2012 +0100 Revert "Convert all strings to utf-8 encoding when retrieving from TreeModel" - This changes existing behaviour (model values being str instead of - unicode) and - also makes tree model behaviour incompatible to the rest of Gtk - behaviour - (which always returns UTF-8 encoded str objects, not unicode). The - original bug - description was a bug in the test case code, you cannot mix str - and unicode - objects in interpolation. - - This reverts commit 33060639bc4857238f21c2329b8e8888fbd8fdc2. + This reverts commit 654711d0f940d7480d0f1cdb25a3dc9996f7a706. - https://bugzilla.gnome.org/show_bug.cgi?id=663610 + Due to this commit breaking backwards compatability, we decided to + revert this change gi/overrides/Gtk.py | 15 --------------- tests/compathelper.py | 2 -- tests/test_overrides.py | 31 +------------------------------ 3 files changed, 1 insertions(+), 47 deletions(-) -commit cba8124389de92f98c45cbaf2bd9c320036d6407 -Author: Tomeu Vizoso <tomeu.vizoso@collabora.com> -Date: Fri Dec 23 12:20:15 2011 +0100 +commit 0e921cd26ed5a6e3bc6ef5f553e8b22b862d72a6 +Author: Sebastian Pölsterl <sebp@k-d-w.org> +Date: Sun Feb 5 13:47:10 2012 +0100 - Post-release bump to 3.0.4 + tests: Fixed issues with python3 - configure.ac | 2 +- + tests/test_gi.py | 9 ++++++--- + 1 files changed, 6 insertions(+), 3 deletions(-) + +commit ee62df4d2fc0cc63c2f29d3ad9b47b875dbd5f89 +Author: Sebastian Pölsterl <sebp@k-d-w.org> +Date: Sun Feb 5 11:59:51 2012 +0100 + + Properly distinguish between different integer types for properties + + https://bugzilla.gnome.org/show_bug.cgi?id=664150 + + gi/pygi-property.c | 48 ++++++++++++++++++++++++++++++++++++--- + tests/test_gi.py | 62 + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 106 insertions(+), 4 deletions(-) + +commit c329bf2aee8d75ce452638db75e09197ff2b9b65 +Author: Sebastian Pölsterl <sebp@k-d-w.org> +Date: Sun Feb 5 11:46:21 2012 +0100 + + Distinguish between GArray and GPtrArray when cleaning up + + This fixes a crash in test_gi.TestGPtrArray and makes sure + memory is free'd correctly + + https://bugzilla.gnome.org/show_bug.cgi?id=669393 + + gi/pygi-marshal-cleanup.c | 32 +++++++++++++++++++++++--------- + 1 files changed, 23 insertions(+), 9 deletions(-) + +commit 4ea37c606f67df843788261b2c8acd6bac4c1e0c +Author: Paolo Borelli <pborelli@gnome.org> +Date: Sun Feb 5 18:51:53 2012 +0100 + + Add null_gerror_callback unit test + + This models the case where the callback is successful and does not set + an error. + + https://bugzilla.gnome.org/show_bug.cgi?id=669415 + + tests/test_everything.py | 9 +++++++++ + 1 files changed, 9 insertions(+), 0 deletions(-) + +commit a41984780ee49dcf02c718ca1be87bba747472e5 +Author: Martin Pitt <martin.pitt@ubuntu.com> +Date: Mon Feb 6 09:34:28 2012 +0100 + + pyglib_error_check: Re-add missing NULL check + + Commit adcfe96d49b09bc accidentally dropped the check if *error is + NULL, i. e. + any error is actually set. Due to that, pyglib_error_check() + always returned + TRUE. Reintroduce the check. + + Thanks to Alberto Mardegan for spotting this! + + https://bugzilla.gnome.org/show_bug.cgi?id=669415 + + gi/_glib/pyglib.c | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +commit 2c797c17913999379e277788d5e4cce8d68cebb0 +Author: Michael Culbertson <michael.culbertson@gmail.com> +Date: Sat Feb 4 16:11:34 2012 +0100 + + Add tests/runtests-windows.py to source tarball + + https://bugzilla.gnome.org/show_bug.cgi?id=663288 + + tests/Makefile.am | 1 + + 1 files changed, 1 insertions(+), 0 deletions(-) + +commit d6a899cdf70e978534326155e3fad75a705f4b20 +Author: Sebastian Pölsterl <sebp@k-d-w.org> +Date: Sat Feb 4 15:55:55 2012 +0100 + + Don't issue a depreciation warning for GtkDialog's NO_SEPARATOR flag, + even when unused + + https://bugzilla.gnome.org/show_bug.cgi?id=665553 + + gi/overrides/Gtk.py | 6 ++---- + 1 files changed, 2 insertions(+), 4 deletions(-) + +commit 534ec71c575a279ff1c05da20a8858bb1145b4d0 +Author: Nirbheek Chauhan <nirbheek@gentoo.org> +Date: Sat Feb 4 15:42:36 2012 +0100 + + Fix bool() operations on GLib.Variant objects + + Defines __nonzero__ (python2) and __bool__ (python3) for GLib.Variant + + Also adds some tests for boolean comparisons. + + https://bugzilla.gnome.org/show_bug.cgi?id=647723 + + gi/overrides/GLib.py | 18 ++++++++++++++++++ + tests/test_overrides.py | 45 + +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 63 insertions(+), 0 deletions(-) + +commit 8d6a127df5dd1e5f26faeba8f977074b4496b24f +Author: Nirbheek Chauhan <nirbheek@gentoo.org> +Date: Sat Feb 4 15:41:08 2012 +0100 + + Fix hash() and __eq__() for GLib.Variant objects + + Define __hash__, __eq__, __ne__ for GLib.Variant so that objects can + be used in sets, dicts, and can be compared using == and != easily. + + Also adds some tests for this. + + https://bugzilla.gnome.org/show_bug.cgi?id=647725 + + gi/overrides/GLib.py | 23 +++++++++++++++++++ + tests/test_overrides.py | 56 + +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 79 insertions(+), 0 deletions(-) + +commit f82404034be042bf2026bbb7f1e33b11d6e17a6f +Author: Martin Pitt <martin.pitt@ubuntu.com> +Date: Wed Jan 25 07:01:06 2012 +0100 + + Fix method names of callback tests + + Change test_everything.TestCallbacks.* test names from camelCase + to the + standard PEP-8 underscore_style. This is now consistent with all + other test + case names. + + tests/test_everything.py | 30 +++++++++++++++--------------- + 1 files changed, 15 insertions(+), 15 deletions(-) + +commit e37ee78fbf0aa72159a40da4165a26bea065faf1 +Author: Will Thompson <will.thompson@collabora.co.uk> +Date: Mon Jan 23 13:10:30 2012 +0000 + + Cairo: add missing braces around array-of-struct definition + + This triggered a -Wmissing-braces warning. + + https://bugzilla.gnome.org/show_bug.cgi?id=668497 + + gi/pygi-foreign-cairo.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) -commit 9ba741343e79f0d108074c0110f1aada5f7da4a3 -Merge: 3306063 8d1a36c +commit db24865d6b60351d72f5b8f47103d6d0a6c63b2e +Author: Will Thompson <will.thompson@collabora.co.uk> +Date: Mon Jan 23 13:06:41 2012 +0000 + + g_instance_init: cast to PyGObject * as needed + + This squashes a compiler warning. + + https://bugzilla.gnome.org/show_bug.cgi?id=668497 + + gi/_gobject/gobjectmodule.c | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +commit a8408cfd68cd5e7cdb0b8a83e107d9a0d828e4bd +Author: Will Thompson <will.thompson@collabora.co.uk> +Date: Mon Jan 23 13:01:27 2012 +0000 + + Fix a few set-but-not-used warnings. + + In a couple of cases, the variable in question was set to a value + spelled out again later in the function. + + The 'sequence_cache' variable is re-declared five lines below. + + The return value of 'read' was previously completely ignored. The + 'gssize ret' variable was in fact added to squash an unused-result + warning. + + https://bugzilla.gnome.org/show_bug.cgi?id=668497 + + gi/_glib/pygiochannel.c | 2 +- + gi/_glib/pygmainloop.c | 3 +-- + gi/_gobject/pygobject.c | 2 +- + gi/pygi-marshal-cleanup.c | 2 -- + 4 files changed, 3 insertions(+), 6 deletions(-) + +commit 29a30490ed51e347e8f57d2bf9af69400734eee8 +Author: Stefano Facchini <stefano.facchini@gmail.com> +Date: Thu Jan 19 18:09:07 2012 +0100 + + pygmainloop: allow for extra arguments in 'quit' method + + To allow for the common syntax: + + object.connect('signal-name', main_loop.quit) + + https://bugzilla.gnome.org/show_bug.cgi?id=668288 + + gi/_glib/pygmainloop.c | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +commit 557a61c12c01137a0d7c679c4b053973df09d445 +Author: Alexandre Rostovtsev <tetromino@gentoo.org> +Date: Mon Dec 26 00:44:56 2011 -0500 + + Fix bytearray test compatibility with python3 + + https://bugs.gentoo.org/show_bug.cgi?id=321879 + + https://bugzilla.gnome.org/show_bug.cgi?id=666852 + + tests/test_gi.py | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +commit d69e5b3c7bdb9113382fd125c256b12bff4c24d2 +Author: Alberto Mardegan <mardy@users.sourceforge.net> +Date: Mon Jan 23 12:37:26 2012 +0200 + + Respect transfer-type when demarshalling GErrors + + The marshaller previously ignored "transfer full" on GError* + arguments, causing + crashes due to double-freeing them. This causes the + testCallbackUserdata() test + case to crash after the previous GError/GHashTable marshalling fix. + + https://bugzilla.gnome.org/show_bug.cgi?id=666270 + + gi/pygi-argument.c | 12 +++++++++++- + 1 files changed, 11 insertions(+), 1 deletions(-) + +commit 77f32d9110bfeb6dad8457f565b4c70b5998fef6 +Author: Alberto Mardegan <mardy@users.sourceforge.net> +Date: Thu Dec 15 16:12:01 2011 +0200 + + Support GHashTable and GError as callback/closure arguments + + Marshalling of these types from C is already implemented, let's + take it + into use for calbacks and closures too. + + Add corresponding test cases. + + https://bugzilla.gnome.org/show_bug.cgi?id=666270 + + Signed-off-by: Martin Pitt <martin.pitt@ubuntu.com> + + gi/pygi-closure.c | 2 ++ + tests/test_everything.py | 35 +++++++++++++++++++++++++++++++++++ + 2 files changed, 37 insertions(+), 0 deletions(-) + +commit 4b9dc03d0e49e9a1f4bf0f2df503bdff00d13a2b +Author: Will Thompson <will.thompson@collabora.co.uk> +Date: Mon Jan 23 13:56:02 2012 +0000 + + Don't leak when marshalling GErrors to C + + Python-land GLib.GErrors are supposed to have three attributes: + "message", "domain" and "code". If those attributes are missing, + or they + have the wrong types, the C GError is filled in with a message + describing the error. The present-but-ill-typed code paths did not + DECREF the ill-typed values. + + https://bugzilla.gnome.org/show_bug.cgi?id=666098 + + gi/_glib/pyglib.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +commit adcfe96d49b09bcc550653d73de196610fd5144d +Author: Will Thompson <will.thompson@collabora.co.uk> +Date: Fri Jan 20 16:20:10 2012 +0000 + + Support functions which return GError + + GStreamer has the following method: + + void gst_message_parse_error ( + GstMessage *message, + GError **error, + gchar **debug_message); + + With this patch, we marshal the GError out parameter as a + GObject.GError + exception, but return it rather than throwing it. The test cases cover + two variations on the theme of the function above (one with (transfer + full), as in GStreamer, and another with (transfer none)) as well as a + function with return type GError *. + + https://bugzilla.gnome.org/show_bug.cgi?id=666098 + + gi/_glib/pyglib.c | 46 + +++++++++++++++++++++++++++++++++++----------- + gi/_glib/pyglib.h | 1 + + gi/pygi-marshal-to-py.c | 16 +++++++++++++--- + tests/test_gi.py | 32 ++++++++++++++++++++++++++++++++ + 4 files changed, 81 insertions(+), 14 deletions(-) + +commit 09f003729eac9d553a208c343c2a14d253b77d9a +Author: Alberto Mardegan <mardy@users.sourceforge.net> +Date: Mon Jan 23 12:42:21 2012 +0200 + + Fix indentation of _pygi_argument_to_object() + + Side issue in https://bugzilla.gnome.org/show_bug.cgi?id=666270 + + Signed-off-by: Martin Pitt <martin.pitt@ubuntu.com> + + gi/pygi-argument.c | 26 +++++++++++++------------- + 1 files changed, 13 insertions(+), 13 deletions(-) + +commit c71c010be01d706f90bc200194325fd82f4071b2 +Author: Paolo Borelli <pborelli@gnome.org> +Date: Sat Jan 14 14:24:23 2012 +0100 + + Avoid C99 syntax. + + gi/gimodule.c | 10 ++++++---- + 1 files changed, 6 insertions(+), 4 deletions(-) + +commit c299d058c22385ececaec64c872d1dd1bc1ae17a +Author: Paolo Borelli <pborelli@gnome.org> +Date: Fri Jan 6 13:39:31 2012 +0100 + + Connect to first action of a radio group. + + gi/overrides/Gtk.py | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +commit dee2f179037902a3883bd0e61ff1c350e1fd8a4f +Author: Paolo Borelli <pborelli@gnome.org> +Date: Wed Jan 4 16:40:51 2012 +0100 + + Use g_slist_free_full in pygi-closure. + + gi/pygi-closure.c | 3 +-- + 1 files changed, 1 insertions(+), 2 deletions(-) + +commit 2bee4207ab6f07dc9c0952affe72f0e304cfb624 +Author: Paolo Borelli <pborelli@gnome.org> +Date: Wed Jan 4 15:24:13 2012 +0100 + + Avoid O(n^2) behavior when marshalling lists + + Appending requires walking the list every time: just prepend and + reverse + the list at the end. + + https://bugzilla.gnome.org/show_bug.cgi?id=667261 + + gi/pygi-marshal-from-py.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +commit d68455e99b1a9ebba31209b17a11317b1958678b +Author: Paolo Borelli <pborelli@gnome.org> +Date: Tue Jan 3 16:57:40 2012 +0100 + + Handle NULL as a valid case of a char** array + + Treat NULL as an empty array and add the corresponding testcase + + gi/pygi-marshal-to-py.c | 9 +++++---- + tests/test_gi.py | 3 +++ + 2 files changed, 8 insertions(+), 4 deletions(-) + +commit e3451b8e6018bb76e9992fb6af24a71725de5cfd Author: Tomeu Vizoso <tomeu.vizoso@collabora.com> -Date: Fri Dec 23 12:18:00 2011 +0100 +Date: Fri Dec 23 12:01:43 2011 +0100 + + Branching, bump version to 3.1.0 - Merge branch 'master' into pygobject-3-0 + configure.ac | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) commit 8d1a36cc73f5f4df091ecb289c8a7b38ec2ab605 Author: Tomeu Vizoso <tomeu.vizoso@collabora.com> @@ -118,28 +485,6 @@ Date: Thu Dec 1 11:50:38 2011 -0300 pygi-convert.sh | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-) -commit 33060639bc4857238f21c2329b8e8888fbd8fdc2 -Author: Sebastian Pölsterl <sebp@k-d-w.org> -Date: Tue Nov 8 12:38:12 2011 +0100 - - Convert all strings to utf-8 encoding when retrieving from TreeModel - - https://bugzilla.gnome.org/show_bug.cgi?id=663610 - - gi/overrides/Gtk.py | 15 +++++++++++++++ - tests/compathelper.py | 2 ++ - tests/test_overrides.py | 31 ++++++++++++++++++++++++++++++- - 3 files changed, 47 insertions(+), 1 deletions(-) - -commit c9884283153c38f5b200a19b9abfaf6d9e698818 -Author: Sebastian Pölsterl <sebp@k-d-w.org> -Date: Fri Nov 25 18:51:53 2011 +0100 - - Post release version bump - - configure.ac | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - commit 654711d0f940d7480d0f1cdb25a3dc9996f7a706 Author: Sebastian Pölsterl <sebp@k-d-w.org> Date: Tue Nov 8 12:38:12 2011 +0100 @@ -1,7 +1,36 @@ -3.0.4 09-Feb-2012 - - Revert "Convert all strings to utf-8 encoding when retrieving from TreeModel" (Martin Pitt) +3.1.0 06-Feb-2012 + - Updated DOAP file to only include people currently actively working on the project (Sebastian Pölsterl) + - Revert "Convert all strings to utf-8 encoding when retrieving from TreeModel" (Sebastian Pölsterl) + - tests: Fixed issues with python3 (Sebastian Pölsterl) + - Properly distinguish between different integer types for properties (Sebastian Pölsterl) + - Distinguish between GArray and GPtrArray when cleaning up (Sebastian Pölsterl) + - Add null_gerror_callback unit test (Paolo Borelli) + - pyglib_error_check: Re-add missing NULL check (Martin Pitt) + - Add tests/runtests-windows.py to source tarball (Michael Culbertson) + - Don't issue a depreciation warning for GtkDialog's NO_SEPARATOR flag, even when unused (Sebastian Pölsterl) + - Fix bool() operations on GLib.Variant objects (Nirbheek Chauhan) + - Fix hash() and __eq__() for GLib.Variant objects (Nirbheek Chauhan) + - Fix method names of callback tests (Martin Pitt) + - Cairo: add missing braces around array-of-struct definition (Will Thompson) + - g_instance_init: cast to PyGObject * as needed (Will Thompson) + - Fix a few set-but-not-used warnings. (Will Thompson) + - pygmainloop: allow for extra arguments in 'quit' method (Stefano Facchini) + - Fix bytearray test compatibility with python3 (Alexandre Rostovtsev) + - Respect transfer-type when demarshalling GErrors (Alberto Mardegan) + - Support GHashTable and GError as callback/closure arguments (Alberto Mardegan) + - Don't leak when marshalling GErrors to C (Will Thompson) + - Support functions which return GError (Will Thompson) + - Fix indentation of _pygi_argument_to_object() (Alberto Mardegan) + - Avoid C99 syntax. (Paolo Borelli) + - Connect to first action of a radio group. (Paolo Borelli) + - Use g_slist_free_full in pygi-closure. (Paolo Borelli) + - Avoid O(n^2) behavior when marshalling lists (Paolo Borelli) + - Handle NULL as a valid case of a char** array (Paolo Borelli) + - Branching, bump version to 3.1.0 (Tomeu Vizoso) + - Add notes about branching to HACKING (Tomeu Vizoso) - Fixed bug where GObject.property did not respect minimum and maximum values (Sebastian Pölsterl) - Remove mention of removed option --enable-docs (Tomeu Vizoso) + - Fix sebp's name in NEWS (Tomeu Vizoso) 3.0.3 12-Dec-2011 - Convert all modifier constants to Gdk.ModifierType (Manuel Quiñones) @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: PyGObject -Version: 3.0.4 +Version: 3.1.0 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: Johan Dahlin Maintainer-email: johan@gnome.org License: GNU LGPL -Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.0/pygobject-3.0.4.tar.gz +Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.1/pygobject-3.1.0.tar.gz Description: Python bindings for GLib and GObject Platform: POSIX, Windows Classifier: Development Status :: 5 - Production/Stable @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.68 for pygobject 3.0.4. +# Generated by GNU Autoconf 2.68 for pygobject 3.1.0. # # Report bugs to <http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject>. # @@ -571,8 +571,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pygobject' PACKAGE_TARNAME='pygobject' -PACKAGE_VERSION='3.0.4' -PACKAGE_STRING='pygobject 3.0.4' +PACKAGE_VERSION='3.1.0' +PACKAGE_STRING='pygobject 3.1.0' PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject' PACKAGE_URL='' @@ -1359,7 +1359,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.0.4 to adapt to many kinds of systems. +\`configure' configures pygobject 3.1.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1429,7 +1429,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pygobject 3.0.4:";; + short | recursive ) echo "Configuration of pygobject 3.1.0:";; esac cat <<\_ACEOF @@ -1554,7 +1554,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pygobject configure 3.0.4 +pygobject configure 3.1.0 generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. @@ -1832,7 +1832,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.0.4, which was +It was created by pygobject $as_me 3.1.0, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ @@ -2191,14 +2191,14 @@ $as_echo "#define PYGOBJECT_MAJOR_VERSION 3" >>confdefs.h PYGOBJECT_MAJOR_VERSION=3 -$as_echo "#define PYGOBJECT_MINOR_VERSION 0" >>confdefs.h +$as_echo "#define PYGOBJECT_MINOR_VERSION 1" >>confdefs.h -PYGOBJECT_MINOR_VERSION=0 +PYGOBJECT_MINOR_VERSION=1 -$as_echo "#define PYGOBJECT_MICRO_VERSION 4" >>confdefs.h +$as_echo "#define PYGOBJECT_MICRO_VERSION 0" >>confdefs.h -PYGOBJECT_MICRO_VERSION=4 +PYGOBJECT_MICRO_VERSION=0 ac_config_headers="$ac_config_headers config.h" @@ -2682,7 +2682,7 @@ fi # Define the identity of the package. PACKAGE='pygobject' - VERSION='3.0.4' + VERSION='3.1.0' cat >>confdefs.h <<_ACEOF @@ -12018,7 +12018,7 @@ Usage: $0 [OPTIONS] Report bugs to <bug-libtool@gnu.org>." lt_cl_version="\ -pygobject config.lt 3.0.4 +pygobject config.lt 3.1.0 configured by $0, generated by GNU Autoconf 2.68. Copyright (C) 2010 Free Software Foundation, Inc. @@ -16727,7 +16727,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.0.4, which was +This file was extended by pygobject $as_me 3.1.0, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16793,7 +16793,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.0.4 +pygobject config.status 3.1.0 configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index 20256ec..d7fb8a8 100644 --- a/configure.ac +++ b/configure.ac @@ -11,8 +11,8 @@ m4_define(python3_min_ver, 3.1) dnl the pygobject version number m4_define(pygobject_major_version, 3) -m4_define(pygobject_minor_version, 0) -m4_define(pygobject_micro_version, 4) +m4_define(pygobject_minor_version, 1) +m4_define(pygobject_micro_version, 0) m4_define(pygobject_version, pygobject_major_version.pygobject_minor_version.pygobject_micro_version) dnl versions of packages we require ... diff --git a/gi/_glib/pygiochannel.c b/gi/_glib/pygiochannel.c index 4f77e28..3921cac 100644 --- a/gi/_glib/pygiochannel.c +++ b/gi/_glib/pygiochannel.c @@ -477,7 +477,7 @@ py_io_channel_add_watch(PyObject *self, PyObject *args, PyObject *kwargs) data->user_data = user_data; Py_XINCREF(user_data); data->iochannel = self; Py_INCREF(self); - handler_id = g_io_add_watch_full(((PyGIOChannel *) self)->channel, + handler_id = g_io_add_watch_full(iochannel, priority, condition, pyg_iowatch_marshal, data, (GDestroyNotify) pyg_iowatch_data_free); diff --git a/gi/_glib/pyglib.c b/gi/_glib/pyglib.c index f127fb4..40df53b 100644 --- a/gi/_glib/pyglib.c +++ b/gi/_glib/pyglib.c @@ -233,30 +233,28 @@ pyglib_set_thread_block_funcs (PyGLibThreadBlockFunc block_threads_func, _PyGLib_API->unblock_threads = unblock_threads_func; } - /** - * pyglib_error_check: + * pyglib_error_marshal: * @error: a pointer to the GError. * - * Checks to see if the GError has been set. If the error has been - * set, then the glib.GError Python exception will be raised, and - * the GError cleared. + * Checks to see if @error has been set. If @error has been set, then a + * GLib.GError Python exception object is returned (but not raised). * - * Returns: True if an error was set. + * Returns: a GLib.GError Python exception object, or NULL. */ -gboolean -pyglib_error_check(GError **error) +PyObject * +pyglib_error_marshal (GError **error) { PyGILState_STATE state; PyObject *exc_type; PyObject *exc_instance; PyObject *d; - g_return_val_if_fail(error != NULL, FALSE); + g_return_val_if_fail(error != NULL, NULL); if (*error == NULL) - return FALSE; - + return NULL; + state = pyglib_gil_state_ensure(); exc_type = _PyGLib_API->gerror_exception; @@ -289,7 +287,35 @@ pyglib_error_check(GError **error) } else { PyObject_SetAttrString(exc_instance, "message", Py_None); } + + pyglib_gil_state_release(state); + return exc_instance; +} + +/** + * pyglib_error_check: + * @error: a pointer to the GError. + * + * Checks to see if the GError has been set. If the error has been + * set, then the glib.GError Python exception will be raised, and + * the GError cleared. + * + * Returns: True if an error was set. + */ +gboolean +pyglib_error_check(GError **error) +{ + PyGILState_STATE state; + PyObject *exc_instance; + + g_return_val_if_fail(error != NULL, FALSE); + if (*error == NULL) + return FALSE; + + state = pyglib_gil_state_ensure(); + + exc_instance = pyglib_error_marshal (error); PyErr_SetObject(_PyGLib_API->gerror_exception, exc_instance); Py_DECREF(exc_instance); g_clear_error(error); @@ -339,6 +365,7 @@ pyglib_gerror_exception_check(GError **error) py_message = PyObject_GetAttrString(value, "message"); if (!py_message || !PYGLIB_PyUnicode_Check(py_message)) { bad_gerror_message = "gi._glib.GError instances must have a 'message' string attribute"; + Py_XDECREF(py_message); goto bad_gerror; } @@ -346,6 +373,7 @@ pyglib_gerror_exception_check(GError **error) if (!py_domain || !PYGLIB_PyUnicode_Check(py_domain)) { bad_gerror_message = "gi._glib.GError instances must have a 'domain' string attribute"; Py_DECREF(py_message); + Py_XDECREF(py_domain); goto bad_gerror; } @@ -354,6 +382,7 @@ pyglib_gerror_exception_check(GError **error) bad_gerror_message = "gi._glib.GError instances must have a 'code' int attribute"; Py_DECREF(py_message); Py_DECREF(py_domain); + Py_XDECREF(py_code); goto bad_gerror; } diff --git a/gi/_glib/pyglib.h b/gi/_glib/pyglib.h index 44ead47..261af7b 100644 --- a/gi/_glib/pyglib.h +++ b/gi/_glib/pyglib.h @@ -37,6 +37,7 @@ PyGILState_STATE pyglib_gil_state_ensure(void); void pyglib_gil_state_release(PyGILState_STATE state); int pyglib_enable_threads(void); gboolean pyglib_error_check(GError **error); +PyObject *pyglib_error_marshal (GError **error); gboolean pyglib_gerror_exception_check(GError **error); PyObject *pyglib_register_exception_for_domain(gchar *name, gint error_domain); diff --git a/gi/_glib/pygmainloop.c b/gi/_glib/pygmainloop.c index 43dcf92..5dabef6 100644 --- a/gi/_glib/pygmainloop.c +++ b/gi/_glib/pygmainloop.c @@ -158,9 +158,8 @@ pyg_signal_watch_check(GSource *source) PySignalWatchSource *real_source = (PySignalWatchSource *)source; GPollFD *poll_fd = &real_source->fd; unsigned char dummy; - gssize ret; if (poll_fd->revents & G_IO_IN) - ret = read(poll_fd->fd, &dummy, 1); + (void) read(poll_fd->fd, &dummy, 1); #endif state = pyglib_gil_state_ensure(); @@ -315,7 +314,7 @@ _wrap_g_main_loop_is_running (PyGMainLoop *self) } static PyObject * -_wrap_g_main_loop_quit (PyGMainLoop *self) +_wrap_g_main_loop_quit (PyGMainLoop *self, PyObject *args, PyObject *kwargs) { g_main_loop_quit(self->loop); @@ -346,7 +345,7 @@ _wrap_g_main_loop_run (PyGMainLoop *self) static PyMethodDef _PyGMainLoop_methods[] = { { "get_context", (PyCFunction)_wrap_g_main_loop_get_context, METH_NOARGS }, { "is_running", (PyCFunction)_wrap_g_main_loop_is_running, METH_NOARGS }, - { "quit", (PyCFunction)_wrap_g_main_loop_quit, METH_NOARGS }, + { "quit", (PyCFunction)_wrap_g_main_loop_quit, METH_VARARGS|METH_KEYWORDS }, { "run", (PyCFunction)_wrap_g_main_loop_run, METH_NOARGS }, { NULL, NULL, 0 } }; diff --git a/gi/_gobject/gobjectmodule.c b/gi/_gobject/gobjectmodule.c index ac065a5..7ac31f6 100644 --- a/gi/_gobject/gobjectmodule.c +++ b/gi/_gobject/gobjectmodule.c @@ -1070,7 +1070,7 @@ pygobject__g_instance_init(GTypeInstance *instance, /* float the wrapper ref here because we are going to orphan it * so we don't destroy the wrapper. The next call to pygobject_new_full * will take the ref */ - pygobject_ref_float (wrapper); + pygobject_ref_float ((PyGObject *) wrapper); args = PyTuple_New(0); kwargs = PyDict_New(); if (Py_TYPE(wrapper)->tp_init(wrapper, args, kwargs)) diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c index 0f0e5e2..8020b40 100644 --- a/gi/_gobject/pygobject.c +++ b/gi/_gobject/pygobject.c @@ -1275,7 +1275,7 @@ pygobject_get_properties(PyGObject *self, PyObject *args) property_name = PYGLIB_PyUnicode_AsString(py_property); - pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(self->obj), + pspec = g_object_class_find_property(class, property_name); if (!pspec) { PyErr_Format(PyExc_TypeError, diff --git a/gi/gimodule.c b/gi/gimodule.c index 873a56e..1961c17 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -60,8 +60,9 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, GIEnumInfo *info; gint n_values; GEnumValue *g_enum_values; - GType g_type; + int i; const gchar *type_name; + GType g_type; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O:enum_add_make_new_gtype", @@ -79,7 +80,7 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, n_values = g_enum_info_get_n_values (info); g_enum_values = g_new0 (GEnumValue, n_values + 1); - for (int i=0; i < n_values; i++) { + for (i = 0; i < n_values; i++) { GIValueInfo *value_info; GEnumValue *enum_value; const gchar *name; @@ -147,8 +148,9 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, GIEnumInfo *info; gint n_values; GFlagsValue *g_flags_values; - GType g_type; + int i; const gchar *type_name; + GType g_type; if (!PyArg_ParseTupleAndKeywords (args, kwargs, "O:flags_add_make_new_gtype", @@ -166,7 +168,7 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, n_values = g_enum_info_get_n_values (info); g_flags_values = g_new0 (GFlagsValue, n_values + 1); - for (int i=0; i < n_values; i++) { + for (i = 0; i < n_values; i++) { GIValueInfo *value_info; GFlagsValue *flags_value; const gchar *name; diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py index f3abe28..27fe017 100644 --- a/gi/overrides/GLib.py +++ b/gi/overrides/GLib.py @@ -172,6 +172,24 @@ class Variant(GLib.Variant): def __repr__(self): return '<GLib.Variant(%s)>' % getattr(self, 'print')(True) + def __eq__(self, other): + try: + return self.equal(other) + except TypeError: + return False + + def __ne__(self, other): + try: + return not self.equal(other) + except TypeError: + return True + + def __hash__(self): + # We're not using just hash(self.unpack()) because otherwise we'll have + # hash collisions between the same content in different variant types, + # which will cause a performance issue in set/dict/etc. + return hash((self.get_type_string(), self.unpack())) + def unpack(self): '''Decompose a GVariant into a native Python object.''' @@ -277,6 +295,7 @@ class Variant(GLib.Variant): def __len__(self): if self.get_type_string() in ['s', 'o', 'g']: return len(self.get_string()) + # Array, dict, tuple if self.get_type_string().startswith('a') or self.get_type_string().startswith('('): return self.n_children() raise TypeError('GVariant type %s does not have a length' % self.get_type_string()) @@ -314,6 +333,28 @@ class Variant(GLib.Variant): raise TypeError('GVariant type %s is not a container' % self.get_type_string()) + # + # Pythonic bool operations + # + def __nonzero__(self): + return self.__bool__() + + def __bool__(self): + if self.get_type_string() in ['y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd']: + return self.unpack() != 0 + if self.get_type_string() in ['b']: + return self.get_boolean() + if self.get_type_string() in ['s', 'o', 'g']: + return len(self.get_string()) != 0 + # Array, dict, tuple + if self.get_type_string().startswith('a') or self.get_type_string().startswith('('): + return self.n_children() != 0 + if self.get_type_string() in ['v']: + # unpack works recursively, hence bool also works recursively + return bool(self.unpack()) + # Everything else is True + return True + def keys(self): if not self.get_type_string().startswith('a{'): return TypeError, 'GVariant type %s is not a dictionary' % self.get_type_string() diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index 7945cc8..1d0cb49 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -276,9 +276,9 @@ class ActionGroup(Gtk.ActionGroup): if first_action is not None and on_change is not None: if user_data is None: - action.connect('changed', on_change) + first_action.connect('changed', on_change) else: - action.connect('changed', on_change, user_data) + first_action.connect('changed', on_change, user_data) ActionGroup = override(ActionGroup) __all__.append('ActionGroup') @@ -411,10 +411,8 @@ class Dialog(Gtk.Dialog, Container): self.set_destroy_with_parent(True) # NO_SEPARATOR has been removed from Gtk 3 - try: - if flags & Gtk.DialogFlags.NO_SEPARATOR: - self.set_has_separator(False) - except AttributeError: + if hasattr(Gtk.DialogFlags, "NO_SEPARATOR") and (flags & Gtk.DialogFlags.NO_SEPARATOR): + self.set_has_separator(False) import warnings warnings.warn("Gtk.DialogFlags.NO_SEPARATOR has been depricated since Gtk+-3.0", DeprecationWarning) diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 3b36c2f..9d99c35 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -1785,19 +1785,29 @@ _pygi_argument_to_object (GIArgument *arg, break; } case GI_TYPE_TAG_ERROR: - if (pyglib_error_check ( (GError **) &arg->v_pointer)) { - PyObject *err_type; - PyObject *err_value; - PyObject *err_trace; - PyErr_Fetch (&err_type, &err_value, &err_trace); - Py_XDECREF (err_type); - Py_XDECREF (err_trace); - object = err_value; - } else { - object = Py_None; - Py_INCREF (object); - break; - } + { + GError *error = (GError *) arg->v_pointer; + if (error != NULL && transfer == GI_TRANSFER_NOTHING) { + /* If we have not been transferred the ownership we must copy + * the error, because pyglib_error_check() is going to free it. + */ + error = g_error_copy (error); + } + + if (pyglib_error_check (&error)) { + PyObject *err_type; + PyObject *err_value; + PyObject *err_trace; + PyErr_Fetch (&err_type, &err_value, &err_trace); + Py_XDECREF (err_type); + Py_XDECREF (err_trace); + object = err_value; + } else { + object = Py_None; + Py_INCREF (object); + break; + } + } } return object; diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c index f770b20..6fc08fb 100644 --- a/gi/pygi-closure.c +++ b/gi/pygi-closure.c @@ -163,6 +163,8 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) g_base_info_unref (interface); } + case GI_TYPE_TAG_ERROR: + case GI_TYPE_TAG_GHASH: case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: g_args[i].v_pointer = * (gpointer *) args[i]; @@ -421,8 +423,7 @@ _pygi_make_native_closure (GICallableInfo* info, ffi_closure *fficlosure; /* Begin by cleaning up old async functions */ - g_slist_foreach (async_free_list, (GFunc) _pygi_invoke_closure_free, NULL); - g_slist_free (async_free_list); + g_slist_free_full (async_free_list, (GDestroyNotify) _pygi_invoke_closure_free); async_free_list = NULL; /* Build the closure itself */ diff --git a/gi/pygi-foreign-cairo.c b/gi/pygi-foreign-cairo.c index c6303f8..4e12df3 100644 --- a/gi/pygi-foreign-cairo.c +++ b/gi/pygi-foreign-cairo.c @@ -112,7 +112,7 @@ cairo_surface_release (GIBaseInfo *base_info, Py_RETURN_NONE; } -static PyMethodDef _gi_cairo_functions[] = {0,}; +static PyMethodDef _gi_cairo_functions[] = { {0,} }; PYGLIB_MODULE_START(_gi_cairo, "_gi_cairo") { #if PY_VERSION_HEX < 0x03000000 diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c index f80ebfa..e65731a 100644 --- a/gi/pygi-marshal-cleanup.c +++ b/gi/pygi-marshal-cleanup.c @@ -311,7 +311,8 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, gboolean was_processed) { if (was_processed) { - GArray *array_; + GArray *array_ = NULL; + GPtrArray *ptr_array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; /* If this isn't a garray create one to help process variable sized @@ -322,6 +323,8 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, if (array_ == NULL) return; + } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { + ptr_array_ = (GPtrArray *) data; } else { array_ = (GArray *) data; } @@ -329,13 +332,14 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, /* clean up items first */ if (sequence_cache->item_cache->from_py_cleanup != NULL) { gsize i; + guint len = (array_ != NULL) ? array_->len : ptr_array_->len; PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->from_py_cleanup; - for(i = 0; i < array_->len; i++) { + for(i = 0; i < len; i++) { cleanup_func (state, sequence_cache->item_cache, - g_array_index (array_, gpointer, i), + (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i), TRUE); } } @@ -345,7 +349,10 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING); } else if (state->failed || arg_cache->transfer == GI_TRANSFER_NOTHING) { - g_array_free (array_, TRUE); + if (array_ != NULL) + g_array_free (array_, TRUE); + else + g_ptr_array_free (ptr_array_, TRUE); } } } @@ -356,11 +363,10 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state, gpointer data, gboolean was_processed) { - PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; - if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER) { - GArray *array_; + GArray *array_ = NULL; + GPtrArray *ptr_array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; /* If this isn't a garray create one to help process variable sized @@ -370,24 +376,30 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state, if (array_ == NULL) return; - + + } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { + ptr_array_ = (GPtrArray *) data; } else { array_ = (GArray *) data; } if (sequence_cache->item_cache->to_py_cleanup != NULL) { gsize i; + guint len = (array_ != NULL) ? array_->len : ptr_array_->len; PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup; - for (i = 0; i < array_->len; i++) { + for (i = 0; i < len; i++) { cleanup_func (state, sequence_cache->item_cache, - g_array_index (array_, gpointer, i), + (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i), was_processed); } } - g_array_free (array_, TRUE); + if (array_ != NULL) + g_array_free (array_, TRUE); + else + g_ptr_array_free (ptr_array_, TRUE); } } diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index 3b3109c..4de874b 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -959,7 +959,7 @@ _pygi_marshal_from_py_glist (PyGIInvokeState *state, &item)) goto err; - list_ = g_list_append (list_, item.v_pointer); + list_ = g_list_prepend (list_, item.v_pointer); continue; err: /* FIXME: clean up list @@ -972,7 +972,7 @@ err: return FALSE; } - arg->v_pointer = list_; + arg->v_pointer = g_list_reverse (list_); return TRUE; } @@ -1026,7 +1026,7 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState *state, &item)) goto err; - list_ = g_slist_append (list_, item.v_pointer); + list_ = g_slist_prepend (list_, item.v_pointer); continue; err: /* FIXME: Clean up list @@ -1040,7 +1040,7 @@ err: return FALSE; } - arg->v_pointer = list_; + arg->v_pointer = g_slist_reverse (list_); return TRUE; } diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c index 1e4a8aa..4b99278 100644 --- a/gi/pygi-marshal-to-py.c +++ b/gi/pygi-marshal-to-py.c @@ -26,6 +26,7 @@ #include <string.h> #include <time.h> +#include <pyglib.h> #include <pygobject.h> #include <pyglib-python-compat.h> @@ -264,8 +265,6 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; gsize processed_items = 0; - array_ = arg->v_pointer; - /* GArrays make it easier to iterate over arrays * with different element sizes but requires that * we allocate a GArray if the argument was a C array @@ -276,8 +275,9 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, g_assert(arg->v_pointer != NULL); len = seq_cache->fixed_size; } else if (seq_cache->is_zero_terminated) { - g_assert(arg->v_pointer != NULL); - if(seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) { + if (arg->v_pointer == NULL) { + len = 0; + } else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) { len = strlen (arg->v_pointer); } else { len = g_strv_length ((gchar **)arg->v_pointer); @@ -303,6 +303,8 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, g_free (array_->data); array_->data = arg->v_pointer; array_->len = len; + } else { + array_ = arg->v_pointer; } if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) { @@ -597,11 +599,20 @@ _pygi_marshal_to_py_gerror (PyGIInvokeState *state, PyGIArgCache *arg_cache, GIArgument *arg) { + GError *error = arg->v_pointer; PyObject *py_obj = NULL; - PyErr_Format (PyExc_NotImplementedError, - "Marshalling for gerror to PyObject is not implemented"); - return py_obj; + py_obj = pyglib_error_marshal(&error); + + if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && error != NULL) { + g_error_free (error); + } + + if (py_obj != NULL) { + return py_obj; + } else { + Py_RETURN_NONE; + } } PyObject * diff --git a/gi/pygi-property.c b/gi/pygi-property.c index 2f8970d..f400820 100644 --- a/gi/pygi-property.c +++ b/gi/pygi-property.c @@ -121,16 +121,36 @@ pygi_get_property_value_real (PyGObject *instance, arg.v_boolean = g_value_get_boolean (&value); break; case GI_TYPE_TAG_INT8: + arg.v_int8 = g_value_get_schar (&value); + break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_INT32: + if (G_VALUE_HOLDS_LONG (&value)) + arg.v_long = g_value_get_long (&value); + else + arg.v_int = g_value_get_int (&value); + break; case GI_TYPE_TAG_INT64: - arg.v_int = g_value_get_int (&value); + if (G_VALUE_HOLDS_LONG (&value)) + arg.v_long = g_value_get_long (&value); + else + arg.v_int64 = g_value_get_int64 (&value); break; case GI_TYPE_TAG_UINT8: + arg.v_uint8 = g_value_get_uchar (&value); + break; case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_UINT32: + if (G_VALUE_HOLDS_ULONG (&value)) + arg.v_ulong = g_value_get_ulong (&value); + else + arg.v_uint = g_value_get_uint (&value); + break; case GI_TYPE_TAG_UINT64: - arg.v_uint = g_value_get_uint (&value); + if (G_VALUE_HOLDS_ULONG (&value)) + arg.v_ulong = g_value_get_ulong (&value); + else + arg.v_uint64 = g_value_get_uint64 (&value); break; case GI_TYPE_TAG_FLOAT: arg.v_float = g_value_get_float (&value); @@ -296,16 +316,36 @@ pygi_set_property_value_real (PyGObject *instance, g_value_set_boolean (&value, arg.v_boolean); break; case GI_TYPE_TAG_INT8: + g_value_set_schar (&value, arg.v_int8); + break; case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_INT32: + if (G_VALUE_HOLDS_LONG (&value)) + g_value_set_long (&value, arg.v_long); + else + g_value_set_int (&value, arg.v_int); + break; case GI_TYPE_TAG_INT64: - g_value_set_int (&value, arg.v_int); + if (G_VALUE_HOLDS_LONG (&value)) + g_value_set_long (&value, arg.v_long); + else + g_value_set_int64 (&value, arg.v_int64); break; case GI_TYPE_TAG_UINT8: + g_value_set_uchar (&value, arg.v_uint8); + break; case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_UINT32: + if (G_VALUE_HOLDS_ULONG (&value)) + g_value_set_ulong (&value, arg.v_ulong); + else + g_value_set_uint (&value, arg.v_uint); + break; case GI_TYPE_TAG_UINT64: - g_value_set_uint (&value, arg.v_uint); + if (G_VALUE_HOLDS_ULONG (&value)) + g_value_set_ulong (&value, arg.v_ulong); + else + g_value_set_uint64 (&value, arg.v_uint64); break; case GI_TYPE_TAG_FLOAT: g_value_set_float (&value, arg.v_float); diff --git a/tests/Makefile.am b/tests/Makefile.am index 4ec6477..06d4768 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -87,6 +87,7 @@ TEST_FILES_GI = \ EXTRA_DIST = \ compathelper.py \ runtests.py \ + runtests-windows.py \ testmodule.py \ test-floating.h \ test-thread.h \ diff --git a/tests/Makefile.in b/tests/Makefile.in index f0b3f95..e27fb71 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -303,9 +303,9 @@ TEST_FILES_GI = \ test_gdbus.py \ test_overrides.py -EXTRA_DIST = compathelper.py runtests.py testmodule.py test-floating.h \ - test-thread.h test-unknown.h te_ST@nouppera \ - org.gnome.test.gschema.xml $(TEST_FILES_STATIC) \ +EXTRA_DIST = compathelper.py runtests.py runtests-windows.py \ + testmodule.py test-floating.h test-thread.h test-unknown.h \ + te_ST@nouppera org.gnome.test.gschema.xml $(TEST_FILES_STATIC) \ $(TEST_FILES_GI) DBUS_LAUNCH = $(shell which dbus-launch) RUN_TESTS_ENV_VARS = \ diff --git a/tests/runtests-windows.py b/tests/runtests-windows.py new file mode 100644 index 0000000..ae81202 --- /dev/null +++ b/tests/runtests-windows.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + + +import os +import sys +import glob +import unittest + +os.environ['PYGTK_USE_GIL_STATE_API'] = '' +sys.path.insert(0, os.path.dirname(__file__)) +sys.argv.append('--g-fatal-warnings') + +from gi.repository import GObject +GObject.threads_init() + + +SKIP_FILES = ['runtests', + 'test_mainloop', # no os.fork on windows + 'test_subprocess'] # blocks on testChildWatch + + +if __name__ == '__main__': + testdir = os.path.split(os.path.abspath(__file__))[0] + os.chdir(testdir) + + def gettestnames(): + files = glob.glob('*.py') + names = map(lambda x: x[:-3], files) + map(names.remove, SKIP_FILES) + return names + + suite = unittest.TestSuite() + loader = unittest.TestLoader() + + for name in gettestnames(): + try: + suite.addTest(loader.loadTestsFromName(name)) + except Exception, e: + print 'Could not load %s: %s' % (name, e) + + testRunner = unittest.TextTestRunner() + testRunner.verbosity = 2 + testRunner.run(suite) diff --git a/tests/test_everything.py b/tests/test_everything.py index 43735e5..82edfcf 100644 --- a/tests/test_everything.py +++ b/tests/test_everything.py @@ -12,6 +12,7 @@ import cairo from gi.repository import GObject from gi.repository import GLib +from gi.repository import Gio from gi.repository import Regress as Everything if sys.version_info < (3, 0): @@ -201,7 +202,7 @@ class TestCallbacks(unittest.TestCase): called = False main_loop = GObject.MainLoop() - def testCallback(self): + def test_callback(self): TestCallbacks.called = False def callback(): TestCallbacks.called = True @@ -209,7 +210,7 @@ class TestCallbacks(unittest.TestCase): Everything.test_simple_callback(callback) self.assertTrue(TestCallbacks.called) - def testCallbackException(self): + def test_callback_exception(self): """ This test ensures that we get errors from callbacks correctly and in particular that we do not segv when callbacks fail @@ -222,7 +223,7 @@ class TestCallbacks(unittest.TestCase): except ZeroDivisionError: pass - def testDoubleCallbackException(self): + def test_double_callback_exception(self): """ This test ensures that we get errors from callbacks correctly and in particular that we do not segv when callbacks fail @@ -240,7 +241,7 @@ class TestCallbacks(unittest.TestCase): except ZeroDivisionError: pass - def testReturnValueCallback(self): + def test_return_value_callback(self): TestCallbacks.called = False def callback(): TestCallbacks.called = True @@ -249,7 +250,7 @@ class TestCallbacks(unittest.TestCase): self.assertEquals(Everything.test_callback(callback), 44) self.assertTrue(TestCallbacks.called) - def testCallbackAsync(self): + def test_callback_async(self): TestCallbacks.called = False def callback(foo): TestCallbacks.called = True @@ -260,7 +261,7 @@ class TestCallbacks(unittest.TestCase): self.assertEquals(44, i); self.assertTrue(TestCallbacks.called) - def testCallbackScopeCall(self): + def test_callback_scope_call(self): TestCallbacks.called = 0 def callback(): TestCallbacks.called += 1 @@ -269,7 +270,7 @@ class TestCallbacks(unittest.TestCase): Everything.test_multi_callback(callback) self.assertEquals(TestCallbacks.called, 2) - def testCallbackUserdata(self): + def test_callback_userdata(self): TestCallbacks.called = 0 def callback(userdata): self.assertEquals(userdata, "Test%d" % TestCallbacks.called) @@ -282,7 +283,7 @@ class TestCallbacks(unittest.TestCase): self.assertEquals(TestCallbacks.called, 100) - def testCallbackUserdataRefCount(self): + def test_callback_userdata_refcount(self): TestCallbacks.called = False def callback(userdata): TestCallbacks.called = True @@ -299,7 +300,7 @@ class TestCallbacks(unittest.TestCase): self.assertEquals(start_ref_count, end_ref_count) - def testAsyncReadyCallback(self): + def test_async_ready_callback(self): TestCallbacks.called = False TestCallbacks.main_loop = GObject.MainLoop() @@ -313,7 +314,7 @@ class TestCallbacks(unittest.TestCase): self.assertTrue(TestCallbacks.called) - def testCallbackDestroyNotify(self): + def test_callback_destroy_notify(self): def callback(user_data): TestCallbacks.called = True return 42 @@ -323,7 +324,7 @@ class TestCallbacks(unittest.TestCase): self.assertTrue(TestCallbacks.called) self.assertEquals(Everything.test_callback_thaw_notifications(), 42) - def testCallbackInMethods(self): + def test_callback_in_methods(self): object_ = Everything.TestObj() def callback(): @@ -346,10 +347,53 @@ class TestCallbacks(unittest.TestCase): obj_ = Everything.TestObj.new_callback(callbackWithUserData, None) self.assertTrue(TestCallbacks.called) - def testCallbackNone(self): + def test_callback_none(self): # make sure this doesn't assert or crash Everything.test_simple_callback(None) + def test_callback_gerror(self): + def callback(error): + self.assertEqual(error.message, 'regression test error') + self.assertTrue('g-io' in error.domain) + self.assertEqual(error.code, Gio.IOErrorEnum.NOT_SUPPORTED) + TestCallbacks.called = True + + TestCallbacks.called = False + Everything.test_gerror_callback(callback) + self.assertTrue(TestCallbacks.called) + + def test_callback_null_gerror(self): + def callback(error): + self.assertEqual(error, None) + TestCallbacks.called = True + + TestCallbacks.called = False + Everything.test_null_gerror_callback(callback) + self.assertTrue(TestCallbacks.called) + + def test_callback_owned_gerror(self): + def callback(error): + self.assertEqual(error.message, 'regression test owned error') + self.assertTrue('g-io' in error.domain) + self.assertEqual(error.code, Gio.IOErrorEnum.PERMISSION_DENIED) + TestCallbacks.called = True + + TestCallbacks.called = False + Everything.test_owned_gerror_callback(callback) + self.assertTrue(TestCallbacks.called) + + def test_callback_hashtable(self): + def callback(data): + self.assertEqual(data, mydict) + mydict['new'] = 42 + TestCallbacks.called = True + + mydict = { 'foo': 1, 'bar': 2 } + TestCallbacks.called = False + Everything.test_hash_table_callback(mydict, callback) + self.assertTrue(TestCallbacks.called) + self.assertEqual(mydict, { 'foo': 1, 'bar': 2, 'new': 42 }) + class TestClosures(unittest.TestCase): def test_int_arg(self): def callback(num): diff --git a/tests/test_gi.py b/tests/test_gi.py index 0a9b1b2..b066626 100644 --- a/tests/test_gi.py +++ b/tests/test_gi.py @@ -743,6 +743,9 @@ class TestArray(unittest.TestCase): def test_array_zero_terminated_return(self): self.assertEquals(['0', '1', '2'], GIMarshallingTests.array_zero_terminated_return()) + def test_array_zero_terminated_return_null(self): + self.assertEquals([], GIMarshallingTests.array_zero_terminated_return_null()) + def test_array_zero_terminated_in(self): GIMarshallingTests.array_zero_terminated_in(Sequence(['0', '1', '2'])) @@ -772,19 +775,22 @@ class TestArray(unittest.TestCase): def test_array_gvariant_none_in(self): v = [GLib.Variant("i", 27), GLib.Variant("s", "Hello")] - self.assertEquals([27, "Hello"], map(GLib.Variant.unpack, GIMarshallingTests.array_gvariant_none_in(v))) + returned = [GLib.Variant.unpack(r) for r in GIMarshallingTests.array_gvariant_none_in(v)] + self.assertEquals([27, "Hello"], returned) def test_array_gvariant_container_in(self): v = [GLib.Variant("i", 27), GLib.Variant("s", "Hello")] - self.assertEquals([27, "Hello"], map(GLib.Variant.unpack, GIMarshallingTests.array_gvariant_none_in(v))) + returned = [GLib.Variant.unpack(r) for r in GIMarshallingTests.array_gvariant_none_in(v)] + self.assertEquals([27, "Hello"], returned) def test_array_gvariant_full_in(self): v = [GLib.Variant("i", 27), GLib.Variant("s", "Hello")] - self.assertEquals([27, "Hello"], map(GLib.Variant.unpack, GIMarshallingTests.array_gvariant_none_in(v))) + returned = [GLib.Variant.unpack(r) for r in GIMarshallingTests.array_gvariant_none_in(v)] + self.assertEquals([27, "Hello"], returned) def test_bytearray_gvariant(self): - v = GLib.Variant.new_bytestring("foo") - self.assertEquals(v.get_bytestring(), "foo") + v = GLib.Variant.new_bytestring(b"foo") + self.assertEquals(v.get_bytestring(), b"foo") class TestGArray(unittest.TestCase): @@ -1826,6 +1832,38 @@ class TestGErrorArrayInCrash(unittest.TestCase): def test_gerror_array_in_crash(self): self.assertRaises(GObject.GError, GIMarshallingTests.gerror_array_in, [1, 2, 3]) +class TestGErrorOut(unittest.TestCase): + # See https://bugzilla.gnome.org/show_bug.cgi?id=666098 + def test_gerror_out(self): + error, debug = GIMarshallingTests.gerror_out() + + self.assertIsInstance(error, GObject.GError) + self.assertEquals(error.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN) + self.assertEquals(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE) + self.assertEquals(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE) + self.assertEquals(debug, GIMarshallingTests.CONSTANT_GERROR_DEBUG_MESSAGE) + +class TestGErrorOutTransferNone(unittest.TestCase): + # See https://bugzilla.gnome.org/show_bug.cgi?id=666098 + def test_gerror_out_transfer_none(self): + error, debug = GIMarshallingTests.gerror_out_transfer_none() + + self.assertIsInstance(error, GObject.GError) + self.assertEquals(error.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN) + self.assertEquals(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE) + self.assertEquals(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE) + self.assertEquals(GIMarshallingTests.CONSTANT_GERROR_DEBUG_MESSAGE, debug) + +class TestGErrorReturn(unittest.TestCase): + # See https://bugzilla.gnome.org/show_bug.cgi?id=666098 + def test_return_gerror(self): + error = GIMarshallingTests.gerror_return() + + self.assertIsInstance(error, GObject.GError) + self.assertEquals(error.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN) + self.assertEquals(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE) + self.assertEquals(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE) + class TestKeywordArgs(unittest.TestCase): def test_calling(self): kw_func = GIMarshallingTests.int_three_in_three_out @@ -1883,3 +1921,65 @@ class TestKeywordArgs(unittest.TestCase): d2 = d.copy() GIMarshallingTests.int_three_in_three_out(1, c=4, **d) self.assertEqual(d, d2) + +class TestPropertiesObject(unittest.TestCase): + + def setUp(self): + self.obj = GIMarshallingTests.PropertiesObject() + + def test_boolean(self): + self.assertEqual(self.obj.props.some_boolean, False) + self.obj.props.some_boolean = True + self.assertEqual(self.obj.props.some_boolean, True) + + @unittest.expectedFailure + def test_char(self): + # gobject-introspection thinks it has a guint8 type tag, which is wrong + self.assertEqual(self.obj.props.some_char, 0) + self.obj.props.some_char = GObject.G_MAXINT8 + self.assertEqual(self.obj.props.some_char, GObject.G_MAXINT8) + + def test_uchar(self): + self.assertEqual(self.obj.props.some_uchar, 0) + self.obj.props.some_uchar = GObject.G_MAXUINT8 + self.assertEqual(self.obj.props.some_uchar, GObject.G_MAXUINT8) + + def test_int(self): + self.assertEqual(self.obj.props.some_int, 0) + self.obj.props.some_int = GObject.G_MAXINT + self.assertEqual(self.obj.props.some_int, GObject.G_MAXINT) + + def test_uint(self): + self.assertEqual(self.obj.props.some_uint, 0) + self.obj.props.some_uint = GObject.G_MAXUINT + self.assertEqual(self.obj.props.some_uint, GObject.G_MAXUINT) + + def test_long(self): + self.assertEqual(self.obj.props.some_long, 0) + self.obj.props.some_long = GObject.G_MAXLONG + self.assertEqual(self.obj.props.some_long, GObject.G_MAXLONG) + + def test_ulong(self): + self.assertEqual(self.obj.props.some_ulong, 0) + self.obj.props.some_ulong = GObject.G_MAXULONG + self.assertEqual(self.obj.props.some_ulong, GObject.G_MAXULONG) + + def test_int64(self): + self.assertEqual(self.obj.props.some_int64, 0) + self.obj.props.some_int64 = GObject.G_MAXINT64 + self.assertEqual(self.obj.props.some_int64, GObject.G_MAXINT64) + + def test_uint64(self): + self.assertEqual(self.obj.props.some_uint64, 0) + self.obj.props.some_uint64 = GObject.G_MAXUINT64 + self.assertEqual(self.obj.props.some_uint64, GObject.G_MAXUINT64) + + def test_float(self): + self.assertEqual(self.obj.props.some_float, 0) + self.obj.props.some_float = GObject.G_MAXFLOAT + self.assertEqual(self.obj.props.some_float, GObject.G_MAXFLOAT) + + def test_double(self): + self.assertEqual(self.obj.props.some_double, 0) + self.obj.props.some_double = GObject.G_MAXDOUBLE + self.assertEqual(self.obj.props.some_double, GObject.G_MAXDOUBLE) diff --git a/tests/test_overrides.py b/tests/test_overrides.py index 8974273..ea74fb3 100644 --- a/tests/test_overrides.py +++ b/tests/test_overrides.py @@ -347,6 +347,107 @@ class TestGLib(unittest.TestCase): self.assertEqual(GLib.Variant.split_signature('(a{iv}(ii)((ss)a{s(ss)}))'), ['a{iv}', '(ii)', '((ss)a{s(ss)})']) + def test_variant_hash(self): + v1 = GLib.Variant('s', 'somestring') + v2 = GLib.Variant('s', 'somestring') + v3 = GLib.Variant('s', 'somestring2') + + self.assertTrue(v2 in set([v1, v3])) + self.assertTrue(v2 in frozenset([v1, v3])) + self.assertTrue(v2 in {v1: '1', v3:'2' }) + + def test_variant_compare(self): + # Check if identical GVariant are equal + + def assert_equal(vtype, value): + self.assertEqual(GLib.Variant(vtype, value), GLib.Variant(vtype, value)) + + def assert_not_equal(vtype1, value1, vtype2, value2): + self.assertNotEqual(GLib.Variant(vtype1, value1), GLib.Variant(vtype2, value2)) + + numbers = ['y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd'] + for num in numbers: + assert_equal(num, 42) + assert_not_equal(num, 42, num, 41) + assert_not_equal(num, 42, 's', '42') + + assert_equal('s', 'something') + assert_not_equal('s', 'something', 's', 'somethingelse') + assert_not_equal('s', 'something', 'i', 1234) + + assert_equal('g', 'dustybinqhogx') + assert_not_equal('g', 'dustybinqhogx', 'g', 'dustybin') + assert_not_equal('g', 'dustybinqhogx', 'i', 1234) + + assert_equal('o', '/dev/null') + assert_not_equal('o', '/dev/null', 'o', '/dev/zero') + assert_not_equal('o', '/dev/null', 'i', 1234) + + assert_equal('(s)', ('strtuple',)) + assert_not_equal('(s)', ('strtuple',), '(s)', ('strtuple2',)) + + assert_equal('a{si}', {'str': 42}) + assert_not_equal('a{si}', {'str': 42}, 'a{si}', {'str': 43}) + + assert_equal('v', GLib.Variant('i', 42)) + assert_not_equal('v', GLib.Variant('i', 42), 'v', GLib.Variant('i', 43)) + + def test_variant_bool(self): + # Check if the GVariant bool matches the unpacked Pythonic bool + + def assert_equals_bool(vtype, value): + self.assertEqual(bool(GLib.Variant(vtype, value)), bool(value)) + + # simple values + assert_equals_bool('b', True) + assert_equals_bool('b', False) + + numbers = ['y', 'n', 'q', 'i', 'u', 'x', 't', 'h', 'd'] + for number in numbers: + assert_equals_bool(number, 0) + assert_equals_bool(number, 1) + + assert_equals_bool('s', '') + assert_equals_bool('g', '') + assert_equals_bool('s', 'something') + assert_equals_bool('o', '/dev/null') + assert_equals_bool('g', 'dustybinqhogx') + + # arrays + assert_equals_bool('ab', [True]) + assert_equals_bool('ab', [False]) + for number in numbers: + assert_equals_bool('a'+number, []) + assert_equals_bool('a'+number, [0]) + assert_equals_bool('as', []) + assert_equals_bool('as', ['']) + assert_equals_bool('ao', []) + assert_equals_bool('ao', ['/']) + assert_equals_bool('ag', []) + assert_equals_bool('ag', ['']) + assert_equals_bool('aai', [[]]) + + # tuples + assert_equals_bool('()', ()) + for number in numbers: + assert_equals_bool('('+number+')', (0,)) + assert_equals_bool('(s)', ('',)) + assert_equals_bool('(o)', ('/',)) + assert_equals_bool('(g)', ('',)) + assert_equals_bool('(())', ((),)) + + # dictionaries + assert_equals_bool('a{si}', {}) + assert_equals_bool('a{si}', {'': 0}) + + # complex types, always True + assert_equals_bool('(as)', ([],)) + assert_equals_bool('a{s(i)}', {'': (0,)}) + + # variant types, recursive unpacking + assert_equals_bool('v', GLib.Variant('i', 0)) + assert_equals_bool('v', GLib.Variant('i', 1)) + class TestPango(unittest.TestCase): def test_default_font_description(self): |