Imported Upstream version 3.8.0 upstream/3.8.0
authorAnas Nashif <anas.nashif@intel.com>
Mon, 8 Apr 2013 18:50:28 +0000 (11:50 -0700)
committerAnas Nashif <anas.nashif@intel.com>
Mon, 8 Apr 2013 18:50:28 +0000 (11:50 -0700)
78 files changed:
ChangeLog
Makefile.am
Makefile.in
NEWS
PKG-INFO
aclocal.m4
autogen.sh [new file with mode: 0755]
configure
configure.ac
examples/Makefile.in
gi/Makefile.in
gi/__init__.py
gi/_glib/Makefile.in
gi/_glib/pyglib-python-compat.h
gi/_gobject/Makefile.in
gi/_gobject/gobjectmodule.c
gi/_gobject/propertyhelper.py
gi/_gobject/pygenum.c
gi/_gobject/pygflags.c
gi/_gobject/pygobject-private.h
gi/_gobject/pygobject.c
gi/_gobject/pygobject.h
gi/_gobject/pygtype.c
gi/gimodule.c
gi/overrides/GLib.py
gi/overrides/GObject.py
gi/overrides/Gdk.py
gi/overrides/Gtk.py
gi/overrides/Makefile.in
gi/overrides/__init__.py
gi/pygi-argument.c
gi/pygi-argument.h
gi/pygi-boxed.c
gi/pygi-boxed.h
gi/pygi-cache.c
gi/pygi-closure.c
gi/pygi-foreign.c
gi/pygi-info.c
gi/pygi-invoke.c
gi/pygi-marshal-cleanup.c
gi/pygi-marshal-from-py.c
gi/pygi-marshal-from-py.h
gi/pygi-marshal-to-py.c
gi/pygi-marshal-to-py.h
gi/pygi-private.h
gi/pygi-property.c
gi/pygi-repository.c
gi/pygi-signal-closure.c
gi/pygi-source.c
gi/pygi-source.h
gi/pygobject-external.h
gi/pygtkcompat.py
gi/repository/Makefile.in
gi/types.py
pygobject.doap [new file with mode: 0644]
pygtkcompat/Makefile.am
pygtkcompat/Makefile.in
pygtkcompat/generictreemodel.py [new file with mode: 0644]
pygtkcompat/pygtkcompat.py
tests/Makefile.am
tests/Makefile.in
tests/runtests.py
tests/test-thread.c
tests/test_everything.py
tests/test_generictreemodel.py [new file with mode: 0644]
tests/test_gi.py
tests/test_gio.py [moved from tests/test_overrides_gio.py with 60% similarity]
tests/test_glib.py
tests/test_gobject.py
tests/test_gtype.py
tests/test_object_marshaling.py [new file with mode: 0644]
tests/test_overrides_gdk.py
tests/test_overrides_glib.py
tests/test_overrides_gtk.py
tests/test_properties.py
tests/test_signal.py
tests/test_source.py
tests/testhelpermodule.c

index ab16367..4dcf17e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
+commit 5f82e007e2dcdbfd82a20d8c4d54f9cd7b3b77ac
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 25 08:12:10 2013 +0100
+
+    release 3.8.0
+
+ NEWS | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit bb4fa093d59173f68a0b16e10016bafe7cd18f62
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Mar 20 23:45:01 2013 -0700
+
+    tests: Fix incorrect assumption when testing pyglib version
+
+    Replace version test of 3.7.2 with 3.0.0 as it is the only reasonable
+    value that can be used for a future proof unittest here.
+
+ tests/test_glib.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 78b7b0bea3068b81ba67deea4d06b1fb27434841
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 18 14:02:29 2013 +0100
+
+    configure.ac: post-release bump to 3.8.0
+
+ configure.ac | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit defbd63e95faafaa84230f160bc95dad0f55e37d
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 18 14:01:05 2013 +0100
+
+    release 3.7.92
+
+ NEWS | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+commit a0844a896603c5c91bed24cf94106765f0ced74e
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Mar 17 23:22:38 2013 -0700
+
+    Fix stack smasher when marshaling enums as a vfunc return value
+
+    Add special case for marshaling GI_TYPE_TAG_INTERFACE with enum or
+    flag types. Default interfaces to marshal as a pointer.
+    Add explicit cases for GType and Unichar out/return marshaling.
+    Fix leaking of GIBaseInfo when marshaling interface as out arg.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=637832
+
+ gi/pygi-closure.c | 69
+ ++++++++++++++++++++++++++++++++++++++++++++++---------
+ tests/test_gi.py  | 19 +++++++++++++++
+ 2 files changed, 77 insertions(+), 11 deletions(-)
+
+commit 669e15c35213dbce6ceb0a4a3d474aae620910ce
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Mar 17 15:37:09 2013 -0700
+
+    Change base class of PyGIDeprecationWarning based on minor version
+
+    Use RuntimeWarning as the base class of PyGIDeprecationWarning
+    for unstable (odd minor version) and use DeprecationWarning for
+    stable (even minor version). This is so PyGObject deprecations
+    behave the same as regular Python deprecations in stable releases.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=696011
+
+ gi/__init__.py | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+commit 755b2e6fc635489d98d48254ea60b2631b43dfbd
+Author: Alban Browaeys <prahal@yahoo.com>
+Date:   Thu Feb 28 18:57:21 2013 +0100
+
+    autogen.sh: Source gnome-autogen to fix out of source builddir
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=694889
+
+ autogen.sh | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a38392a9d713b0001cf30066d337b1abbbbbc59e
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Mar 5 12:22:15 2013 +0100
+
+    Add 3.7.91.1 NEWS entry
+
+    Forgot to push this back then.
+
+ NEWS | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit 85f8aae849dd0fb21de8722a3af9234ca20ea1e0
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Mar 17 04:19:57 2013 -0700
+
+    pygtkcompat: Make gdk.Window.get_geometry return tuple of 5
+
+    Make get_geometry return a tuple of (x, y, width, height, depth)
+    as it did in pygtk 2.
+    Update pygtkcompat.enable_gtk() to default to version 3.0 because
+    version 2.0 core dumps trying to use introspection with gtk 2.
+
+ pygtkcompat/pygtkcompat.py | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+commit 38683f721c33cc35f0260868e58643fd35f04cbe
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Mar 17 02:08:03 2013 -0700
+
+    testhelpermodule: Fix build warning for PyGObject_Type redefinition
+
+    Remove dynamic retrieval of PyGObject_Type as it is available
+    in pygobject.h since commit 2656bc47 (causing this compile warning)
+
+ tests/testhelpermodule.c | 14 +-------------
+ 1 file changed, 1 insertion(+), 13 deletions(-)
+
+commit a3ec8867945da7722beebb7e77c6255ee3ba8bb8
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Mar 17 01:51:33 2013 -0700
+
+    pygtkcompat: Initialize hint to zero in set_geometry_hints
+
+ pygtkcompat/pygtkcompat.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 471204953d6fc93b3d311afd133d40f7d75ec541
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Mar 15 04:33:22 2013 -0700
+
+    Remove incorrect bounds check with property helper flags
+
+    Remove bounds check for flags as it is not necessary for the
+    helper to make these kind of judgement calls in general.
+    e.g. leave it to marshaling/internals to complain about potential
+    problems. The flags were being bounds checked to a maximum
+    value of 32 (the intention was most likely to limit it to 32 bits).
+
+ gi/_gobject/propertyhelper.py | 3 ---
+ tests/test_properties.py      | 1 -
+ 2 files changed, 4 deletions(-)
+
+commit 2656bc47ca1219b329066da1c2c58018ae624866
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Mar 7 18:07:17 2013 -0800
+
+    Fix crash when setting property of type object to an incorrect type
+
+    Add type check when marshaling an object from Python for GObject
+    types.
+    Add PyGObject_Type as part of the pygobject API to check for this.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=695420
+
+ gi/_gobject/gobjectmodule.c     | 3 ++-
+ gi/_gobject/pygobject.h         | 2 ++
+ gi/pygi-marshal-from-py.c       | 8 ++++++++
+ tests/test_object_marshaling.py | 4 ++++
+ 4 files changed, 16 insertions(+), 1 deletion(-)
+
+commit 44587f42224a44a480629223c8d78a426bc32a12
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Mar 7 17:59:02 2013 -0800
+
+    Remove skipping of object property tests
+
+    These were showing up as unexpected successes now that bug 675726
+    is fixed.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=695420
+
+ tests/test_object_marshaling.py | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+commit 10214ba2d96fd6d66eeea159219f585abff8632a
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Mar 7 15:34:49 2013 -0800
+
+    Give more informative error when setting property to incorrect type
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=695420
+
+ gi/_gobject/pygobject.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+commit 9ab6e5451aea43ed086c0d26324c4efed24476d7
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Mar 5 12:04:55 2013 +0100
+
+    Revert "Drop gi.overrides.overridefunc()"
+
+    This reverts commit 1dc2bc9f65669417ae1964d70b85f115928b2963. External
+    modules
+    like GEdit plugins use @overrides for functions as well, we must
+    not break
+    them.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=695199
+
+ gi/overrides/Gtk.py      |  7 ++++---
+ gi/overrides/__init__.py | 24 ++++++++++++++++++++++--
+ 2 files changed, 26 insertions(+), 5 deletions(-)
+
+commit 862de794bf01a66aa6d796c674bce375cad37ba7
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 17:33:51 2013 +0100
+
+    configure.ac: Post-release bump to 3.7.92
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bb12e652d661cf6ce931b44a89c11951894101bf
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 17:27:50 2013 +0100
+
+    release 3.7.91
+
+ NEWS | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+commit 25a6f90f28b065dd4f1cd352826598577402dc0b
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 17:16:22 2013 +0100
+
+    Dot not clobber original Gdk/Gtk functions with overrides
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=686835
+
+ gi/overrides/Gdk.py | 3 ++-
+ gi/overrides/Gtk.py | 3 ++-
+ 2 files changed, 4 insertions(+), 2 deletions(-)
+
+commit d50d16428edf42799489fe1befbc4ce56f0fa181
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 15:30:31 2013 +0100
+
+    tests: Reorganize GError and GClosure tests
+
+    Split TestGClosure.test_gclosure_in() into its three components.
+
+    Merge the various TestGError* classes into one, to match the structure
+    of the
+    other tests.
+
+ tests/test_gi.py | 59
+ +++++++++++++++++++++++++-------------------------------
+ 1 file changed, 26 insertions(+), 33 deletions(-)
+
+commit 8cfd596c7849bf78a74fee04630fbbb104f02080
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 15:16:25 2013 +0100
+
+    Fix memory leaks in property setting/getting
+
+    Do not leak GValues and string arrays, free them properly. As we
+    always free
+    the intermediate GValues, use g_value_dup_boxed() instead of
+    g_value_get_boxed() when appropriate.
+
+    Detected by test_gi.TestPropertiesObject.test_strv test case.
+
+ gi/pygi-property.c | 21 ++++++++++++++++-----
+ 1 file changed, 16 insertions(+), 5 deletions(-)
+
+commit eec8c3a932d42e92ccaf7f97d3d90948842e263f
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 12:43:24 2013 +0100
+
+    Fix memory leak in pyg_flags_get_value_nicks()
+
+    Discovered by test_gi.TestKeywords.test_uppercase() test.
+
+ gi/_gobject/pygflags.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit 002a834dd993b82508a4fe262269befcf1a6d341
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 12:10:03 2013 +0100
+
+    Fix memory leak in _pygi_argument_to_array()
+
+    Free the originally allocated GArray data before setting it to
+    our already
+    existing C array.
+
+    Discovered by test_gi.TestStructure.test_boxed_struct_return test
+    case.
+
+ gi/pygi-argument.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit d32b410a1b1fcca6d10d75fbd771ea789999da64
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Mar 4 10:19:34 2013 +0100
+
+    Fix leaking inout C arrays
+
+    g_*_info_invoke() changes the original state->in_args and state->args
+    C arrays
+    to the output values for (inout) arguments, thus losing the pointer
+    to the
+    originally allocated array. Remember that in state->args_data,
+    so that we can
+    free it in _pygi_marshal_cleanup_from_py_array().
+
+    Reproduced by test_gi.TestArray.test_array_fixed_inout test case.
+
+ gi/pygi-marshal-cleanup.c | 6 ++++++
+ gi/pygi-marshal-from-py.c | 4 ++++
+ 2 files changed, 10 insertions(+)
+
+commit e4098cbc28ff9324fa851bca2e423da4e51b5091
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Mar 1 15:12:31 2013 +0100
+
+    Fix leak in _PyGI_ERROR_PREFIX()
+
+    Properly clean up our allocated py_error_prefix string.
+
+    Fixes memory leak in e. g. test_gi.TestArray.test_array_fixed_int_in.
+
+ gi/pygi-private.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit b388c3e87ce86d26560337c88eb33d0a95647db8
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Mar 1 15:01:06 2013 +0100
+
+    Fix leaking of boxed array elements
+
+    Commit 631d8ef879a copies struct array elements, but this needlessly
+    duplicates
+    and leaks the array element for boxed types. So only do it for
+    plain structs.
+
+    This fixes the memory leak with
+    test_gi.TestGValue.test_gvalue_flat_array_out.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693402
+
+ gi/pygi-marshal-to-py.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 1dc2bc9f65669417ae1964d70b85f115928b2963
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Mar 1 14:04:34 2013 +0100
+
+    Drop gi.overrides.overridefunc()
+
+    This just adds an unnecessary extra function call and is not really
+    needed.
+    Drop it from the only remaining function which uses this
+    (Gtk.main_quit) and
+    drop overridefunc().
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=686835
+
+ gi/overrides/Gtk.py      |  7 +++----
+ gi/overrides/__init__.py | 24 ++----------------------
+ 2 files changed, 5 insertions(+), 26 deletions(-)
+
+commit 1edc4ba31b3f9375ec3920aab5b71eb066ee3739
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Mar 1 14:02:02 2013 +0100
+
+    Add some tests for overridden Gdk/Gtk functions
+
+    Add tests for Gtk.main_quit, Gtk.stock_parse(), and Gdk.color_parse(),
+    as we
+    have overrides for them.
+
+ tests/test_overrides_gdk.py |  7 +++++++
+ tests/test_overrides_gtk.py | 15 +++++++++++++++
+ 2 files changed, 22 insertions(+)
+
+commit 6f6c0ceff00fea83bc85756b10694f7c96039abc
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Mar 1 11:10:01 2013 +0100
+
+    Fix GLib.Source ref leak upon destruction
+
+    In GLib.Source.__del__(), manually unref the source if we are a
+    custom Source.
+    As we use a static binding to create it, the GI part won't unref it
+    for us,
+    leading to finalize() method not being called and the GSource
+    object leaking.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=510511
+
+ gi/overrides/GLib.py |  4 ++++
+ tests/test_source.py | 31 +++++++++++++++++++++++++++++++
+ 2 files changed, 35 insertions(+)
+
+commit 91f76dd94fb0afc6888a821a31c3a4e2e053360e
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Feb 28 15:08:56 2013 +0100
+
+    Add performance test for Gtk.ListStore.append
+
+    We are going to optimize this in various ways, so let's measure it.
+
+ tests/test_overrides_gtk.py | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+commit b1ff74b085bdca72c272f019be4dd387073a991a
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Feb 28 04:32:30 2013 -0800
+
+    Optimize GValue.get/set_value by setting GValue.g_type to a local
+
+    This increases performance by a factor of 2x for types later
+    in the dispatch.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=694857
+
+ gi/overrides/GObject.py | 98
+ +++++++++++++++++++++++++------------------------
+ 1 file changed, 51 insertions(+), 47 deletions(-)
+
+commit 105e6738ee249b64904da26ae45dd273ca4eeba8
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Feb 28 11:43:47 2013 +0100
+
+    Fix leak of caller-allocated boxed values
+
+    Add a new "allocated_slice" argument to _pygi_boxed_new() which
+    specifies
+    whether its "boxed" pointer was allocated using a slice (by giving
+    its size) or
+    malloc (by specifying 0), as _pygi_boxed_new cannot determine that
+    itself any
+    more.
+
+    Use this in _pygi_marshal_to_py_interface_struct() for
+    caller-allocated boxed
+    values, as _caller_alloc() uses _pygi_boxed_alloc() for those
+    (i. e. slices),
+    which would otherwise leak.
+
+    Thanks to Mike Gorse <mgorse@suse.com> for the original patch!
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=691501
+
+ gi/gimodule.c           |  2 +-
+ gi/pygi-argument.c      |  2 +-
+ gi/pygi-boxed.c         | 14 ++++++++++----
+ gi/pygi-boxed.h         |  3 ++-
+ gi/pygi-marshal-to-py.c |  6 ++++--
+ gi/pygi-source.c        |  3 ++-
+ 6 files changed, 20 insertions(+), 10 deletions(-)
+
+commit 64bcca2d39fed1734ad1abbe291406387e901f5c
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Feb 28 10:48:18 2013 +0100
+
+    Fix memory handling of caller-allocated boxed types
+
+    _pygi_marshal_to_py_interface_struct() and other places treat
+    subtypes of
+    G_TYPE_BOXED as boxed values and wrap them with _pygi_boxed_new(). Fix
+    _caller_alloc() and _cleanup_caller_allocates() to consider
+    G_TYPE_BOXED
+    subtypes as well and use the slice allocator instead of malloc()'ing
+    a struct.
+    This avoids trying to free an malloc'ed struct with g_slice_free()
+    and properly
+    cleans up the boxed values.
+
+    The leak was produced with:
+
+    G_SLICE=debug-blocks PYTHONPATH=. valgrind --tool=memcheck
+    --leak-check=full --show-possibly-lost=no \
+      python3 -c 'from gi.repository import Gtk; b=Gtk.TextBuffer();
+      (s,e) = b.get_bounds()'
+
+ gi/pygi-invoke.c          | 2 +-
+ gi/pygi-marshal-cleanup.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 4f5e8b7554b6388aa2d0eb4a3b285d99499163be
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Feb 27 23:21:34 2013 +0100
+
+    Fix cleanup of GValue arrays
+
+    Commit bc1fd8 introduced a thinko: We must not change
+    item_arg_cache->from_py_cleanup, as it's a global cache. Revert
+    the original
+    change, and instead put the hack into
+    _pygi_marshal_cleanup_from_py_array(),
+    which now short-circuits
+    _pygi_marshal_cleanup_from_py_interface_struct_gvalue() to avoid
+    trying to release a slice which has never been allocated in
+    _pygi_marshal_from_py_array().
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=672224
+
+ gi/pygi-marshal-cleanup.c | 11 ++++++++++-
+ gi/pygi-marshal-from-py.c | 10 +++-------
+ 2 files changed, 13 insertions(+), 8 deletions(-)
+
+commit 70118c3840b10e1585d066a4be485c097cd23e99
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Feb 27 21:52:43 2013 +0100
+
+    Revert "Mark caller-allocated boxed structures as having a slice
+    allocated"
+
+    This is wrong after all, as it sets slice_allocated to TRUE, but
+    doesn't set a
+    corresponding size. Also, poking in internal fields from that place
+    is ugly;
+    this should rather be fixed in gi/pygi-marshal-cleanup.c
+    _cleanup_caller_allocates().
+
+    This reverts commit dc3d21173b75232f7ea0b9913f7309486456a69d.
+
+ gi/pygi-marshal-to-py.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+commit a51c72c771dafc0c13d7990f1ff3e428dca729a1
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Feb 27 21:51:30 2013 +0100
+
+    Run tests with G_SLICE=debug_blocks
+
+    This will help finding regressions in slice management, like in
+    https://bugzilla.gnome.org/show_bug.cgi?id=691501
+
+ tests/Makefile.am | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+commit 4f6ebcfe0605a7a593dc3f9dd322a4da9bd091a3
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Feb 27 18:30:23 2013 +0100
+
+     Add override helper for stripping boolean returns
+
+    Introduce a gi.overrides.strip_boolean_result() helper which checks
+    a boolean
+    return value and if True, return the remaining arguments, otherwise
+    return a
+    default. This pattern is being used by a lot of overrides, which get
+    significantly smaller and more consistent that way.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=694431
+
+ gi/overrides/Gdk.py      |  27 +-------
+ gi/overrides/Gtk.py      | 156
+ +++++++++--------------------------------------
+ gi/overrides/__init__.py |  22 +++++++
+ 3 files changed, 53 insertions(+), 152 deletions(-)
+
+commit 08c97b0bd3140921f1b5c74f7764e23d3a9bf0ee
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Feb 27 15:39:23 2013 +0100
+
+    Drop obsolete pygobject_register_sinkfunc() declaration
+
+    There is no definition for this any more, nor is it being used
+    anywhere.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=639849
+
+ gi/_gobject/pygobject-private.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit b6fefd625b843d4fc3dabc456584a2ad27a48c8c
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Feb 27 13:41:55 2013 +0100
+
+    Fix marshalling of C arrays with explicit length in signal arguments
+
+    We need _pygi_argument_to_array() from both closure marshalling
+    (where we have
+    the arguments as GIArgument array) and signal closure marshalling
+    (where we
+    have the arguments in a GValue array). Add an alternative
+    "args_values"
+    parameter to _pygi_argument_to_array() so that callers can specify
+    one or the
+    other depending on which type they have available.
+
+    This allows us to pass on the full argument list for signal closures,
+    so that
+    _pygi_argument_to_array() can access the explicit length argument
+    for an
+    array.
+
+    This fixes the GSettings:change-event signal.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=662241
+
+ gi/pygi-argument.c       | 36 ++++++++++++++++++++++++++++--------
+ gi/pygi-argument.h       |  1 +
+ gi/pygi-closure.c        |  2 +-
+ gi/pygi-info.c           |  4 ++--
+ gi/pygi-signal-closure.c |  3 ++-
+ tests/test_gio.py        | 18 ++++++++++++++++++
+ 6 files changed, 52 insertions(+), 12 deletions(-)
+
+commit caeeeb7e4282e183eefc3c53b2d53c8c2bb7de89
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Feb 27 08:07:20 2013 +0100
+
+    Fix signedness, overflow checking, and 32 bit overflow of GFlags
+
+    GFlagsValue.value is a guint, so we must access it as unsigned
+    type. Define two
+    new macros PYGLIB_PyLong_FromUnsignedLong() and
+    PYGLIB_PyLong_AsUnsignedLong()
+    for that purpose, and consistently use them for handling flag
+    values. Use the
+    checked variant of these functions which produce OverflowErrors
+    instead
+    of the unchecked PYGLIB_PyLong_AS_LONG().
+
+    Insert zero padding after the PyLongObject in PyGFlags and
+    PyGEnum. Without
+    this, the directly adjacent GType field seems to confuse
+    PyLong_FromUnsignedLong() and includes the GType into the numeric
+    value.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693121
+
+ gi/_glib/pyglib-python-compat.h |  8 +++++++
+ gi/_gobject/gobjectmodule.c     |  2 +-
+ gi/_gobject/pygflags.c          | 52
+ +++++++++++++++++++++++++----------------
+ gi/_gobject/pygobject-private.h | 10 ++++----
+ gi/_gobject/pygobject.h         |  4 ++--
+ gi/_gobject/pygtype.c           |  6 ++---
+ tests/test_overrides_gdk.py     | 15 ++++++++++++
+ 7 files changed, 67 insertions(+), 30 deletions(-)
+
+commit b3a3da37e369f3f5d434c8dc9f3c7f1e74d537ac
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Tue Feb 26 16:15:36 2013 +0800
+
+    gi/pygi-marshal-from-py.c: Fix build on Visual C++
+
+    Since Visual C++ does not provide the INFINITY and NAN constants
+    in its
+    math.h (they are items defined by C99), provide fallback
+    implementations
+    for it here.  The INFINITY constant can be provided with HUGE_VAL,
+    since
+    we are using INFINITY to check the value of a variable of double
+    type, and
+    we could use a rather simple workaround for NAN.
+
+    Also avoid declaring variables in the middle of the block.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692856
+
+ gi/pygi-marshal-from-py.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+commit 5210e3d5bb7936a21b6a2c938ede505bf1d848c9
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 26 16:42:19 2013 +0100
+
+    Fix some style issues with previous patch
+
+ gi/pygi-cache.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 999679beaa9f5b36d9483abdbd30cd5e113b6bf6
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 26 10:15:22 2013 +0100
+
+    Raise DeprecationWarning on deprecated callables
+
+    Check if a callable is marked as deprecated and raise a
+    DeprecationWarning in
+    that case.
+
+    Notes:
+     - Python hides DeprecationWarning by default, you need to enable
+     them with -Wd
+     - The deprecation message is currently not in the typelib (bug
+     #694728)
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=665084
+
+ gi/pygi-cache.c  | 14 ++++++++++++++
+ tests/test_gi.py | 10 ++++++++++
+ 2 files changed, 24 insertions(+)
+
+commit 9f8258cfdcf562aa6cf37b9e66075b7f6a6ed97a
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Feb 18 00:39:45 2013 -0800
+
+    pygtkcompat: Add Widget.window, scroll_to_mark, and window methods
+
+    Fix gi.pygtkcompat attempting relative import in Python < 3.0.
+    Add Gtk.Widget.window property which uses get_window()
+    Add Gtk.TextView.scroll_to_mark with defaults
+    Add Gtk.window_list_toplevels and Gtk.window_set_default_icon_name
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=694067
+
+ gi/pygtkcompat.py          |  2 ++
+ pygtkcompat/pygtkcompat.py | 14 ++++++++++++++
+ 2 files changed, 16 insertions(+)
+
+commit e8e2bbee7bb79039bbd9a968f7db88438bd937f9
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Dec 16 02:56:06 2012 -0800
+
+    pygtkcompat: Add Gtk.Window.set_geometry_hints which accepts keyword
+    arguments
+
+    Monkey patch a keyword argument version of set_geometry_hints onto
+    Gtk.Window.
+    This version is compatible with pygtk and takes keywords instead of a
+    Gdk.Geometry and Gdk.GeometryMask.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=694067
+
+ pygtkcompat/pygtkcompat.py | 44
+ ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 44 insertions(+)
+
+commit 1ca0e142709843cdae9ca965dfa6cc292ef53ab5
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 26 10:09:47 2013 +0100
+
+    tests: Fix warning behaviour
+
+    -Werror::* does not seem to do what it says on the tin, these
+    options are
+    ignored entirely apparently. Just keep -Wd to actually show all
+    warnings
+    including DeprecationWarning, which is hidden by default.
+
+ tests/Makefile.am | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit e7ea6952c7a2d8da68ed8b66770d889cd756df9a
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 26 08:49:10 2013 +0100
+
+    Ship pygobject.doap for autogen.sh
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=694591
+
+ Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 80ed803dab3ad914d7214a475e3c6ed743dfdccc
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Tue Feb 19 03:07:19 2013 -0800
+
+    Fix crashes in various GObject signal handler functions
+
+    Fix crashes in a large amount of signal handler functions exposed
+    on the GObject module. This is possible now that the underlying
+    GObject pointer is exposed to Python as a PyCapsule which marshaling
+    can handle. The following functions in the GObject module have been
+    verified:
+
+    signal_handler_unblock
+    signal_handler_disconnect
+    signal_handler_is_connected
+    signal_stop_emission
+    signal_stop_emission_by_name
+    signal_has_handler_pending
+    signal_connect_closure
+    signal_connect_closure_by_id
+    signal_handler_find
+    signal_handlers_destroy
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=633927
+
+ gi/_gobject/gobjectmodule.c |  57 ++--------------
+ gi/overrides/GObject.py     | 158
+ ++++++++++++++++++++++++++++++++++----------
+ tests/test_signal.py        | 121 ++++++++++++++++++++++++++++++++-
+ 3 files changed, 247 insertions(+), 89 deletions(-)
+
+commit e9c578c1d47375cb2249ccdd86873faad04b89e1
+Author: Olivier Crête <olivier.crete@collabora.com>
+Date:   Fri Sep 14 21:29:53 2012 -0400
+
+    pygi-closure: Protect the GSList prepend with the GIL
+
+    Signed-off-by: Simon Feltman <sfeltman@src.gnome.org>
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=684060
+
+ gi/pygi-closure.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 6e0a32f6d9febbd782dc56a619974f009e79abd9
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Feb 20 01:21:32 2013 -0800
+
+    generictreemodel: Fix bad default return type for get_column_type
+
+ pygtkcompat/generictreemodel.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 8ec5c335e223bdf00c7bb6c9aac3e7ac7791e38e
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 19 12:23:13 2013 +0100
+
+    configure.ac: post-release bump to 3.7.91
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit f2fb7f6142cd7112db9c2526d7f1c642a50cfc2a
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 19 12:19:35 2013 +0100
+
+    Release 3.7.90
+
+ NEWS         | 17 +++++++++++++++++
+ configure.ac |  2 +-
+ 2 files changed, 18 insertions(+), 1 deletion(-)
+
+commit 840c871441cb215f24cc6e7ed26b9f38e5aad0df
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Feb 18 01:46:22 2013 -0800
+
+    overrides: Fix inconsistencies with drag and drop target list API
+
+    Add support to Gtk.Widget.drag_dest_set_target_list and
+    Gtk.Widget.drag_source_set_target_list to accept iterables containing
+    mixed TargetEntry or a tuple of (target, flags, info).
+    Add support to Gtk.TreeView.enable_model_drag_source and
+    Gtk.TreeView.enable_model_drag_dest to accept a list of
+    Gtk.TargetEntry
+    items.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=680640
+
+ gi/overrides/Gtk.py         | 40 +++++++++++++++++++++++++++++-----------
+ tests/test_overrides_gtk.py | 32 ++++++++++++++++++++++++++++++++
+ 2 files changed, 61 insertions(+), 11 deletions(-)
+
+commit 62e94b0f87845bb7a1cfddf70dcdc89ff7a80bf7
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Feb 18 03:19:34 2013 -0800
+
+    tests: Add test_marshaling_object to Makefile.am
+
+ tests/Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit a10fb7216de57046d1ecacb73dd032eaadcbad09
+Author: Simon Feltman <s.feltman@gmail.com>
+Date:   Wed Aug 29 03:46:23 2012 -0700
+
+    pygtkcompat: Add pygtk compatible GenericTreeModel implementation
+
+    Add Python implementation of the GenericTreeModel that was
+    available in pygtk. The implementation attempts a better job
+    than the original at ref counting by guaranteeing no leaks
+    upon deletion of the model itself. Or by using the extra "node"
+    argument to the row_deleted signal. The model is available in
+    the pygtkcompat package directly as
+    pygtkcompat.generictreemodel.GenericTreeModel or with as
+    gtk.GenericTreeModel when pygtkcompat.enable_gtk() is set.
+
+    Add file list and tree demos making use of GenericTreeModel
+    to gtk-demo.
+
+    Auto-expand gtk-demo app tree to give a better overview of
+    the demos available.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=682933
+
+ .../gtk-demo/demos/Tree View/treemodel_filelist.py | 234 ++++++++++++
+ .../gtk-demo/demos/Tree View/treemodel_filetree.py | 279 ++++++++++++++
+ demos/gtk-demo/gtk-demo.py                         |   2 +-
+ gi/pygtkcompat.py                                  |   2 +-
+ pygtkcompat/Makefile.am                            |   1 +
+ pygtkcompat/generictreemodel.py                    | 420
+ +++++++++++++++++++++
+ pygtkcompat/pygtkcompat.py                         |   3 +
+ tests/Makefile.am                                  |   1 +
+ tests/test_generictreemodel.py                     | 406
+ ++++++++++++++++++++
+ 9 files changed, 1346 insertions(+), 2 deletions(-)
+
+commit 871878c7a1e18fbdbf0744e0dd52cbcc6b610cdb
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Feb 18 02:54:14 2013 -0800
+
+    overrides: Add support for iterables besides tuples for TreePath
+    creation
+
+    Allow Gtk.TreePath to accept any iterable for creation of the path.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=682933
+
+ gi/overrides/Gtk.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 93c1536b45f56c20b6d874c41c4cacd2b6cdca0a
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Feb 15 22:56:29 2013 -0800
+
+    Unify Python callable to GClosure GI marshaling code
+
+    Add pygi_marshal_from_py_gclosure which can be used for direct
+    gi method
+    call args and vfunc out args.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693405
+
+ gi/pygi-argument.c        | 14 +-----------
+ gi/pygi-marshal-from-py.c | 55
+ ++++++++++++++++++++++++++++-------------------
+ gi/pygi-marshal-from-py.h |  3 +++
+ 3 files changed, 37 insertions(+), 35 deletions(-)
+
+commit 9e47afe459df942d9ffc4f71b39f1443976293df
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Feb 15 20:56:12 2013 -0800
+
+    Unify Python object to GValue GI marshaling code
+
+    Add pygi_marshal_from_py_g_value which can be used for direct
+    gi method
+    call args and vfunc out args. The new method also adds an
+    "is_allocated"
+    parameter that will be used to fix leaks in the future.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693405
+
+ gi/pygi-argument.c        | 43 +++++++--------------------
+ gi/pygi-marshal-from-py.c | 74
+ ++++++++++++++++++++++++++++++++---------------
+ gi/pygi-marshal-from-py.h |  5 ++++
+ 3 files changed, 65 insertions(+), 57 deletions(-)
+
+commit 15cd7be5ad80e2411d6c13b04f5e2c33e4f5605e
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Feb 15 23:07:57 2013 -0800
+
+    Rename pygi_marshal_from_py_object to make it more explicit
+
+    Rename pygi_marshal_from_py_object to pygi_marshal_from_py_gobject
+    to make it more explicit and give consistency with future refactoring.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693405
+
+ gi/pygi-argument.c        |  2 +-
+ gi/pygi-marshal-from-py.c | 22 +++++++++++++---------
+ gi/pygi-marshal-from-py.h |  6 +++---
+ 3 files changed, 17 insertions(+), 13 deletions(-)
+
+commit 84103dfabd05742d1a18729663a609e9bf7c45f8
+Author: Niklas Koep <niklas.koep@gmail.com>
+Date:   Fri Feb 15 21:23:01 2013 -0800
+
+    Prefix __module__ attribute of function objects with gi.repository
+
+    This allows gi module methods to work with pydoc and help().
+    Additionally correct typo in two docstrings of the same module.
+
+    Co-authored-by: Simon Feltman <sfeltman@src.gnome.org>
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693839
+
+ gi/overrides/__init__.py | 3 ++-
+ gi/types.py              | 6 +++---
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+commit f6d4d2da676ae63d7a24dd172775b488ce665fe4
+Author: Jonathan Ballet <jon@multani.info>
+Date:   Thu Feb 14 07:50:02 2013 +0100
+
+    configure.ac: only enable code coverage when available
+
+    When building with an older gnome-common which does not yet provide
+    code
+    coverage support, disable it instead of breaking the configure script.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693328
+
+ configure.ac | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+commit 42cbff60e2032f715d9be6ab280954211899e03c
+Author: Jonathan Ballet <jon@multani.info>
+Date:   Tue Feb 12 23:03:00 2013 +0100
+
+    Correctly set properties on object with statically defined properties
+
+    Fix failures in GObject.Object.set_properties() when used with
+    statically defined properties:
+
+    * Calling the method was raising a "SystemError: error return without
+    exception set" since `result` was (most of the time) still NULL at the
+    end of pygobject_set_properties()
+
+    * Calling the method with several properties would only set one of
+    the properties, since the function was exiting too early.
+
+    Signed-off-by: Simon Feltman <sfeltman@src.gnome.org>
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693618
+
+ gi/_gobject/pygobject.c | 19 +++++++++++--------
+ tests/test_gi.py        |  6 ++++++
+ 2 files changed, 17 insertions(+), 8 deletions(-)
+
+commit 2384769810a61d6ed08d8742b7ae976ebfaa8cb5
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Feb 11 18:08:37 2013 +0100
+
+    autogen.sh: Use gnome-autogen.sh
+
+    We depend on gnome-common now anyway, so use gnome-autogen.sh. This
+    will result
+    in a much better error message when gnome-common is not installed,
+    too.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693328
+
+ autogen.sh | 30 +++++++++++++++++-------------
+ 1 file changed, 17 insertions(+), 13 deletions(-)
+
+commit c107bb1f9275a748b494d3f32818f227e07cadf0
+Author: Christoph Reiter <christoph.reiter@gmx.at>
+Date:   Mon Feb 11 10:07:47 2013 +0100
+
+    GTK tests: Add and use context manager for realized widgets
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693377
+
+ tests/test_overrides_gtk.py | 91
+ +++++++++++++++++++++++++--------------------
+ 1 file changed, 50 insertions(+), 41 deletions(-)
+
+commit e6670ee26b7682e6213f71deef813ce2e7cd6730
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Feb 11 08:55:19 2013 +0100
+
+    _pygi_marshal_from_py_array: Fix uninitialized variable
+
+ gi/pygi-marshal-from-py.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit a37bfdcb3d9dcc8bcdd8126ad55d80fab4729c62
+Author: Christoph Reiter <christoph.reiter@gmx.at>
+Date:   Mon Feb 11 08:34:42 2013 +0100
+
+    Skip some vfunc tests with gi 1.34
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693374
+
+ tests/test_object_marshaling.py | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+commit aff2ea1b681c3019f7dbdc841c2e33de78dbb88f
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Feb 10 13:40:45 2013 -0800
+
+    Remove workaround for g_struct_info_get_size reporting incorrect size
+
+    Remove workaround for g_struct_info_get_size reporting incorrect size
+    for boxed GValues. Verified this now returns the correct size of 24.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=622711
+
+ gi/pygi-boxed.c | 31 +++++++++++++------------------
+ 1 file changed, 13 insertions(+), 18 deletions(-)
+
+commit 5efe2e5c8458d9f4d72329ea1209d96b5ebecfb4
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Feb 4 20:50:10 2013 -0800
+
+    Fix reference leaks with transient floating objects
+
+    Unify and refactor caller and callee GObject argument marshalers.
+    Combine code from the large switch statement used to marshal
+    arguments to and from vfuncs/closures with the marshalers used
+    for direct calls to gi functions. This fixes a reference leak
+    when marshalling GObjects to Python with transfer=full due to
+    the diverging code paths.
+    Replace ability in gobject_new_full to optionally sink objects
+    with ability to optionaly "steal" objects. This fits the premise
+    that binding layers should always sink objects initially. The
+    steal argument is then used for marshalling arguments which are
+    transfer=full.
+    Add hacks and comments to work around GTK+ bugs 693393 and 693400.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=687522
+
+ gi/_gobject/gobjectmodule.c     | 10 +++++--
+ gi/_gobject/pygobject-private.h |  2 +-
+ gi/_gobject/pygobject.c         | 45 ++++++++++++++++++++----------
+ gi/_gobject/pygobject.h         |  8 ++++--
+ gi/pygi-argument.c              | 52 +++++++++++++++++------------------
+ gi/pygi-marshal-from-py.c       | 61
+ +++++++++++++++++++++++++++++++++++++----
+ gi/pygi-marshal-from-py.h       |  6 ++++
+ gi/pygi-marshal-to-py.c         | 45 +++++++++++++++---------------
+ gi/pygi-marshal-to-py.h         |  5 ++++
+ tests/test_object_marshaling.py | 44 ++++++++++++++---------------
+ 10 files changed, 181 insertions(+), 97 deletions(-)
+
+commit bd54b8ab30fc957849e7f57e9ee4c4b41aa37013
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Feb 6 12:56:44 2013 -0800
+
+    tests: Fix spelling mistakes in new vfunc object marshalling tests
+
+ tests/test_object_marshaling.py | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+commit cd96fd8b8e10add9890f36ec237bb78548de7002
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 5 07:53:38 2013 +0100
+
+    configure.ac: post-release bump to 3.7.6
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 92b1404e61f46348168f32720eff4a482531e5e3
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Feb 5 07:46:46 2013 +0100
+
+    release 3.7.5.1
+
+ NEWS         | 3 +++
+ configure.ac | 2 +-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+commit a3a30559240077194f23c4651d6f382fa59b7d63
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Feb 4 15:16:37 2013 -0800
+
+    Fix API break with pygobject.h
+
+    Move pygobject_new_full after everything in the public API table.
+    This fixes a break that went in along with bug 675726.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=675726
+
+ gi/_gobject/gobjectmodule.c | 5 +++--
+ gi/_gobject/pygobject.h     | 2 +-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+commit b3ca7e27494c35620995840d777037a097082661
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Feb 4 19:53:26 2013 +0100
+
+    configure.ac: post-release bump to 3.7.6
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 77f638411314218748f349b337a36e2864eed1f4
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Feb 4 19:37:14 2013 +0100
+
+    release 3.7.5
+
+ NEWS | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+commit 50da4fca1435f8c27072e15875227c5e7fb9b7e4
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Feb 3 23:56:14 2013 -0800
+
+    Fix pointer cast warning that was missed in bug 675726
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=675726
+
+ gi/_gobject/pygobject.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b31d8a952cd57dc92b06a381e054199660a2d570
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Jan 31 02:35:36 2013 -0800
+
+    Move various signal methods from static bindings to gi and python
+
+    Move disconnect, handler_is_connected, handler_block, handler_unblock,
+    and stop_emission from static to gi python overrides.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692918
+
+ gi/_gobject/pygobject.c | 90
+ -------------------------------------------------
+ gi/overrides/GObject.py | 44 +++++++++++++++++-------
+ tests/test_signal.py    | 19 ++++++-----
+ 3 files changed, 42 insertions(+), 111 deletions(-)
+
+commit 3a6a4a7a21a0f5e851518b7912d8ff455aa3ede4
+Author: Paolo Borelli <pborelli@gnome.org>
+Date:   Fri Feb 1 21:09:26 2013 +0100
+
+    GLib overrides: Support unpacking 'maybe' variants
+
+    Automatically unpack 'maybe' variants to None or to their actual value
+    as we do for other kind of variants
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693032
+
+ gi/overrides/GLib.py         | 5 +++++
+ tests/test_overrides_glib.py | 8 ++++++++
+ 2 files changed, 13 insertions(+)
+
+commit 9bc3e6807f6c14fb0e132a90ff8f9984229896f6
+Author: Mike Gorse <mgorse@suse.com>
+Date:   Mon Jan 21 16:45:52 2013 -0600
+
+    Fix ref count leak when creating pygobject wrappers for input args
+
+    Only sink input references for closures and vfuncs when transfer is
+    everything. This fixes cases where incoming floating references for
+    callbacks need to maintain their floating state throughout the
+    callback so they don't leak a strong reference. Re-introduce a
+    working "sink" argument to pygobject_new_full which allows for this.
+    Change existing callers to always sink in order maintain behavior.
+
+    Co-Authored-By: Simon Feltman <sfeltman@src.gnome.org>
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=675726
+
+ gi/_gobject/gobjectmodule.c     |  5 +--
+ gi/_gobject/pygobject.c         |  7 ++--
+ gi/_gobject/pygobject.h         |  2 ++
+ gi/pygi-argument.c              | 13 +++----
+ tests/test_object_marshaling.py | 76
+ +++++++++++++++++++++++++++++++++++++----
+ 5 files changed, 85 insertions(+), 18 deletions(-)
+
+commit a53a9176a3f87cfb26f3ad98ea746ada0f1a39fa
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Jan 31 01:50:44 2013 -0800
+
+    Add tests for signal stop_emission, disconnect, and
+    handler_is_connected
+
+    Add tests for methods which will be moving from static bindings to gi
+    by using the new __gpointer__ attribute of GObject.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692918
+
+ tests/test_signal.py | 51
+ ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 50 insertions(+), 1 deletion(-)
+
+commit df18f9cc3828d1bcf6b6cdf26af786fd9f36d77e
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Jan 30 21:37:07 2013 -0800
+
+    Add __gpointer__ property to GObject static binding
+
+    Add access to the underlying C GObject pointer by wrapping it in a
+    PyCapsule/PyCPointer and exposing it as __gpointer__.
+    Add special case marshaling for gi parameters annotated as gpointer
+    to accept a PyCapsule and extract the underlying pointer as the arg.
+    This allows usage of methods like GObject.signal_handler_disconnect
+    which we can start replacing the static bindings with.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692918
+
+ gi/_gobject/pygobject.c   | 11 +++++++++--
+ gi/pygi-marshal-from-py.c |  6 +++++-
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+commit 571e0cb246baa4ef7db179b20da6b325f358fe5b
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Jan 27 01:22:37 2013 -0800
+
+    Prefix names of typeless enums and flags for GType registration
+
+    Prefix names given to g_flags_register_static and
+    g_enum_register_static
+    with "Py". This avoids conflicts with GTypes of the same name being
+    registered later by a library which does not provide a "get-type"
+    annotation.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692515
+
+ gi/gimodule.c    | 10 ++++++++--
+ tests/test_gi.py |  4 ++--
+ 2 files changed, 10 insertions(+), 4 deletions(-)
+
+commit 97f48f5dcabc8dad4480727a78416b1c2a220777
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Jan 30 04:35:32 2013 -0800
+
+    Add tests for vfunc object arguments and returns
+
+    Add tests which use different combinations of floating, transfer full,
+    transfer none, and held wrapper as in, out, or return arguments
+    to vfuncs.
+    Most of these are marked as skip or expectedFailure due to various
+    bugs
+    noted on the tests.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=687522
+
+ gi/overrides/GObject.py         |  15 +-
+ tests/test_object_marshaling.py | 540
+ ++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 550 insertions(+), 5 deletions(-)
+
+commit 73a83186329ede7702501d5bc49df269482461e4
+Author: Paolo Borelli <pborelli@gnome.org>
+Date:   Wed Jan 30 17:48:12 2013 +0100
+
+    Cosmetic fix to last patch
+
+ gi/pygi-argument.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+commit 9e0c41509d62e8df7d0d82608a8be75f3defe05c
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Fri Jan 25 13:05:18 2013 +0800
+
+    gi/pygi-info.c, gi/pygi-repository.c: Deal with C99isms
+
+    Drop the array forward static declarations. They are not necessary
+    and are not
+    valid in C89.
+
+    Also move declarations of variables to the top of their respective
+    blocks.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692856
+
+ gi/pygi-info.c       | 18 ++++++++++--------
+ gi/pygi-repository.c |  2 --
+ 2 files changed, 10 insertions(+), 10 deletions(-)
+
+commit 2e7c458ef6377a872043634b47737ef12eed744a
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Fri Jan 25 13:00:48 2013 +0800
+
+    Move variable declaration to top of blocks (C99ism)
+
+    Move variable declarations to the top of their respective blocks,
+    so that these
+    code will build under C89 compilers such as Visual C++.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692856
+
+ gi/pygi-argument.c        | 10 ++++++----
+ gi/pygi-closure.c         | 23 +++++++++++++++--------
+ gi/pygi-invoke.c          |  3 ++-
+ gi/pygi-marshal-cleanup.c |  3 ++-
+ gi/pygi-property.c        |  3 ++-
+ 5 files changed, 27 insertions(+), 15 deletions(-)
+
+commit 20fc5aa7514215fc7807adceb603d17f7943304a
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Fri Jan 25 12:58:26 2013 +0800
+
+    gi/pygobject-external.h: Remove GCCism
+
+    We can use G_GNUC_UNUSED from GLib that does the same purpose of
+    __attribute__ ( (unused)) when we are using a GCC that provides this.
+
+    The GLib headers that defines that macro should have already been
+    included
+    before this header is included (due to use of gboolean).
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692856
+
+ gi/pygobject-external.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 5d2f453f3fdb167a4b4a833011ae777bfd228eb9
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Jan 30 14:59:11 2013 +0100
+
+    tests: Update test_double() after e65c1248
+
+    Commit e65c1248 introduced support for NaN and ±inf as valid
+    float values,
+    rendering the "expect ValueError on 2*double" check broken. Just
+    remove it.
+
+ tests/test_everything.py | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit b8bf4ec6c2478275dc9c813946a90b82ded6d9ce
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Jan 23 07:14:16 2013 +0100
+
+    Do not immediately initialize Gdk and Gtk on import
+
+    Raising an exception if Gdk/Gtk cannot be imported makes it
+    impossible to
+    merely import a module for e. g. nosetests without actually running
+    it.
+
+    Programs who want to provide a proper error message should check
+    Gtk.initialized explicitly after importing. Check initialized
+    status in
+    Window.__init__() instead to provide a reasonably early error message
+    for most
+    programs.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692300
+
+ gi/overrides/Gdk.py | 2 --
+ gi/overrides/Gtk.py | 5 +++--
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+commit 93d5cc2986cb3d3d979694b1beb1719d2d8fed53
+Author: Chun-wei Fan <fanchunwei@src.gnome.org>
+Date:   Fri Jan 25 12:49:18 2013 +0800
+
+    gi/overrides/Glib.py: Fix running on Windows/non-Unix
+
+    The definition of self._signal_source uses a Unix-specific GLib
+    API, which
+    does not exist or have a direct equivilant on Windows.
+
+    Only define and use that variable when we aren't on Windows.
+
+ gi/overrides/GLib.py | 18 ++++++++++--------
+ 1 file changed, 10 insertions(+), 8 deletions(-)
+
+commit e65c124893ceaa9c97eb4c8c743fbeb756b9a6e6
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Jan 23 14:56:02 2013 +0100
+
+    Accept ±inf and NaN as float and double values
+
+    Also fix the broken error message when a float value is out of range.
+    PyErr_Format() does not support float macros.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=692381
+
+ gi/pygi-marshal-from-py.c | 37 +++++++++++++++++++------------------
+ tests/test_gobject.py     | 14 ++++++++++++++
+ 2 files changed, 33 insertions(+), 18 deletions(-)
+
+commit a52245381fab3c2aebd330cc9c5e717a93c9607d
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Jan 23 14:28:42 2013 +0100
+
+    Fix repr() of GLib.Variant
+
+    When using a standard constructor like GLib.Variant.new_*(), the
+    object does
+    not have a format_string property, and previously repr() would
+    crash. Fall back
+    to get_type_string() instead.
+
+    Also drop the unintended type annotations in repr().
+
+ gi/overrides/GLib.py         |  6 +++++-
+ tests/test_overrides_glib.py | 15 ++++++++++++++-
+ 2 files changed, 19 insertions(+), 2 deletions(-)
+
+commit 2270cf15012005362dc47456213c5d9e7f6ed28a
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Jan 23 14:14:29 2013 +0100
+
+    Fix gtk-demo for Python 3
+
+    It was crashing with
+
+       package = __import__(packagename, globals(), locals(),
+       [modulename], -1)
+      ValueError: level must be >= 0
+
+    Using level zero works with both Python 2 and 3.
+
+ demos/gtk-demo/gtk-demo.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit b24d07577da1e17c8e27f758fc1a23d7f2d0f668
+Author: Colin Walters <walters@verbum.org>
+Date:   Tue Jan 22 10:49:57 2013 -0500
+
+    build: Add autogen.sh to EXTRA_DIST
+
+    So downstreams that patch the autotools can use it.
+
+ Makefile.am | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit ed7fb99efa81854d947ae548d41a03f5275c5884
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Jan 17 08:23:02 2013 +0100
+
+    Define GObject.TYPE_VALUE gtype constant
+
+ gi/overrides/GObject.py | 4 +++-
+ tests/test_gobject.py   | 4 ++++
+ 2 files changed, 7 insertions(+), 1 deletion(-)
+
+commit fd32acdd97f49f086a8ad5cf2b65862c4e6ccc44
+Author: Olivier Crête <olivier.crete@collabora.com>
+Date:   Mon Sep 17 15:37:04 2012 -0400
+
+    gobject: Go through introspection on property setting
+
+    Consider introspected properties in object.set_property().
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=684062
+
+ gi/_gobject/pygobject.c  | 18 +++++++++++++++++-
+ tests/test_properties.py | 13 ++++++++++---
+ 2 files changed, 27 insertions(+), 4 deletions(-)
+
+commit 9a2060f26c2cc2f9ef79ab6fb9f512c317004856
+Author: Mike Gorse <mgorse@suse.com>
+Date:   Tue Jan 15 20:04:46 2013 -0600
+
+    Clean up caller-allocated GValues and their memory
+
+    When space for a GValue is allocated by the caller (as in
+    gtk_tree_model_get_value), we need to free the space allocated for the
+    value along with its contents. The GValue is not needed after
+    Pyg_value_as_pyobject is called, so call _cleanup_caller_allocates and
+    have it unset the value and deallocate the memory.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=691820
+
+ gi/pygi-marshal-cleanup.c | 20 ++++++++++++++++++--
+ 1 file changed, 18 insertions(+), 2 deletions(-)
+
+commit 45b7975d0a3d78f01f1112ae7b3f4208f15694d8
+Author: Dmitry Shachnev <mitya57@ubuntu.com>
+Date:   Wed Jan 16 13:44:42 2013 +0400
+
+    tests: define correct unittest.skipIf for python 2.6
+
+ tests/runtests.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 4706cd686ea1b25260c9ecc77abd324d6e4cf505
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Jan 16 09:17:13 2013 +0100
+
+    tests: More robust tree view realization
+
+    With current GNOME git head, the Gtk.TreeViews were not realized
+    enough any
+    more to receive property values. Put them into a Gtk.Dialog now and
+    show it to
+    ensure that they are realized.
+
+ tests/test_overrides_gtk.py | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+commit 90c6f596df2a96f9c8059ae9157bc467a80b7574
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Jan 15 10:42:49 2013 +0100
+
+    Drop deprecated g_thread_create()
+
+    Replace with g_thread_new(). This is available with glib >= 2.32,
+    and we
+    already require >= 2.34.
+
+ tests/test-thread.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 98504273dead9eade6e53c2297bcaec7bea6265a
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Jan 15 10:37:52 2013 +0100
+
+    Drop usage of deprecated GStaticPrivate
+
+    Replace with GPrivate.
+
+ gi/_gobject/gobjectmodule.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+commit 655e2eece14f5de3baf4505f524d17484b8b5a75
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Jan 15 10:29:47 2013 +0100
+
+    Don't call g_type_init() with glib >= 2.35.x
+
+    This fixes a deprecation warning.
+
+ gi/_gobject/gobjectmodule.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit 206e736380ba798c68de09f661d75c8e27451117
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Jan 15 09:47:11 2013 +0100
+
+    Use GNOME_COMPILE_WARNINGS from gnome-common
+
+    As we are now using gnome-common anyway for the code coverage macro,
+    also use
+    GNOME_COMPILE_WARNINGS, and only manually specify the extra options
+    that we
+    want beyond that.
+
+    This also enables -Wstrict-prototypes.
+
+ configure.ac | 14 ++++----------
+ 1 file changed, 4 insertions(+), 10 deletions(-)
+
+commit 137679426ff39507e15f08e9e6428d851fee06b7
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Jan 15 09:46:01 2013 +0100
+
+    Fix function prototypes and static functions
+
+    These cause errors/warnings with -Wstrict-prototypes.
+
+ gi/_glib/pyglib-python-compat.h | 2 ++
+ gi/pygi-foreign.c               | 2 +-
+ gi/pygi-marshal-from-py.c       | 4 ++--
+ gi/pygi-marshal-to-py.c         | 4 ++--
+ gi/pygi-source.c                | 2 +-
+ gi/pygi-source.h                | 2 +-
+ 6 files changed, 9 insertions(+), 7 deletions(-)
+
+commit d47927f1701a11aec8566425f22688c5df73d7f2
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 17:38:23 2013 +0100
+
+    configure.ac: post-release bump to 3.7.5
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit bd6da84a4aec74e47f5d70e8ed18695c37e746c6
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 17:30:48 2013 +0100
+
+    release 3.7.4
+
+ NEWS | 38 ++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 38 insertions(+)
+
+commit c90ef9dfac7dd51ec82c99c3605915996bea0f73
+Author: Simonas Kazlauskas <simonas@kazlauskas.me>
+Date:   Tue Dec 4 15:45:00 2012 +0200
+
+    Allow setting values through GtkTreeModelFilter
+
+    Previously, trying to set a value through filter throwed an exception
+    that the
+    model has no set_value() method. You had to first retrieve the
+    deepest child
+    model and set value to it.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=689624
+
+ gi/overrides/Gtk.py         |  5 +++++
+ tests/test_overrides_gtk.py | 11 +++++++++++
+ 2 files changed, 16 insertions(+)
+
+commit b092630efc691a6f7ae94ae896193254f5a961a6
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 12:37:18 2013 +0100
+
+    tests: Add (failing) test case for GParamSpec arguments
+
+    This reproduces
+    https://bugzilla.gnome.org/show_bug.cgi?id=682355
+
+ tests/test_gi.py | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 52d84b5da7f9fd4f65faea4e6fe3d250f937a208
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 12:20:27 2013 +0100
+
+    tests: Skip struct string member tests with g-i 1.34
+
+    We still support building against gobject-introspection 1.34, so
+    skip tests
+    which do not work with that version yet.
+
+ tests/test_gi.py | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit f9429192cb1002725a11a75a7b8f9300375b9caf
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 12:15:27 2013 +0100
+
+    Support GParamSpec signal arguments from Python
+
+    In pyg_value_from_pyobject(), recognize both the real GI
+    GObject.ParamSpec type
+    as well as the statically wrapped _gobject.GParamSpec type.
+
+    This fixes marshalling GObject.ParamSpec signal/vfunc arguments.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=683099
+
+ gi/_gobject/pygtype.c    |  6 +++++-
+ tests/test_signal.py     | 12 ++++++++++++
+ tests/testhelpermodule.c | 13 +++++++++++++
+ 3 files changed, 30 insertions(+), 1 deletion(-)
+
+commit 99f72925c7de76611f7592bce9d8217a9ff46809
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 11:48:11 2013 +0100
+
+    pygobject_emit(): Fix cleanup on error
+
+    Dot not try to unset GValues which have not been initialized yet,
+    when type
+    conversion fails for a parameter.
+
+ gi/_gobject/pygobject.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit acef1d3266d11b2465d61185a55526df879a5c62
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Dec 31 19:01:57 2012 -0800
+
+    Add signal emission methods to TreeModel which coerce the path
+    argument
+
+    Override TreeModel row_changed, row_inserted, row_has_child_toggled,
+    row_deleted, and rows_reordered methods to accept python iterables as
+    the path parameter. This is for compatibility with pygtk and
+    consistency
+    with the rest of the TreeModel and TreePath overrides.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=682933
+
+ gi/overrides/Gtk.py         | 31 ++++++++++++++++++++++++++++---
+ tests/test_overrides_gtk.py | 27 +++++++++++++++++++++++++++
+ 2 files changed, 55 insertions(+), 3 deletions(-)
+
+commit 9cfba517e1a6dced5e66786b28ed5e101b7b4a29
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 10:36:36 2013 +0100
+
+    Simplify overrides and tests using the new GObject.Value override
+
+    The previous commit added support for constructing a GObject.Value
+    with a given
+    GType and Python object conversion. Use this to simplify the Gtk
+    override and
+    the tests that construct GValues.
+
+    See https://bugzilla.gnome.org/show_bug.cgi?id=677473
+
+ gi/overrides/Gtk.py         | 88
+ +++------------------------------------------
+ tests/test_gi.py            | 26 +++++---------
+ tests/test_overrides_gtk.py |  2 +-
+ tests/test_signal.py        | 12 ++-----
+ 4 files changed, 17 insertions(+), 111 deletions(-)
+
+commit f62b98398177991bfdbe0b6753342e79e6cf170a
+Author: Bastian Winkler <buz@netbuz.org>
+Date:   Mon Jan 14 10:26:08 2013 +0100
+
+    Add override for GValue
+
+    Override GValue with a custom constructor and set_value()/get_value()
+    methods. This allows you to call
+
+    >>> GObject.Value(GObject.TYPE_FLOAT, 42.23)
+
+    instead of
+
+    >>> value = GObject.Value()
+    >>> value.init(GObject.TYPE_FLOAT)
+    >>> value.set_float(42.23)
+
+    This is especially useful for overrides that need to convert a Python
+    value to a expected type like G_TYPE_FLOAT.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=677473
+
+ gi/overrides/GObject.py | 127
+ +++++++++++++++++++++++++++++++++++++++++++++++-
+ tests/test_gobject.py   |  47 +++++++++++++++++-
+ 2 files changed, 172 insertions(+), 2 deletions(-)
+
+commit dc3d21173b75232f7ea0b9913f7309486456a69d
+Author: Mike Gorse <mgorse@suse.com>
+Date:   Thu Jan 10 15:48:30 2013 -0600
+
+    Mark caller-allocated boxed structures as having a slice allocated
+
+    When a C function takes a pointer and fills it with a boxed structure
+    (ie,
+    gtk_tree_store_insert_with_values), pygi should deallocate the slice
+    when the
+    box is no longer being used.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=699501
+
+ gi/pygi-marshal-to-py.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+commit 0c496d230fee7fd3ada90ee9af10e0bc1e29ee12
+Author: Olivier Crête <olivier.crete@collabora.com>
+Date:   Fri Sep 14 21:31:32 2012 -0400
+
+    pygi-property: Support boxed GSList/GList types
+
+    Note that this does not yet work for construct properties.
+
+    Co-Authored-By: Martin Pitt <martinpitt@gnome.org>
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=684059
+
+ gi/pygi-property.c | 10 ++++++++--
+ tests/test_gi.py   | 21 +++++++++++++++++++++
+ 2 files changed, 29 insertions(+), 2 deletions(-)
+
+commit 074f10d815453e58f4bee2f440c5db799add3876
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 07:48:31 2013 +0100
+
+    test_gio: Fix for Python 2
+
+    Python 2 does not yet take an "encoding" argument for str(), while
+    Python 3
+    requires it. Use a less fancy static test string instead.
+
+ tests/test_gio.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 734979d0c8317201148a7e94a323225fba2d1635
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 07:40:10 2013 +0100
+
+    tests: Add missing backwards compat methods for Python 2.6
+
+    Define skipIf(), assertLess(), and assertLessEqual() for running
+    the tests with
+    Python 2.6.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=691646
+
+ tests/runtests.py | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+commit dc0dafd1f6ca3ebbf04210768a45587387e44551
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Jan 14 07:34:46 2013 +0100
+
+    tests: Stop using assertSequenceEqual()
+
+    assertSequenceEqual() does not yet exist in Python 2.6, and is
+    not necessary
+    either as assertEqual() on sequences automatically does list
+    comparison.
+
+    Part of https://bugzilla.gnome.org/show_bug.cgi?id=691646
+
+ tests/test_gtype.py  | 6 ++----
+ tests/test_signal.py | 6 ++----
+ 2 files changed, 4 insertions(+), 8 deletions(-)
+
+commit 0a5587b6a56d417a6703e342f153596f08cd5889
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Jan 13 18:19:51 2013 -0800
+
+    Allow setting TreeModel values to None
+
+    Change TreeModel.set_value to use an empty but initialized GValue when
+    None is used as the value argument. This allows clearing of cell data
+    which was not accessible due to auto-coercion.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=684094
+
+ gi/overrides/Gtk.py         | 11 ++++++++---
+ tests/test_overrides_gtk.py |  8 ++++++++
+ 2 files changed, 16 insertions(+), 3 deletions(-)
+
+commit 5ae129da436793478750f0dc9427a174a980e10b
+Author: Mike Gorse <mgorse@suse.com>
+Date:   Thu Jan 10 16:42:17 2013 -0600
+
+    Set clean-up handler for marshalled arrays
+
+    Arrays did not have a cleanup handler set in some cases, resulting
+    in a leak.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=691509
+
+ gi/pygi-cache.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit 58bd307c57d542a8f69867dea2d0a0eb51230c7b
+Author: Vadim Rutkovsky <vrutkovs@redhat.com>
+Date:   Fri Jan 11 15:41:27 2013 +0100
+
+    Support setting string fields in structs
+
+    Co-Authored-By: Martin Pitt <martinpitt@gnome.org>
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=678401
+
+ gi/pygi-info.c   |  3 ++-
+ tests/test_gi.py | 16 ++++++++++++++++
+ 2 files changed, 18 insertions(+), 1 deletion(-)
+
+commit f2bcaa43c1158040a8c2cbc3a2ba5070d126a410
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Jan 11 14:58:44 2013 +0100
+
+    Re-enable test_gi.TestPropertiesObject.test_char test
+
+    The gobject-introspection bug got fixed:
+    https://bugzilla.gnome.org/show_bug.cgi?id=691524
+
+ tests/test_gi.py | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+commit 9a8c49087cf400e01c1f78241fa4d74b4d15f54e
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Jan 11 09:46:56 2013 +0100
+
+    tests: Re-enable test_callback_scope_call_array() check
+
+    Drop the expected failure from test_callback_scope_call_array()
+    and just add
+    the explicit array length arguments. While it would look cleaner to
+    not pass
+    them, it is probably not worth breaking the API for this.
+
+ tests/test_everything.py | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+commit 609636424b5f9b659e99a4bb53a48c165187c430
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Jan 11 09:13:36 2013 +0100
+
+    Permit plain integers for "gchar" values
+
+    Similar to guchar/guint8, allow plain integers (withing correct
+    boundaries) as
+    values for gchar/gint8 types.
+
+    This is covered by the test_gi.TestPropertiesObject.test_char
+    test when
+    removing the "expected failure" flag.
+
+ gi/_gobject/pygtype.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+commit a558d3d3a9274aeccfc54705bf5effdf71dee06b
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Fri Jan 11 09:09:41 2013 +0100
+
+    Allow single byte values for int8 types
+
+    When fixing gobject-introspection to consider "gchar" as signed (see
+    https://bugzilla.gnome.org/show_bug.cgi?id=691524), we must also
+    permit a
+    single-element "bytes" array as a valid value for int8, not just
+    for uint8.
+
+    This is caught by the test_overrides_gtk.TestTreeModel.test_tree_store
+    test.
+
+ gi/pygi-argument.c        |  4 ++--
+ gi/pygi-marshal-from-py.c | 34 +++++++++++++++++++++-------------
+ 2 files changed, 23 insertions(+), 15 deletions(-)
+
+commit aa7f6cd12fe403acb2cffc7890724af7abb9b990
+Author: Mike Gorse <mgorse@suse.com>
+Date:   Thu Jan 10 14:11:56 2013 -0600
+
+    Fix invalid memory access handling errors when registering an
+    enum type
+
+    Don't free the name until we are done with it.
+
+ gi/gimodule.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+commit ecd235959317d39b6d598662c00829e0ec717b17
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Jan 10 16:42:46 2013 +0100
+
+    Fix (out) arguments in callbacks
+
+    Do not ignore the first argument in _pygi_closure_set_out_arguments().
+    Presumably that has been done to skip over "self", but callbacks
+    are not
+    required to have a self argument. As self is never (out), we can
+    safely include
+    it in the loop.
+
+ gi/pygi-closure.c | 2 +-
+ tests/test_gi.py  | 4 ----
+ 2 files changed, 1 insertion(+), 5 deletions(-)
+
+commit d8e241e24a816691acbd592775b73defd9aa4f44
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Jan 10 15:14:05 2013 +0100
+
+    Fix C to Python marshalling of struct pointer arrays
+
+    Do not treat an array of pointers to values like an array of values on
+    marshalling from C. This makes the test_array_boxed_struct_return()
+    test case
+    work.
+
+ gi/pygi-marshal-to-py.c | 5 +++--
+ tests/test_gi.py        | 2 --
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+commit 60544b02f6f98c0b212625ae83b94a4c6debddeb
+Author: Simonas Kazlauskas <simonas@kazlauskas.me>
+Date:   Tue Jan 8 23:22:54 2013 +0200
+
+    Add tests for GFile
+
+    Most notably this commit contains a test for
+    Gio.File.replace_contents_async(),
+    which currently fails. Disable the tests for now as it breaks the
+    other tests.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=690525
+
+ tests/test_gio.py | 64
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 64 insertions(+)
+
+commit 118c5eaad045580455515876ba73b9537a8468b4
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Jan 10 13:56:11 2013 +0100
+
+    Rename test_overrides_gio.py to test_gio.py
+
+    As we want to add more tests for non-overridden API.
+
+ tests/Makefile.am           |   2 +-
+ tests/test_gio.py           | 121
+ ++++++++++++++++++++++++++++++++++++++++++++
+ tests/test_overrides_gio.py | 121
+ --------------------------------------------
+ 3 files changed, 122 insertions(+), 122 deletions(-)
+
+commit 8117e6bce73581e89211371708ff7d5de7d870d4
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Thu Jan 10 12:13:16 2013 +0100
+
+    Don't let Property.setter() method names define property names
+
+    Defining property names in install_properties() is too late when using
+    @propname.setter decorators; their method names don't define a
+    property name,
+    nor are they even required to be a valid property identifier.
+
+    So change the logic to already fix the property name when using
+    a setter
+    decorator and use that instead of the member name in
+    install_properties().
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=688971
+
+ gi/_gobject/propertyhelper.py | 29 ++++++++++++++++++++++-------
+ tests/test_properties.py      | 18 ++++++++++++++++++
+ 2 files changed, 40 insertions(+), 7 deletions(-)
+
+commit c0bd060521cc1b481995648dbe286b7e2f9ecd80
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Wed Jan 9 10:39:36 2013 +0100
+
+    tests: Force UTF-8 file name encoding
+
+    The test_gi.TestFilename tests fail if the environment specifies
+    a non-UTF8
+    file name encoding. Force it to "UTF-8" for the tests.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=691355
+
+ tests/runtests.py | 1 +
+ 1 file changed, 1 insertion(+)
+
+commit c02a00ae9599a661076630b21b7e24e78fb88c29
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Jan 8 16:56:40 2013 +0100
+
+    Use g-i stack allocation API
+
+    Where possible, i. e. when not keeping references across functions,
+    use the
+    _load_() methods instead of the _get_() ones from
+    gobject-introspection, which
+    is faster and less prone to memory leaks:
+
+      g_callable_info_get_arg () → g_callable_info_load_arg ()
+      g_callable_info_get_return_type() →
+      g_callable_info_load_return_type ()
+      g_arg_info_get_type() → g_arg_info_load_type ()
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=615982
+
+ gi/pygi-argument.c | 16 ++++------
+ gi/pygi-closure.c  | 88
+ ++++++++++++++++++++++++------------------------------
+ 2 files changed, 45 insertions(+), 59 deletions(-)
+
+commit 23d1f14f553069740465c82eaa937b877c41e0cb
+Author: Ray Strode <rstrode@redhat.com>
+Date:   Wed Dec 19 13:04:32 2012 -0500
+
+    pyg_value_from_pyobject: support GArray
+
+    This commit adds support for marshalling a python list (or other
+    sequence)
+    returned from signal handlers to GArray, if necessary.
+
+    This parallels the implementation written to marshal to (the now
+    deprecated)
+    GValueArray.
+
+    This fixes a crash in rhythmbox as seen downstream here:
+    https://bugzilla.redhat.com/show_bug.cgi?id=872851
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=690514
+
+    Co-Authored-By: Martin Pitt <martinpitt@gnome.org>
+
+ gi/_gobject/pygtype.c    | 60
+ ++++++++++++++++++++++++++++++++++++++++++++++++
+ tests/test_everything.py | 22 ++++++++++++++++++
+ 2 files changed, 82 insertions(+)
+
+commit 2089dbb117bae769b0303411c2630b6f86dc7d2d
+Author: Marko Lindqvist <cazfi74@gmail.com>
+Date:   Fri Jan 4 07:01:29 2013 +0100
+
+    Fix obsolete automake macros
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=691101
+
+ configure.ac | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+commit 6c02ab0ad720780f176192fdc6372aaa178812fd
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Dec 31 02:53:07 2012 -0800
+
+    Change dynamic enum and flag gtype creation to use namespaced naming
+
+    Use the combination of g_base_info_get_namespace and
+    g_base_info_get_name
+    as the name for registering enum and flag types with glib through
+    g_enum_register_static and g_flags_register_static. This avoids
+    conflicts
+    with types like GLib.SeekType and Gst.SeekType. Add better exceptions
+    and memory cleanup for invalid registration problems.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=690455
+
+ gi/_gobject/pygenum.c |  6 ++--
+ gi/gimodule.c         | 78
+ ++++++++++++++++++++++++++++++++++++++++++++-------
+ tests/test_gi.py      | 35 +++++++++++++++++++++++
+ 3 files changed, 106 insertions(+), 13 deletions(-)
+
+commit 692c80e11a05e2fb0515580acb22fd6fe65cede1
+Author: Dan Horák <dan@danny.cz>
+Date:   Fri Dec 28 22:12:32 2012 +0100
+
+    Fix test for GBytes.compare()
+
+    The result of the compare method is defined as equal, less than or
+    greater than zero
+    and the test must match to that. The underlaying memcmp() function
+    can return other
+    values than -1, 0 and 1. For example on architectures where it is
+    implemented directly
+    via a CPU instruction like on s390(x) where I can see -2 as a result
+    instead of the
+    "expected" -1.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=690837
+
+ tests/test_gi.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+commit 948dbcb223249a08f4398d4ad8861e92e3de0dfa
+Author: Jonathan Ballet <jon@multani.info>
+Date:   Thu Dec 27 16:04:51 2012 +0100
+
+    Fix Gtk.UIManager.add_ui_from_string() override for non-ASCII chars
+
+    The length argument is the size of the buffer in bytes, not in
+    characters.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=690329
+
+    Co-Authored-By: Martin Pitt <martinpitt@gnome.org>
+
+ gi/overrides/Gtk.py         | 2 +-
+ tests/test_overrides_gtk.py | 7 +++++++
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+commit 53bc12a87da824cbfb006a4fd65731edec12ecc7
+Author: Mike Gorse <mgorse@suse.com>
+Date:   Wed Dec 19 20:51:03 2012 -0500
+
+    Don't dup strings before passing them to type registration functions
+
+    Strings passed to g_enum_register_static and g_flags_register_static
+    are
+    eventually passed to g_quark_from_string, which dups the string
+    passed to it if
+    needed and does not take ownership of it, so passing in a
+    dynamically-allocated
+    string without freeing it results in a small leak.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=690532
+
+ gi/gimodule.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+commit 9454c01f2b1b82d43eea0f72fe9a28ef50065fc9
+Author: Carlos Garnacho <carlos@lanedo.com>
+Date:   Tue Dec 18 22:47:09 2012 +0100
+
+    Fix marshalling of arrays of boxed struct values
+
+    This fixes methods like gtk_selection_set_with_data().  In such cases
+    data is passed as an array of struct pointers, so it must be converted
+    to an array of structs.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=656312
+
+    Co-Authored-By: Martin Pitt <martinpitt@gnome.org>
+
+ gi/pygi-marshal-from-py.c |  6 ++++++
+ tests/test_gi.py          | 12 ++++++++++++
+ 2 files changed, 18 insertions(+)
+
+commit 231d5a7cfc73518b4e2b0c926d4c1ce9a804797e
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Tue Dec 18 02:03:41 2012 -0800
+
+    Add reference counting tests for Object.bind_property
+
+    Add tests which ensure transform callbacks and user_data
+    are propertly ref-counted.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=690397
+
+ tests/test_gobject.py | 40 ++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 36 insertions(+), 4 deletions(-)
+
+commit c29e11812d176b1f057074c9bab22c9614ae4f8c
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Tue Dec 18 11:43:04 2012 +0100
+
+    testhelpermodule.c: Do not unref called method
+
+    In _wrap_test_gerror_exception(), do not unref the method
+    arguments. This
+    causes a crash when being run with the stricter refcounting/memory
+    checks with
+    debug-enabled Python builds.
+
+ tests/testhelpermodule.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit ff0d9106bcd02a6b2c67cc3722481218c599a9f4
+Author: Martin Pitt <martinpitt@gnome.org>
+Date:   Mon Dec 17 23:20:50 2012 +0100
+
+    configure.ac: post-release bump to 3.7.4
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
 commit 061b23d14386c0e54d2c3af113554231bbe85f16
 Author: Martin Pitt <martinpitt@gnome.org>
 Date:   Mon Dec 17 23:18:31 2012 +0100
@@ -11611,9 +13892,10 @@ Date:  Tue Feb 22 15:07:40 2011 -0500
 
     [gi-demos] add liststore demo
 
+ demos/gtk-demo/demos/Tree View/__init__.py  |  0
  demos/gtk-demo/demos/Tree View/liststore.py | 205
  ++++++++++++++++++++++++++++
1 file changed, 205 insertions(+)
2 files changed, 205 insertions(+)
 
 commit 09de5cf99474fc8a34b5f4a61cede1fb47353ebb
 Author: John (J5) Palmieri <johnp@redhat.com>
@@ -12079,9 +14361,10 @@ Date:  Sat Feb 19 19:42:41 2011 -0500
 
     [gi-demos] add icon view edit and drag-and-drop demo
 
+ demos/gtk-demo/demos/Icon View/__init__.py    |   0
  demos/gtk-demo/demos/Icon View/iconviewedit.py | 101
  +++++++++++++++++++++++++
1 file changed, 101 insertions(+)
2 files changed, 101 insertions(+)
 
 commit 7b47289e25d1dd57ce15556ccfbb3ede1c4bfe8b
 Author: John (J5) Palmieri <johnp@redhat.com>
@@ -18501,9 +20784,10 @@ Date:  Tue Jul 6 17:27:04 2010 -0400
 
     add the Entry demo directory and the entry_buffer demo
 
+ demos/gtk-demo/demos/Entry/__init__.py     |  0
  demos/gtk-demo/demos/Entry/entry_buffer.py | 73
  ++++++++++++++++++++++++++++++
1 file changed, 73 insertions(+)
2 files changed, 73 insertions(+)
 
 commit f2b1d222120f055bec9339cca55c9cc90f538c00
 Author: John (J5) Palmieri <johnp@redhat.com>
@@ -19040,6 +21324,7 @@ Date:   Sun Jun 20 11:09:57 2010 -0300
 
  Makefile.am                                       |   14 +-
  configure.ac                                      |   29 +-
+ demos/gtk-demo/demos/__init__.py                  |    0
  demos/gtk-demo/demos/appwindow.py                 |  411 +++++
  demos/gtk-demo/demos/assistant.py                 |  134 ++
  demos/gtk-demo/demos/builder.py                   |   57 +
@@ -19069,6 +21354,7 @@ Date:   Sun Jun 20 11:09:57 2010 -0300
  examples/Makefile.am                              |    2 +-
  examples/cairo-demo.py                                    |  121 ++
  gi/Makefile.am                                            |    4 +-
+ gi/demos/gtk-demo/demos/__init__.py               |    0
  gi/demos/gtk-demo/demos/appwindow.py              |  411 -----
  gi/demos/gtk-demo/demos/assistant.py              |  134 --
  gi/demos/gtk-demo/demos/builder.py                |   57 -
@@ -19110,7 +21396,7 @@ Date:   Sun Jun 20 11:09:57 2010 -0300
  tests/test_gi.py                                  | 1624
  ++++++++++++++++++++
  tests/test_overrides.py                           |  132 ++
- 66 files changed, 4124 insertions(+), 4186 deletions(-)
+ 68 files changed, 4124 insertions(+), 4186 deletions(-)
 
 commit 597bd64319d7966045b5b8613ca6fc85668c3f56
 Merge: ec8d148 fa91dfd
@@ -19130,6 +21416,7 @@ Date:   Sun Jun 20 10:53:36 2010 -0300
  Makefile.am                                       |   28 -
  autogen.sh                                        |  166 --
  configure.ac                                      |   60 -
+ demos/gtk-demo/demos/__init__.py                  |    0
  demos/gtk-demo/demos/appwindow.py                 |  411 -----
  demos/gtk-demo/demos/assistant.py                 |  134 --
  demos/gtk-demo/demos/builder.py                   |   57 -
@@ -19160,6 +21447,7 @@ Date:   Sun Jun 20 10:53:36 2010 -0300
  examples/cairo-demo.py                                    |  121 --
  gi/.gitignore                                     |   40 +
  gi/HACKING                                        |   26 +
+ gi/demos/gtk-demo/demos/__init__.py               |    0
  gi/demos/gtk-demo/demos/appwindow.py              |  411 +++++
  gi/demos/gtk-demo/demos/assistant.py              |  134 ++
  gi/demos/gtk-demo/demos/builder.py                |   57 +
@@ -19202,7 +21490,7 @@ Date:   Sun Jun 20 10:53:36 2010 -0300
  tests/test_gi.py                                  | 1624
  --------------------
  tests/test_overrides.py                           |  132 --
- 71 files changed, 4248 insertions(+), 4414 deletions(-)
+ 73 files changed, 4248 insertions(+), 4414 deletions(-)
 
 commit ec8d148eccbb3714093f21b595ea77ae4c7c3bce
 Author: Johan Dahlin <johan@gnome.org>
@@ -19560,6 +21848,7 @@ Date:   Fri Jun 4 16:26:54 2010 -0400
        - http://bugzilla-attachments.gnome.org/attachment.cgi?id=162682
        - http://bugzilla-attachments.gnome.org/attachment.cgi?id=162764
 
+ demos/gtk-demo/demos/__init__.py                |   0
  demos/gtk-demo/demos/appwindow.py               | 393
  +++++++++++++++++++++++
  demos/gtk-demo/demos/data/alphatest.png         | Bin 0 -> 26529 bytes
@@ -19579,7 +21868,7 @@ Date:   Fri Jun 4 16:26:54 2010 -0400
  demos/gtk-demo/demos/data/gtk-logo-rgb.gif      | Bin 0 -> 6427 bytes
  demos/gtk-demo/demos/test.py                    |  14 +
  demos/gtk-demo/gtk-demo.py                      | 266 +++++++++++++++
- 18 files changed, 931 insertions(+)
+ 19 files changed, 931 insertions(+)
 
 commit b3b1f029d8d16cf9bd74160009808147d07e3b3f
 Author: Tomeu Vizoso <tomeu.vizoso@collabora.co.uk>
@@ -20460,8 +22749,9 @@ Date:   Sun Apr 18 13:48:45 2010 -0400
 
     Add one more missing file to tarballs
 
- gi/overrides/Makefile.am | 1 +
- 1 file changed, 1 insertion(+)
+ gi/overrides/GIMarshallingTests.py | 0
+ gi/overrides/Makefile.am          | 1 +
+ 2 files changed, 1 insertion(+)
 
 commit 979e01852fc7f830ee91093accdc387fa535075f
 Author: Tomeu Vizoso <tomeu@sugarlabs.org>
@@ -22089,24 +24379,25 @@ Date: Mon Nov 23 22:39:12 2009 +0100
 
     Remove the girepository module
 
- Makefile.am                   |    2 +-
- configure.ac                  |   17 -
- girepository/Makefile.am      |   54 --
- girepository/__init__.py      |   24 -
- girepository/bank-argument.c  |  379 -------------
- girepository/bank-info.c      | 1194
- ----------------------------------------
- girepository/bank-repository.c |  236 --------
- girepository/bank.c           |  155 ------
- girepository/bank.h           |   80 ---
- girepository/btypes.py                |  300 ----------
- girepository/importer.py      |   51 --
- girepository/module.py                |  224 --------
- girepository/overrides/Gdk.py |   14 -
- girepository/overrides/Gtk.py |    8 -
- girepository/repository.py    |   51 --
- tests/test_girepository.py    |  386 -------------
- 16 files changed, 1 insertion(+), 3174 deletions(-)
+ Makefile.am                       |    2 +-
+ configure.ac                      |   17 -
+ girepository/Makefile.am          |   54 --
+ girepository/__init__.py          |   24 -
+ girepository/bank-argument.c      |  379 ------------
+ girepository/bank-info.c          | 1194
+ ------------------------------------
+ girepository/bank-repository.c     |  236 -------
+ girepository/bank.c               |  155 -----
+ girepository/bank.h               |   80 ---
+ girepository/btypes.py                    |  300 ---------
+ girepository/importer.py          |   51 --
+ girepository/module.py                    |  224 -------
+ girepository/overrides/Gdk.py     |   14 -
+ girepository/overrides/Gtk.py     |    8 -
+ girepository/overrides/__init__.py |   0
+ girepository/repository.py        |   51 --
+ tests/test_girepository.py        |  386 ------------
+ 17 files changed, 1 insertion(+), 3174 deletions(-)
 
 commit a644edf0515c26ed027522891ccf02aceac764e8
 Author: Johan Dahlin <johan@gnome.org>
@@ -22348,6 +24639,7 @@ Date:   Sun Nov 8 12:35:08 2009 +0100
  gi/overrides/Gdk.py      |   21 +
  gi/overrides/Gtk.py      |   13 +
  gi/overrides/Makefile.am  |   10 +
+ gi/overrides/__init__.py  |   0
  gi/pygi-argument.c       | 1976 ++++++++++++++++++++++++++
  gi/pygi-argument.h       |   65 +
  gi/pygi-info.c                   | 2093 ++++++++++++++++++++++++++++
@@ -22370,7 +24662,7 @@ Date:   Sun Nov 8 12:35:08 2009 +0100
  tests/libtestgi.h        |  643 +++++++++
  tests/runtests.py        |   22 +
  tests/test_gi.py         | 1416 +++++++++++++++++++
- 33 files changed, 11566 insertions(+)
+ 34 files changed, 11566 insertions(+)
 
 commit bfd3100a580b8bea9db25b8bb7443fb8c3dbe1cc
 Author: Simon van der Linden <svdlinden@src.gnome.org>
@@ -22835,11 +25127,12 @@ Date: Wed Jun 3 10:47:58 2009 +0200
 
     Adds overrides modules from PyBank.
 
- girepository/Makefile.am      |  3 +++
- girepository/importer.py      |  3 +--
- girepository/overrides/Gdk.py | 14 ++++++++++++++
- girepository/overrides/Gtk.py |  8 ++++++++
- 4 files changed, 26 insertions(+), 2 deletions(-)
+ girepository/Makefile.am          |  3 +++
+ girepository/importer.py          |  3 +--
+ girepository/overrides/Gdk.py     | 14 ++++++++++++++
+ girepository/overrides/Gtk.py     |  8 ++++++++
+ girepository/overrides/__init__.py |  0
+ 5 files changed, 26 insertions(+), 2 deletions(-)
 
 commit c12964e6a3354d8063355225c94e6d21d621e08b
 Author: Simon van der Linden <simon.vanderlinden@student.uclouvain.be>
@@ -22996,8 +25289,12 @@ Date:  Sun May 31 17:43:16 2009 +0300
  codegen/Makefile.am     | 23 ++++++++++++-----------
  codegen/code-coverage.py |  2 ++
  codegen/codegen.py      |  2 ++
+ codegen/createdefs.py   |  0
  codegen/defsconvert.py   |  2 ++
- 4 files changed, 18 insertions(+), 11 deletions(-)
+ codegen/defsgen.py      |  0
+ codegen/docgen.py       |  0
+ codegen/scmexpr.py      |  0
+ 8 files changed, 18 insertions(+), 11 deletions(-)
 
 commit 833d4da202bcfcb01a414f8aec4b751ec8e1ccb2
 Author: Paul Pogonyshev <pogonyshev@gmx.net>
index f317f84..5e91024 100644 (file)
@@ -9,6 +9,8 @@ CLEANFILES = \
        `find "$(builddir)" -type f -name "*.pyc" -print`
 
 EXTRA_DIST = \
+       autogen.sh \
+       pygobject.doap \
        pygobject-$(PLATFORM_VERSION).pc.in \
        PKG-INFO \
        PKG-INFO.in \
index fc44c8d..71b8428 100644 (file)
@@ -280,6 +280,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -343,6 +344,8 @@ CLEANFILES = \
        `find "$(builddir)" -type f -name "*.pyc" -print`
 
 EXTRA_DIST = \
+       autogen.sh \
+       pygobject.doap \
        pygobject-$(PLATFORM_VERSION).pc.in \
        PKG-INFO \
        PKG-INFO.in \
diff --git a/NEWS b/NEWS
index 19ad872..dbe1027 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,143 @@
+3.8.0   25-Mar-2013
+       - tests: Fix incorrect assumption when testing pyglib version
+         (Simon Feltman)
+
+3.7.92  18-Mar-2013
+       - Fix stack smasher when marshaling enums as a vfunc return value
+         (Simon Feltman) (#637832)
+       - Change base class of PyGIDeprecationWarning based on minor version
+         (Simon Feltman) (#696011)
+       - autogen.sh: Source gnome-autogen to fix out of source builddir (Alban
+         Browaeys) (#694889)
+        - pygtkcompat: Make gdk.Window.get_geometry return tuple of 5
+         (Simon Feltman)
+        - pygtkcompat: Initialize hint to zero in set_geometry_hints
+         (Simon Feltman)
+        - Remove incorrect bounds check with property helper flags
+         (Simon Feltman)
+       - Fix crash when setting property of type object to an incorrect type
+         (Simon Feltman) (#695420)
+       - Give more informative error when setting property to incorrect type
+         (Simon Feltman) (#695420)
+
+3.7.91.1 05-Mar-2013
+        - Revert "Drop gi.overrides.overridefunc()" (Martin Pitt) (#695199)
+
+3.7.91  04-Mar-2013
+        - Fix many memory leaks (#675726, #693402, #691501, #510511, #691501,
+         #672224, and several more which are detected by our test suite)
+         (Martin Pitt)
+        - Dot not clobber original Gdk/Gtk functions with overrides
+         (Martin Pitt) (#686835)
+       - Optimize GValue.get/set_value by setting GValue.g_type to a local
+         (Simon Feltman) (#694857)
+        - Run tests with G_SLICE=debug_blocks (Martin Pitt) (#691501)
+       - Add override helper for stripping boolean returns (Martin Pitt)
+         (#694431)
+       - Drop obsolete pygobject_register_sinkfunc() declaration (Martin Pitt)
+         (#639849)
+       - Fix marshalling of C arrays with explicit length in signal arguments
+         (Martin Pitt) (#662241)
+       - Fix signedness, overflow checking, and 32 bit overflow of GFlags
+         (Martin Pitt) (#693121)
+       - gi/pygi-marshal-from-py.c: Fix build on Visual C++ (Chun-wei Fan)
+         (#692856)
+       - Raise DeprecationWarning on deprecated callables (Martin Pitt)
+         (#665084)
+       - pygtkcompat: Add Widget.window, scroll_to_mark, and window methods
+         (Simon Feltman) (#694067)
+       - pygtkcompat: Add Gtk.Window.set_geometry_hints which accepts keyword
+         arguments (Simon Feltman) (#694067)
+        - Ship pygobject.doap for autogen.sh (Martin Pitt) (#694591)
+       - Fix crashes in various GObject signal handler functions
+         (Simon Feltman) (#633927)
+       - pygi-closure: Protect the GSList prepend with the GIL (Olivier Crête)
+         (#684060)
+       - generictreemodel: Fix bad default return type for get_column_type
+         (Simon Feltman)
+
+3.7.90  19-Feb-2013
+       - overrides: Fix inconsistencies with drag and drop target list API
+         (Simon Feltman) (#680640)
+       - pygtkcompat: Add pygtk compatible GenericTreeModel implementation
+         (Simon Feltman) (#682933)
+       - overrides: Add support for iterables besides tuples for TreePath
+         creation (Simon Feltman) (#682933)
+       - Prefix __module__ attribute of function objects with gi.repository
+         (Niklas Koep) (#693839)
+       - configure.ac: only enable code coverage when available, to fix
+         autogen.sh with older gnome-commons (Jonathan Ballet) (#693328)
+       - Correctly set properties on object with statically defined properties
+         (Jonathan Ballet) (#693618)
+       - autogen.sh: Use gnome-autogen.sh (Martin Pitt) (#693328)
+       - Fix reference leaks with transient floating objects (Simon Feltman)
+         (#687522)
+
+3.7.5.1 05-Feb-2013
+        - Fix ABI break with pygobject.h from 3.7.5 (Simon Feltman) (#675726)
+
+3.7.5   04-Feb-2013
+       - Move various signal methods from static bindings to GI
+         (Simon Feltman) (#692918)
+       - GLib overrides: Support unpacking 'maybe' variants (Paolo Borelli)
+         (#693032)
+       - Fix ref count leak when creating pygobject wrappers for input args
+         (Mike Gorse) (#675726)
+       - Prefix names of typeless enums and flags for GType registration
+         (Simon Feltman) (#692515)
+       - Fix compilation with non-C99 compilers such as Visual C++
+         (Chun-wei Fan) (#692856)
+        - gi/overrides/Glib.py: Fix running on Windows/non-Unix (Chun-wei Fan)
+       - Do not immediately initialize Gdk and Gtk on import (Martin Pitt)
+         (#692300)
+        - Accept ±inf and NaN as float and double values (Martin Pitt) (#692381)
+        - Fix repr() of GLib.Variant (Martin Pitt)
+        - Fix gtk-demo for Python 3 (Martin Pitt)
+        - Define GObject.TYPE_VALUE gtype constant (Martin Pitt)
+       - gobject: Go through introspection on property setting (Olivier Crête)
+         (#684062)
+       - Clean up caller-allocated GValues and their memory (Mike Gorse)
+         (#691820)
+        - Use GNOME_COMPILE_WARNINGS from gnome-common (Martin Pitt)
+
+3.7.4   14-Jan-2013
+        - Allow setting values through GtkTreeModelFilter (Simonas Kazlauskas)
+          (#689624)
+        - Support GParamSpec signal arguments from Python (Martin Pitt)
+          (#683099)
+        - pygobject_emit(): Fix cleanup on error (Martin Pitt)
+        - Add signal emission methods to TreeModel which coerce the path
+          argument (Simon Feltman) (#682933)
+        - Add override for GValue (Bastian Winkler) (#677473)
+        - Mark caller-allocated boxed structures as having a slice allocated
+          (Mike Gorse) (#699501)
+        - pygi-property: Support boxed GSList/GList types (Olivier Crête)
+          (#684059)
+        - tests: Add missing backwards compat methods for Python 2.6
+          (Martin Pitt) (#691646)
+        - Allow setting TreeModel values to None (Simon Feltman) (#684094)
+        - Set clean-up handler for marshalled arrays (Mike Gorse) (#691509)
+        - Support setting string fields in structs (Vadim Rutkovsky) (#678401)
+        - Permit plain integers for "gchar" values (Martin Pitt)
+        - Allow single byte values for int8 types (Martin Pitt) (#691524)
+        - Fix invalid memory access handling errors when registering an enum
+          type (Mike Gorse)
+        - Fix (out) arguments in callbacks (Martin Pitt)
+        - Fix C to Python marshalling of struct pointer arrays (Martin Pitt)
+        - Don't let Property.setter() method names define property names
+          (Martin Pitt) (#688971)
+        - Use g-i stack allocation API (Martin Pitt) (#615982)
+        - pyg_value_from_pyobject: support GArray (Ray Strode) (#690514)
+        - Fix obsolete automake macros (Marko Lindqvist) (#691101)
+        - Change dynamic enum and flag gtype creation to use namespaced naming
+          (Simon Feltman) (#690455)
+        - Fix Gtk.UIManager.add_ui_from_string() override for non-ASCII chars
+          (Jonathan Ballet) (#690329)
+        - Don't dup strings before passing them to type registration functions
+          (Mike Gorse) (#690532)
+        - Fix marshalling of arrays of boxed struct values (Carlos Garnacho)
+          (#656312)
+
 3.7.3   17-Dec-2012
        - Add support for caller-allocated GArray out arguments (Martin Pitt)
          (#690041)
index 1956ce7..3badb54 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: PyGObject
-Version: 3.7.3
+Version: 3.8.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.7/pygobject-3.7.3.tar.gz
+Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.8/pygobject-3.8.0.tar.gz
 Description: Python bindings for GLib and GObject
 Platform: POSIX, Windows
 Classifier: Development Status :: 5 - Production/Stable
index db21f54..c397c89 100644 (file)
@@ -114,29 +114,6 @@ AC_PREREQ([2.50])dnl
 am_aux_dir=`cd $ac_aux_dir && pwd`
 ])
 
-
-# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 4
-
-# This was merged into AC_PROG_CC in Autoconf.
-
-AU_DEFUN([AM_PROG_CC_STDC],
-[AC_PROG_CC
-AC_DIAGNOSE([obsolete], [$0:
-       your code should no longer depend upon `am_cv_prog_cc_stdc', but upon
-       `ac_cv_prog_cc_stdc'.  Remove this warning and the assignment when
-       you adjust the code.  You can also remove the above call to
-       AC_PROG_CC if you already called it elsewhere.])
-am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc
-])
-AU_DEFUN([fp_PROG_CC_STDC])
-
 # AM_CONDITIONAL                                            -*- Autoconf -*-
 
 # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
@@ -439,18 +416,6 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
      [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
 ])
 
-# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
-# Free Software Foundation, Inc.
-#
-# This file is free software; the Free Software Foundation
-# gives unlimited permission to copy and/or distribute it,
-# with or without modifications, as long as this notice is preserved.
-
-# serial 8
-
-# AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
-AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
-
 # Do all the work for Automake.                             -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
@@ -1318,164 +1283,6 @@ AC_SUBST([am__tar])
 AC_SUBST([am__untar])
 ]) # _AM_PROG_TAR
 
-dnl GNOME_CODE_COVERAGE
-dnl
-dnl Defines CODE_COVERAGE_CFLAGS and CODE_COVERAGE_LDFLAGS which should be
-dnl included in the CFLAGS and LIBS/LDFLAGS variables of every build target
-dnl (program or library) which should be built with code coverage support.
-dnl Also defines GNOME_CODE_COVERAGE_RULES which should be substituted in your
-dnl Makefile; and $enable_code_coverage which can be used in subsequent
-dnl configure output.
-dnl
-dnl Note that all optimisation flags in CFLAGS must be disabled when code
-dnl coverage is enabled.
-dnl
-dnl Derived from Makefile.decl in GLib, originally licenced under LGPLv2.1+.
-dnl This file is licenced under GPLv3. For the full gnome-common licence
-dnl (GPLv3), see the COPYING file.
-dnl
-dnl Usage example:
-dnl configure.ac:
-dnl    GNOME_CODE_COVERAGE
-dnl
-dnl Makefile.am:
-dnl    @GNOME_CODE_COVERAGE_RULES@
-dnl    my_program_LIBS = … $(CODE_COVERAGE_LDFLAGS) …
-dnl    my_program_CFLAGS = … $(CODE_COVERAGE_CFLAGS) …
-dnl
-dnl This results in a “check-code-coverage” rule being added to any Makefile.am
-dnl which includes “@GNOME_CODE_COVERAGE_RULES@” (assuming the module has been
-dnl configured with --enable-code-coverage). Running `make check-code-coverage`
-dnl in that directory will run the module’s test suite (`make check`) and build
-dnl a code coverage report detailing the code which was touched, then print the
-dnl URI for the report.
-
-AC_DEFUN([GNOME_CODE_COVERAGE],[
-       dnl Check for --enable-code-coverage
-       AC_MSG_CHECKING([whether to build with code coverage support])
-       AC_ARG_ENABLE([code-coverage], AS_HELP_STRING([--enable-code-coverage], [Whether to enable code coverage support]),, enable_code_coverage=no)
-       AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes])
-       AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
-       AC_MSG_RESULT($enable_code_coverage)
-
-       AS_IF([ test "$enable_code_coverage" = "yes" ], [
-               dnl Check if gcc is being used
-               AS_IF([ test "$GCC" = "no" ], [
-                       AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
-               ])
-
-               # List of supported lcov versions.
-               lcov_version_list="1.6 1.7 1.8 1.9"
-
-               AC_CHECK_PROG([LCOV], [lcov], [lcov])
-               AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
-
-               AS_IF([ test "$LCOV" ], [
-                       AC_CACHE_CHECK([for lcov version], gnome_cv_lcov_version, [
-                               gnome_cv_lcov_version=invalid
-                               lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
-                               for lcov_check_version in $lcov_version_list; do
-                                       if test "$lcov_version" = "$lcov_check_version"; then
-                                               gnome_cv_lcov_version="$lcov_check_version (ok)"
-                                       fi
-                               done
-                       ])
-               ], [
-                       lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
-                       AC_MSG_ERROR([$lcov_msg])
-               ])
-
-               case $gnome_cv_lcov_version in
-                       ""|invalid[)]
-                               lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
-                               AC_MSG_ERROR([$lcov_msg])
-                               LCOV="exit 0;"
-                       ;;
-               esac
-
-               AS_IF([ test -z "$GENHTML" ], [
-                       AC_MSG_ERROR([Could not find genhtml from the lcov package])
-               ])
-
-               dnl Build the code coverage flags
-               CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
-               CODE_COVERAGE_LDFLAGS="-lgcov"
-
-               AC_SUBST([CODE_COVERAGE_CFLAGS])
-               AC_SUBST([CODE_COVERAGE_LDFLAGS])
-       ])
-
-GNOME_CODE_COVERAGE_RULES='
-# Code coverage
-#
-# Optional:
-#  - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
-#    (Default: $(top_builddir))
-#  - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
-#    by lcov for code coverage. (Default:
-#    $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
-#  - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
-#    reports to be created. (Default:
-#    $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
-#  - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the lcov instance.
-#    (Default: empty)
-#  - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
-#    instance. (Default: empty)
-#
-# The generated report will be titled using the $(PACKAGE_NAME) and
-# $(PACKAGE_VERSION). In order to add the current git hash to the title,
-# use the git-version-gen script, available online.
-
-# Optional variables
-CODE_COVERAGE_DIRECTORY ?= $(top_builddir)
-CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
-CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
-CODE_COVERAGE_LCOV_OPTIONS ?=
-CODE_COVERAGE_GENHTML_OPTIONS ?=
-
-# Use recursive makes in order to ignore errors during check
-check-code-coverage:
-ifdef CODE_COVERAGE_ENABLED
-       -$(MAKE) $(AM_MAKEFLAGS) -k check
-       $(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
-else
-       @echo "Need to reconfigure with --enable-code-coverage"
-endif
-
-# Capture code coverage data
-code-coverage-capture: code-coverage-capture-hook
-ifdef CODE_COVERAGE_ENABLED
-       $(LCOV) --directory $(CODE_COVERAGE_DIRECTORY) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_OPTIONS)
-       $(LCOV) --directory $(CODE_COVERAGE_DIRECTORY) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" --output-file "$(CODE_COVERAGE_OUTPUT_FILE)"
-       -rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
-       LANG=C $(GENHTML) --prefix $(CODE_COVERAGE_DIRECTORY) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
-       @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
-else
-       @echo "Need to reconfigure with --enable-code-coverage"
-endif
-
-# Hook rule executed before code-coverage-capture, overridable by the user
-code-coverage-capture-hook:
-
-clean: code-coverage-clean
-code-coverage-clean:
-       -$(LCOV) --directory $(top_builddir) -z
-       -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY)
-       -find . -name "*.gcda" -o -name "*.gcov" -delete
-
-GITIGNOREFILES ?=
-GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
-
-DISTCHECK_CONFIGURE_FLAGS ?=
-DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
-
-.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean
-'
-
-       AC_SUBST([GNOME_CODE_COVERAGE_RULES])
-       m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([GNOME_CODE_COVERAGE_RULES])])
-])
-
 # pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
 # serial 1 (pkg-config-0.24)
 # 
@@ -1851,6 +1658,335 @@ main ()
   rm -f conf.glibtest
 ])
 
+dnl GNOME_CODE_COVERAGE
+dnl
+dnl Defines CODE_COVERAGE_CFLAGS and CODE_COVERAGE_LDFLAGS which should be
+dnl included in the CFLAGS and LIBS/LDFLAGS variables of every build target
+dnl (program or library) which should be built with code coverage support.
+dnl Also defines GNOME_CODE_COVERAGE_RULES which should be substituted in your
+dnl Makefile; and $enable_code_coverage which can be used in subsequent
+dnl configure output.
+dnl
+dnl Note that all optimisation flags in CFLAGS must be disabled when code
+dnl coverage is enabled.
+dnl
+dnl Derived from Makefile.decl in GLib, originally licenced under LGPLv2.1+.
+dnl This file is licenced under LGPLv2.1+.
+dnl
+dnl Usage example:
+dnl configure.ac:
+dnl    GNOME_CODE_COVERAGE
+dnl
+dnl Makefile.am:
+dnl    @GNOME_CODE_COVERAGE_RULES@
+dnl    my_program_LIBS = … $(CODE_COVERAGE_LDFLAGS) …
+dnl    my_program_CFLAGS = … $(CODE_COVERAGE_CFLAGS) …
+dnl
+dnl This results in a “check-code-coverage” rule being added to any Makefile.am
+dnl which includes “@GNOME_CODE_COVERAGE_RULES@” (assuming the module has been
+dnl configured with --enable-code-coverage). Running `make check-code-coverage`
+dnl in that directory will run the module’s test suite (`make check`) and build
+dnl a code coverage report detailing the code which was touched, then print the
+dnl URI for the report.
+
+AC_DEFUN([GNOME_CODE_COVERAGE],[
+       dnl Check for --enable-code-coverage
+       AC_MSG_CHECKING([whether to build with code coverage support])
+       AC_ARG_ENABLE([code-coverage], AS_HELP_STRING([--enable-code-coverage], [Whether to enable code coverage support]),, enable_code_coverage=no)
+       AM_CONDITIONAL([CODE_COVERAGE_ENABLED], [test x$enable_code_coverage = xyes])
+       AC_SUBST([CODE_COVERAGE_ENABLED], [$enable_code_coverage])
+       AC_MSG_RESULT($enable_code_coverage)
+
+       AS_IF([ test "$enable_code_coverage" = "yes" ], [
+               dnl Check if gcc is being used
+               AS_IF([ test "$GCC" = "no" ], [
+                       AC_MSG_ERROR([not compiling with gcc, which is required for gcov code coverage])
+               ])
+
+               # List of supported lcov versions.
+               lcov_version_list="1.6 1.7 1.8 1.9"
+
+               AC_CHECK_PROG([LCOV], [lcov], [lcov])
+               AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
+
+               AS_IF([ test "$LCOV" ], [
+                       AC_CACHE_CHECK([for lcov version], gnome_cv_lcov_version, [
+                               gnome_cv_lcov_version=invalid
+                               lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'`
+                               for lcov_check_version in $lcov_version_list; do
+                                       if test "$lcov_version" = "$lcov_check_version"; then
+                                               gnome_cv_lcov_version="$lcov_check_version (ok)"
+                                       fi
+                               done
+                       ])
+               ], [
+                       lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list"
+                       AC_MSG_ERROR([$lcov_msg])
+               ])
+
+               case $gnome_cv_lcov_version in
+                       ""|invalid[)]
+                               lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)."
+                               AC_MSG_ERROR([$lcov_msg])
+                               LCOV="exit 0;"
+                       ;;
+               esac
+
+               AS_IF([ test -z "$GENHTML" ], [
+                       AC_MSG_ERROR([Could not find genhtml from the lcov package])
+               ])
+
+               dnl Build the code coverage flags
+               CODE_COVERAGE_CFLAGS="-O0 -g -fprofile-arcs -ftest-coverage"
+               CODE_COVERAGE_LDFLAGS="-lgcov"
+
+               AC_SUBST([CODE_COVERAGE_CFLAGS])
+               AC_SUBST([CODE_COVERAGE_LDFLAGS])
+       ])
+
+GNOME_CODE_COVERAGE_RULES='
+# Code coverage
+#
+# Optional:
+#  - CODE_COVERAGE_DIRECTORY: Top-level directory for code coverage reporting.
+#    (Default: $(top_builddir))
+#  - CODE_COVERAGE_OUTPUT_FILE: Filename and path for the .info file generated
+#    by lcov for code coverage. (Default:
+#    $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info)
+#  - CODE_COVERAGE_OUTPUT_DIRECTORY: Directory for generated code coverage
+#    reports to be created. (Default:
+#    $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage)
+#  - CODE_COVERAGE_LCOV_OPTIONS: Extra options to pass to the lcov instance.
+#    (Default: empty)
+#  - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
+#    instance. (Default: empty)
+#  - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
+#
+# The generated report will be titled using the $(PACKAGE_NAME) and
+# $(PACKAGE_VERSION). In order to add the current git hash to the title,
+# use the git-version-gen script, available online.
+
+# Optional variables
+CODE_COVERAGE_DIRECTORY ?= $(top_builddir)
+CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
+CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
+CODE_COVERAGE_LCOV_OPTIONS ?=
+CODE_COVERAGE_GENHTML_OPTIONS ?=
+CODE_COVERAGE_IGNORE_PATTERN ?=
+
+code_coverage_quiet = $(code_coverage_quiet_$(V))
+code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
+code_coverage_quiet_0 = --quiet
+
+# Use recursive makes in order to ignore errors during check
+check-code-coverage:
+ifdef CODE_COVERAGE_ENABLED
+       -$(MAKE) $(AM_MAKEFLAGS) -k check
+       $(MAKE) $(AM_MAKEFLAGS) code-coverage-capture
+else
+       @echo "Need to reconfigure with --enable-code-coverage"
+endif
+
+# Capture code coverage data
+code-coverage-capture: code-coverage-capture-hook
+ifdef CODE_COVERAGE_ENABLED
+       $(LCOV) $(code_coverage_quiet) --directory $(CODE_COVERAGE_DIRECTORY) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_OPTIONS)
+       $(LCOV) $(code_coverage_quiet) --directory $(CODE_COVERAGE_DIRECTORY) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)"
+       -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
+       LANG=C $(GENHTML) $(code_coverage_quiet) --prefix $(CODE_COVERAGE_DIRECTORY) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
+       @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
+else
+       @echo "Need to reconfigure with --enable-code-coverage"
+endif
+
+# Hook rule executed before code-coverage-capture, overridable by the user
+code-coverage-capture-hook:
+
+clean: code-coverage-clean
+code-coverage-clean:
+       -$(LCOV) --directory $(top_builddir) -z
+       -rm -rf $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_FILE).tmp $(CODE_COVERAGE_OUTPUT_DIRECTORY)
+       -find . -name "*.gcda" -o -name "*.gcov" -delete
+
+GITIGNOREFILES ?=
+GITIGNOREFILES += $(CODE_COVERAGE_OUTPUT_FILE) $(CODE_COVERAGE_OUTPUT_DIRECTORY)
+
+DISTCHECK_CONFIGURE_FLAGS ?=
+DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
+
+.PHONY: check-code-coverage code-coverage-capture code-coverage-capture-hook code-coverage-clean
+'
+
+       AC_SUBST([GNOME_CODE_COVERAGE_RULES])
+       m4_ifdef([_AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE([GNOME_CODE_COVERAGE_RULES])])
+])
+
+dnl GNOME_COMPILE_WARNINGS
+dnl Turn on many useful compiler warnings and substitute the result into
+dnl WARN_CFLAGS
+dnl For now, only works on GCC
+AC_DEFUN([GNOME_COMPILE_WARNINGS],[
+    dnl ******************************
+    dnl More compiler warnings
+    dnl ******************************
+
+    AC_ARG_ENABLE(compile-warnings, 
+                  AC_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],
+                                 [Turn on compiler warnings]),,
+                  [enable_compile_warnings="m4_default([$1],[yes])"])
+
+    if test "x$GCC" != xyes; then
+       enable_compile_warnings=no
+    fi
+
+    warning_flags=
+    realsave_CFLAGS="$CFLAGS"
+
+    dnl These are warning flags that aren't marked as fatal.  Can be
+    dnl overridden on a per-project basis with -Wno-foo.
+    base_warn_flags=" \
+        -Wall \
+        -Wstrict-prototypes \
+        -Wnested-externs \
+    "
+
+    dnl These compiler flags typically indicate very broken or suspicious
+    dnl code.  Some of them such as implicit-function-declaration are
+    dnl just not default because gcc compiles a lot of legacy code.
+    dnl We choose to make this set into explicit errors.
+    base_error_flags=" \
+        -Werror=missing-prototypes \
+        -Werror=implicit-function-declaration \
+        -Werror=pointer-arith \
+        -Werror=init-self \
+        -Werror=format-security \
+        -Werror=format=2 \
+        -Werror=missing-include-dirs \
+    "
+
+    case "$enable_compile_warnings" in
+    no)
+        warning_flags=
+        ;;
+    minimum)
+        warning_flags="-Wall"
+        ;;
+    yes)
+        warning_flags="$base_warn_flags $base_error_flags"
+        ;;
+    maximum|error)
+        warning_flags="$base_warn_flags $base_error_flags"
+        ;;
+    *)
+        AC_MSG_ERROR(Unknown argument '$enable_compile_warnings' to --enable-compile-warnings)
+        ;;
+    esac
+
+    if test "$enable_compile_warnings" = "error" ; then
+        warning_flags="$warning_flags -Werror"
+    fi
+
+    dnl Check whether GCC supports the warning options
+    for option in $warning_flags; do
+       save_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS $option"
+       AC_MSG_CHECKING([whether gcc understands $option])
+       AC_TRY_COMPILE([], [],
+           has_option=yes,
+           has_option=no,)
+       CFLAGS="$save_CFLAGS"
+       AC_MSG_RESULT([$has_option])
+       if test $has_option = yes; then
+           tested_warning_flags="$tested_warning_flags $option"
+       fi
+       unset has_option
+       unset save_CFLAGS
+    done
+    unset option
+    CFLAGS="$realsave_CFLAGS"
+    AC_MSG_CHECKING(what warning flags to pass to the C compiler)
+    AC_MSG_RESULT($tested_warning_flags)
+
+    AC_ARG_ENABLE(iso-c,
+                  AC_HELP_STRING([--enable-iso-c],
+                                 [Try to warn if code is not ISO C ]),,
+                  [enable_iso_c=no])
+
+    AC_MSG_CHECKING(what language compliance flags to pass to the C compiler)
+    complCFLAGS=
+    if test "x$enable_iso_c" != "xno"; then
+       if test "x$GCC" = "xyes"; then
+       case " $CFLAGS " in
+           *[\ \       ]-ansi[\ \      ]*) ;;
+           *) complCFLAGS="$complCFLAGS -ansi" ;;
+       esac
+       case " $CFLAGS " in
+           *[\ \       ]-pedantic[\ \  ]*) ;;
+           *) complCFLAGS="$complCFLAGS -pedantic" ;;
+       esac
+       fi
+    fi
+    AC_MSG_RESULT($complCFLAGS)
+
+    WARN_CFLAGS="$tested_warning_flags $complCFLAGS"
+    AC_SUBST(WARN_CFLAGS)
+])
+
+dnl For C++, do basically the same thing.
+
+AC_DEFUN([GNOME_CXX_WARNINGS],[
+  AC_ARG_ENABLE(cxx-warnings,
+                AC_HELP_STRING([--enable-cxx-warnings=@<:@no/minimum/yes@:>@]
+                               [Turn on compiler warnings.]),,
+                [enable_cxx_warnings="m4_default([$1],[minimum])"])
+
+  AC_MSG_CHECKING(what warning flags to pass to the C++ compiler)
+  warnCXXFLAGS=
+  if test "x$GXX" != xyes; then
+    enable_cxx_warnings=no
+  fi
+  if test "x$enable_cxx_warnings" != "xno"; then
+    if test "x$GXX" = "xyes"; then
+      case " $CXXFLAGS " in
+      *[\ \    ]-Wall[\ \      ]*) ;;
+      *) warnCXXFLAGS="-Wall -Wno-unused" ;;
+      esac
+
+      ## -W is not all that useful.  And it cannot be controlled
+      ## with individual -Wno-xxx flags, unlike -Wall
+      if test "x$enable_cxx_warnings" = "xyes"; then
+       warnCXXFLAGS="$warnCXXFLAGS -Wshadow -Woverloaded-virtual"
+      fi
+    fi
+  fi
+  AC_MSG_RESULT($warnCXXFLAGS)
+
+   AC_ARG_ENABLE(iso-cxx,
+                 AC_HELP_STRING([--enable-iso-cxx],
+                                [Try to warn if code is not ISO C++ ]),,
+                 [enable_iso_cxx=no])
+
+   AC_MSG_CHECKING(what language compliance flags to pass to the C++ compiler)
+   complCXXFLAGS=
+   if test "x$enable_iso_cxx" != "xno"; then
+     if test "x$GXX" = "xyes"; then
+      case " $CXXFLAGS " in
+      *[\ \    ]-ansi[\ \      ]*) ;;
+      *) complCXXFLAGS="$complCXXFLAGS -ansi" ;;
+      esac
+
+      case " $CXXFLAGS " in
+      *[\ \    ]-pedantic[\ \  ]*) ;;
+      *) complCXXFLAGS="$complCXXFLAGS -pedantic" ;;
+      esac
+     fi
+   fi
+  AC_MSG_RESULT($complCXXFLAGS)
+
+  WARN_CXXFLAGS="$CXXFLAGS $warnCXXFLAGS $complCXXFLAGS"
+  AC_SUBST(WARN_CXXFLAGS)
+])
+
 m4_include([m4/as-ac-expand.m4])
 m4_include([m4/jhflags.m4])
 m4_include([m4/libtool.m4])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755 (executable)
index 0000000..3c7605d
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/sh
+# Run this to generate all the initial makefiles, etc.
+set -e
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+
+PKG_NAME="pygobject"
+
+(test -f $srcdir/configure.ac \
+  && test -f $srcdir/$PKG_NAME.doap) || {
+    echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
+    echo " top-level $PKG_NAME directory"
+    exit 1
+}
+
+if type lcov >/dev/null 2>&1; then
+    EXTRA_ARGS="--enable-code-coverage"
+else
+    echo "lcov not installed, not enabling code coverage"
+fi
+
+
+which gnome-autogen.sh || {
+    echo "You need to install gnome-common."
+    exit 1
+}
+
+. gnome-autogen.sh "$EXTRA_ARGS" "$@"
+
index 5e1cc46..19d32dd 100755 (executable)
--- 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.7.3.
+# Generated by GNU Autoconf 2.69 for pygobject 3.8.0.
 #
 # 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.7.3'
-PACKAGE_STRING='pygobject 3.7.3'
+PACKAGE_VERSION='3.8.0'
+PACKAGE_STRING='pygobject 3.8.0'
 PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject'
 PACKAGE_URL='https://live.gnome.org/PyGObject/'
 
@@ -645,6 +645,7 @@ LCOV
 CODE_COVERAGE_ENABLED
 CODE_COVERAGE_ENABLED_FALSE
 CODE_COVERAGE_ENABLED_TRUE
+WARN_CFLAGS
 INTROSPECTION_COMPILER
 INTROSPECTION_SCANNER
 ENABLE_CAIRO_FALSE
@@ -826,6 +827,8 @@ enable_thread
 enable_glibtest
 with_ffi
 enable_cairo
+enable_compile_warnings
+enable_iso_c
 enable_code_coverage
 '
       ac_precious_vars='build_alias
@@ -1391,7 +1394,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.7.3 to adapt to many kinds of systems.
+\`configure' configures pygobject 3.8.0 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1461,7 +1464,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of pygobject 3.7.3:";;
+     short | recursive ) echo "Configuration of pygobject 3.8.0:";;
    esac
   cat <<\_ACEOF
 
@@ -1482,6 +1485,9 @@ Optional Features:
   --disable-glibtest      do not try to compile and run a test GLIB program
   --enable-cairo          Enable Cairo bindings using introspection
                           information
+  --enable-compile-warnings=[no/minimum/yes/maximum/error]
+                          Turn on compiler warnings
+  --enable-iso-c          Try to warn if code is not ISO C
   --enable-code-coverage  Whether to enable code coverage support
 
 Optional Packages:
@@ -1593,7 +1599,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-pygobject configure 3.7.3
+pygobject configure 3.8.0
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1871,7 +1877,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.7.3, which was
+It was created by pygobject $as_me 3.8.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2230,14 +2236,14 @@ $as_echo "#define PYGOBJECT_MAJOR_VERSION 3" >>confdefs.h
 PYGOBJECT_MAJOR_VERSION=3
 
 
-$as_echo "#define PYGOBJECT_MINOR_VERSION 7" >>confdefs.h
+$as_echo "#define PYGOBJECT_MINOR_VERSION 8" >>confdefs.h
 
-PYGOBJECT_MINOR_VERSION=7
+PYGOBJECT_MINOR_VERSION=8
 
 
-$as_echo "#define PYGOBJECT_MICRO_VERSION 3" >>confdefs.h
+$as_echo "#define PYGOBJECT_MICRO_VERSION 0" >>confdefs.h
 
-PYGOBJECT_MICRO_VERSION=3
+PYGOBJECT_MICRO_VERSION=0
 
 
 ac_config_headers="$ac_config_headers config.h"
@@ -2748,7 +2754,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='pygobject'
- VERSION='3.7.3'
+ VERSION='3.8.0'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -12419,676 +12425,6 @@ else
 fi
 
 
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}gcc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_CC"; then
-  ac_ct_CC=$CC
-  # Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="gcc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
-else
-  CC="$ac_cv_prog_CC"
-fi
-
-if test -z "$CC"; then
-          if test -n "$ac_tool_prefix"; then
-    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
-set dummy ${ac_tool_prefix}cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="${ac_tool_prefix}cc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  fi
-fi
-if test -z "$CC"; then
-  # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-  ac_prog_rejected=no
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
-       ac_prog_rejected=yes
-       continue
-     fi
-    ac_cv_prog_CC="cc"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-if test $ac_prog_rejected = yes; then
-  # We found a bogon in the path, so make sure we never use it.
-  set dummy $ac_cv_prog_CC
-  shift
-  if test $# != 0; then
-    # We chose a different compiler from the bogus one.
-    # However, it has the same basename, so the bogon will be chosen
-    # first if we set CC to just the basename; use the full file name.
-    shift
-    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
-  fi
-fi
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$CC"; then
-  if test -n "$ac_tool_prefix"; then
-  for ac_prog in cl.exe
-  do
-    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
-set dummy $ac_tool_prefix$ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$CC"; then
-  ac_cv_prog_CC="$CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-CC=$ac_cv_prog_CC
-if test -n "$CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
-$as_echo "$CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-    test -n "$CC" && break
-  done
-fi
-if test -z "$CC"; then
-  ac_ct_CC=$CC
-  for ac_prog in cl.exe
-do
-  # Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_CC+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_CC"; then
-  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_CC="$ac_prog"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_CC=$ac_cv_prog_ac_ct_CC
-if test -n "$ac_ct_CC"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
-$as_echo "$ac_ct_CC" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-  test -n "$ac_ct_CC" && break
-done
-
-  if test "x$ac_ct_CC" = x; then
-    CC=""
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    CC=$ac_ct_CC
-  fi
-fi
-
-fi
-
-
-test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
-$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error $? "no acceptable C compiler found in \$PATH
-See \`config.log' for more details" "$LINENO" 5; }
-
-# Provide some information about the compiler.
-$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
-set X $ac_compile
-ac_compiler=$2
-for ac_option in --version -v -V -qversion; do
-  { { ac_try="$ac_compiler $ac_option >&5"
-case "(($ac_try" in
-  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-  *) ac_try_echo=$ac_try;;
-esac
-eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
-$as_echo "$ac_try_echo"; } >&5
-  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
-  ac_status=$?
-  if test -s conftest.err; then
-    sed '10a\
-... rest of stderr output deleted ...
-         10q' conftest.err >conftest.er1
-    cat conftest.er1 >&5
-  fi
-  rm -f conftest.er1 conftest.err
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }
-done
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
-$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
-if ${ac_cv_c_compiler_gnu+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-#ifndef __GNUC__
-       choke me
-#endif
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_compiler_gnu=yes
-else
-  ac_compiler_gnu=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-ac_cv_c_compiler_gnu=$ac_compiler_gnu
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
-$as_echo "$ac_cv_c_compiler_gnu" >&6; }
-if test $ac_compiler_gnu = yes; then
-  GCC=yes
-else
-  GCC=
-fi
-ac_test_CFLAGS=${CFLAGS+set}
-ac_save_CFLAGS=$CFLAGS
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
-$as_echo_n "checking whether $CC accepts -g... " >&6; }
-if ${ac_cv_prog_cc_g+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_save_c_werror_flag=$ac_c_werror_flag
-   ac_c_werror_flag=yes
-   ac_cv_prog_cc_g=no
-   CFLAGS="-g"
-   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_g=yes
-else
-  CFLAGS=""
-      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-else
-  ac_c_werror_flag=$ac_save_c_werror_flag
-        CFLAGS="-g"
-        cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_g=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-   ac_c_werror_flag=$ac_save_c_werror_flag
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
-$as_echo "$ac_cv_prog_cc_g" >&6; }
-if test "$ac_test_CFLAGS" = set; then
-  CFLAGS=$ac_save_CFLAGS
-elif test $ac_cv_prog_cc_g = yes; then
-  if test "$GCC" = yes; then
-    CFLAGS="-g -O2"
-  else
-    CFLAGS="-g"
-  fi
-else
-  if test "$GCC" = yes; then
-    CFLAGS="-O2"
-  else
-    CFLAGS=
-  fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
-$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
-if ${ac_cv_prog_cc_c89+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  ac_cv_prog_cc_c89=no
-ac_save_CC=$CC
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <stdarg.h>
-#include <stdio.h>
-struct stat;
-/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
-struct buf { int x; };
-FILE * (*rcsopen) (struct buf *, struct stat *, int);
-static char *e (p, i)
-     char **p;
-     int i;
-{
-  return p[i];
-}
-static char *f (char * (*g) (char **, int), char **p, ...)
-{
-  char *s;
-  va_list v;
-  va_start (v,p);
-  s = g (p, va_arg (v,int));
-  va_end (v);
-  return s;
-}
-
-/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
-   function prototypes and stuff, but not '\xHH' hex character constants.
-   These don't provoke an error unfortunately, instead are silently treated
-   as 'x'.  The following induces an error, until -std is added to get
-   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
-   array size at least.  It's necessary to write '\x00'==0 to get something
-   that's true only with -std.  */
-int osf4_cc_array ['\x00' == 0 ? 1 : -1];
-
-/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
-   inside strings and character constants.  */
-#define FOO(x) 'x'
-int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
-
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};
-int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
-int argc;
-char **argv;
-int
-main ()
-{
-return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
-  ;
-  return 0;
-}
-_ACEOF
-for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
-       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
-do
-  CC="$ac_save_CC $ac_arg"
-  if ac_fn_c_try_compile "$LINENO"; then :
-  ac_cv_prog_cc_c89=$ac_arg
-fi
-rm -f core conftest.err conftest.$ac_objext
-  test "x$ac_cv_prog_cc_c89" != "xno" && break
-done
-rm -f conftest.$ac_ext
-CC=$ac_save_CC
-
-fi
-# AC_CACHE_VAL
-case "x$ac_cv_prog_cc_c89" in
-  x)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
-$as_echo "none needed" >&6; } ;;
-  xno)
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
-$as_echo "unsupported" >&6; } ;;
-  *)
-    CC="$CC $ac_cv_prog_cc_c89"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
-$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
-esac
-if test "x$ac_cv_prog_cc_c89" != xno; then :
-
-fi
-
-ac_ext=c
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
-ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
-ac_compiler_gnu=$ac_cv_c_compiler_gnu
-
-depcc="$CC"   am_compiler_list=
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
-$as_echo_n "checking dependency style of $depcc... " >&6; }
-if ${am_cv_CC_dependencies_compiler_type+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
-  # We make a subdir and do the tests there.  Otherwise we can end up
-  # making bogus files that we don't know about and never remove.  For
-  # instance it was reported that on HP-UX the gcc test will end up
-  # making a dummy file named `D' -- because `-MD' means `put the output
-  # in D'.
-  rm -rf conftest.dir
-  mkdir conftest.dir
-  # Copy depcomp to subdir because otherwise we won't find it if we're
-  # using a relative directory.
-  cp "$am_depcomp" conftest.dir
-  cd conftest.dir
-  # We will build objects and dependencies in a subdirectory because
-  # it helps to detect inapplicable dependency modes.  For instance
-  # both Tru64's cc and ICC support -MD to output dependencies as a
-  # side effect of compilation, but ICC will put the dependencies in
-  # the current directory while Tru64 will put them in the object
-  # directory.
-  mkdir sub
-
-  am_cv_CC_dependencies_compiler_type=none
-  if test "$am_compiler_list" = ""; then
-     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
-  fi
-  am__universal=false
-  case " $depcc " in #(
-     *\ -arch\ *\ -arch\ *) am__universal=true ;;
-     esac
-
-  for depmode in $am_compiler_list; do
-    # Setup a source with many dependencies, because some compilers
-    # like to wrap large dependency lists on column 80 (with \), and
-    # we should not choose a depcomp mode which is confused by this.
-    #
-    # We need to recreate these files for each test, as the compiler may
-    # overwrite some of them when testing with obscure command lines.
-    # This happens at least with the AIX C compiler.
-    : > sub/conftest.c
-    for i in 1 2 3 4 5 6; do
-      echo '#include "conftst'$i'.h"' >> sub/conftest.c
-      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
-      # Solaris 8's {/usr,}/bin/sh.
-      touch sub/conftst$i.h
-    done
-    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
-
-    # We check with `-c' and `-o' for the sake of the "dashmstdout"
-    # mode.  It turns out that the SunPro C++ compiler does not properly
-    # handle `-M -o', and we need to detect this.  Also, some Intel
-    # versions had trouble with output in subdirs
-    am__obj=sub/conftest.${OBJEXT-o}
-    am__minus_obj="-o $am__obj"
-    case $depmode in
-    gcc)
-      # This depmode causes a compiler race in universal mode.
-      test "$am__universal" = false || continue
-      ;;
-    nosideeffect)
-      # after this tag, mechanisms are not by side-effect, so they'll
-      # only be used when explicitly requested
-      if test "x$enable_dependency_tracking" = xyes; then
-       continue
-      else
-       break
-      fi
-      ;;
-    msvc7 | msvc7msys | msvisualcpp | msvcmsys)
-      # This compiler won't grok `-c -o', but also, the minuso test has
-      # not run yet.  These depmodes are late enough in the game, and
-      # so weak that their functioning should not be impacted.
-      am__obj=conftest.${OBJEXT-o}
-      am__minus_obj=
-      ;;
-    none) break ;;
-    esac
-    if depmode=$depmode \
-       source=sub/conftest.c object=$am__obj \
-       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
-       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
-         >/dev/null 2>conftest.err &&
-       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
-       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
-       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
-      # icc doesn't choke on unknown options, it will just issue warnings
-      # or remarks (even with -Werror).  So we grep stderr for any message
-      # that says an option was ignored or not supported.
-      # When given -MP, icc 7.0 and 7.1 complain thusly:
-      #   icc: Command line warning: ignoring option '-M'; no argument required
-      # The diagnosis changed in icc 8.0:
-      #   icc: Command line remark: option '-MP' not supported
-      if (grep 'ignoring option' conftest.err ||
-          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
-        am_cv_CC_dependencies_compiler_type=$depmode
-        break
-      fi
-    fi
-  done
-
-  cd ..
-  rm -rf conftest.dir
-else
-  am_cv_CC_dependencies_compiler_type=none
-fi
-
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5
-$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
-CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
-
- if
-  test "x$enable_dependency_tracking" != xno \
-  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
-  am__fastdepCC_TRUE=
-  am__fastdepCC_FALSE='#'
-else
-  am__fastdepCC_TRUE='#'
-  am__fastdepCC_FALSE=
-fi
-
-
-
-am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc
-
 if test "x$CC" != xcc; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
@@ -14854,305 +14190,86 @@ else
         { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 
-fi
-    fi
-fi
- if test "$enable_cairo" = "yes"; then
-  ENABLE_CAIRO_TRUE=
-  ENABLE_CAIRO_FALSE='#'
-else
-  ENABLE_CAIRO_TRUE='#'
-  ENABLE_CAIRO_FALSE=
-fi
-
-
-INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
-INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
-
-
-
-
-if test "x$GCC" = "xyes"; then
-
-case " $CFLAGS " in
-*[\    \ ]-Wall[\      \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Wall"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Wall" >&5
-$as_echo_n "checking whether $CC understands -Wall... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
-else
-  jh_has_option=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
-  #JH_ADD_CFLAG([-Werror=missing-prototypes])
-
-case " $CFLAGS " in
-*[\    \ ]-Werror=implicit-function-declaration[\      \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Werror=implicit-function-declaration"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Werror=implicit-function-declaration" >&5
-$as_echo_n "checking whether $CC understands -Werror=implicit-function-declaration... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
-else
-  jh_has_option=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
-
-case " $CFLAGS " in
-*[\    \ ]-Werror=pointer-arith[\      \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Werror=pointer-arith"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Werror=pointer-arith" >&5
-$as_echo_n "checking whether $CC understands -Werror=pointer-arith... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
-else
-  jh_has_option=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
-
-case " $CFLAGS " in
-*[\    \ ]-Werror=format-security[\    \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Werror=format-security"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Werror=format-security" >&5
-$as_echo_n "checking whether $CC understands -Werror=format-security... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
-else
-  jh_has_option=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
-
-case " $CFLAGS " in
-*[\    \ ]-Werror=missing-include-dirs[\       \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Werror=missing-include-dirs"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Werror=missing-include-dirs" >&5
-$as_echo_n "checking whether $CC understands -Werror=missing-include-dirs... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
-else
-  jh_has_option=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
-
-case " $CFLAGS " in
-*[\    \ ]-Werror=format[\     \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Werror=format"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Werror=format" >&5
-$as_echo_n "checking whether $CC understands -Werror=format... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
-else
-  jh_has_option=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
-
-case " $CFLAGS " in
-*[\    \ ]-Werror=unused-variable[\    \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -Werror=unused-variable"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Werror=unused-variable" >&5
-$as_echo_n "checking whether $CC understands -Werror=unused-variable... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
+fi
+    fi
+fi
+ if test "$enable_cairo" = "yes"; then
+  ENABLE_CAIRO_TRUE=
+  ENABLE_CAIRO_FALSE='#'
 else
-  jh_has_option=no
+  ENABLE_CAIRO_TRUE='#'
+  ENABLE_CAIRO_FALSE=
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
 
-case " $CFLAGS " in
-*[\    \ ]-fno-strict-aliasing[\       \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -fno-strict-aliasing"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -fno-strict-aliasing" >&5
-$as_echo_n "checking whether $CC understands -fno-strict-aliasing... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
 
-int
-main ()
-{
+INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
+INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
 
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
+
+
+
+# compiler warnings, errors, required cflags, and code coverage support
+
+
+    # Check whether --enable-compile-warnings was given.
+if test "${enable_compile_warnings+set}" = set; then :
+  enableval=$enable_compile_warnings;
 else
-  jh_has_option=no
+  enable_compile_warnings="maximum"
 fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
 
-  case $host_os in
-  solaris*)
-    ;;
-  *)
 
-case " $CFLAGS " in
-*[\    \ ]-std=c9x[\   \ ]*)
-  ;;
-*)
-  save_CFLAGS="$CFLAGS"
-  CFLAGS="$CFLAGS -std=c9x"
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -std=c9x" >&5
-$as_echo_n "checking whether $CC understands -std=c9x... " >&6; }
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+    if test "x$GCC" != xyes; then
+       enable_compile_warnings=no
+    fi
+
+    warning_flags=
+    realsave_CFLAGS="$CFLAGS"
+
+            base_warn_flags=" \
+        -Wall \
+        -Wstrict-prototypes \
+        -Wnested-externs \
+    "
+
+                    base_error_flags=" \
+        -Werror=missing-prototypes \
+        -Werror=implicit-function-declaration \
+        -Werror=pointer-arith \
+        -Werror=init-self \
+        -Werror=format-security \
+        -Werror=format=2 \
+        -Werror=missing-include-dirs \
+    "
+
+    case "$enable_compile_warnings" in
+    no)
+        warning_flags=
+        ;;
+    minimum)
+        warning_flags="-Wall"
+        ;;
+    yes)
+        warning_flags="$base_warn_flags $base_error_flags"
+        ;;
+    maximum|error)
+        warning_flags="$base_warn_flags $base_error_flags"
+        ;;
+    *)
+        as_fn_error $? "Unknown argument '$enable_compile_warnings' to --enable-compile-warnings" "$LINENO" 5
+        ;;
+    esac
+
+    if test "$enable_compile_warnings" = "error" ; then
+        warning_flags="$warning_flags -Werror"
+    fi
+
+        for option in $warning_flags; do
+       save_CFLAGS="$CFLAGS"
+       CFLAGS="$CFLAGS $option"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether gcc understands $option" >&5
+$as_echo_n "checking whether gcc understands $option... " >&6; }
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
 int
@@ -15164,24 +14281,60 @@ main ()
 }
 _ACEOF
 if ac_fn_c_try_compile "$LINENO"; then :
-  jh_has_option=yes
+  has_option=yes
 else
-  jh_has_option=no
+  has_option=no
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
-$as_echo "$jh_has_option" >&6; }
-  if test $jh_has_option = no; then
-    CFLAGS="$save_CFLAGS"
-  fi
-  ;;
-esac
-    ;;
-  esac
+       CFLAGS="$save_CFLAGS"
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_option" >&5
+$as_echo "$has_option" >&6; }
+       if test $has_option = yes; then
+           tested_warning_flags="$tested_warning_flags $option"
+       fi
+       unset has_option
+       unset save_CFLAGS
+    done
+    unset option
+    CFLAGS="$realsave_CFLAGS"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking what warning flags to pass to the C compiler" >&5
+$as_echo_n "checking what warning flags to pass to the C compiler... " >&6; }
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tested_warning_flags" >&5
+$as_echo "$tested_warning_flags" >&6; }
 
+    # Check whether --enable-iso-c was given.
+if test "${enable_iso_c+set}" = set; then :
+  enableval=$enable_iso_c;
+else
+  enable_iso_c=no
 fi
 
-# enable code coverage support
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking what language compliance flags to pass to the C compiler" >&5
+$as_echo_n "checking what language compliance flags to pass to the C compiler... " >&6; }
+    complCFLAGS=
+    if test "x$enable_iso_c" != "xno"; then
+       if test "x$GCC" = "xyes"; then
+       case " $CFLAGS " in
+           *\ \        -ansi\ \        *) ;;
+           *) complCFLAGS="$complCFLAGS -ansi" ;;
+       esac
+       case " $CFLAGS " in
+           *\ \        -pedantic\ \    *) ;;
+           *) complCFLAGS="$complCFLAGS -pedantic" ;;
+       esac
+       fi
+    fi
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $complCFLAGS" >&5
+$as_echo "$complCFLAGS" >&6; }
+
+    WARN_CFLAGS="$tested_warning_flags $complCFLAGS"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for Gnome code coverage support" >&5
+$as_echo_n "checking for Gnome code coverage support... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
 
                { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with code coverage support" >&5
 $as_echo_n "checking whether to build with code coverage support... " >&6; }
@@ -15356,6 +14509,7 @@ GNOME_CODE_COVERAGE_RULES='
 #    (Default: empty)
 #  - CODE_COVERAGE_GENHTML_OPTIONS: Extra options to pass to the genhtml
 #    instance. (Default: empty)
+#  - CODE_COVERAGE_IGNORE_PATTERN: Extra glob pattern of files to ignore
 #
 # The generated report will be titled using the $(PACKAGE_NAME) and
 # $(PACKAGE_VERSION). In order to add the current git hash to the title,
@@ -15367,6 +14521,11 @@ CODE_COVERAGE_OUTPUT_FILE ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage.info
 CODE_COVERAGE_OUTPUT_DIRECTORY ?= $(PACKAGE_NAME)-$(PACKAGE_VERSION)-coverage
 CODE_COVERAGE_LCOV_OPTIONS ?=
 CODE_COVERAGE_GENHTML_OPTIONS ?=
+CODE_COVERAGE_IGNORE_PATTERN ?=
+
+code_coverage_quiet = $(code_coverage_quiet_$(V))
+code_coverage_quiet_ = $(code_coverage_quiet_$(AM_DEFAULT_VERBOSITY))
+code_coverage_quiet_0 = --quiet
 
 # Use recursive makes in order to ignore errors during check
 check-code-coverage:
@@ -15380,10 +14539,10 @@ endif
 # Capture code coverage data
 code-coverage-capture: code-coverage-capture-hook
 ifdef CODE_COVERAGE_ENABLED
-       $(LCOV) --directory $(CODE_COVERAGE_DIRECTORY) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_OPTIONS)
-       $(LCOV) --directory $(CODE_COVERAGE_DIRECTORY) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" --output-file "$(CODE_COVERAGE_OUTPUT_FILE)"
-       -rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
-       LANG=C $(GENHTML) --prefix $(CODE_COVERAGE_DIRECTORY) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
+       $(LCOV) $(code_coverage_quiet) --directory $(CODE_COVERAGE_DIRECTORY) --capture --output-file "$(CODE_COVERAGE_OUTPUT_FILE).tmp" --test-name "$(PACKAGE_NAME)-$(PACKAGE_VERSION)" --no-checksum --compat-libtool $(CODE_COVERAGE_LCOV_OPTIONS)
+       $(LCOV) $(code_coverage_quiet) --directory $(CODE_COVERAGE_DIRECTORY) --remove "$(CODE_COVERAGE_OUTPUT_FILE).tmp" "/tmp/*" $(CODE_COVERAGE_IGNORE_PATTERN) --output-file "$(CODE_COVERAGE_OUTPUT_FILE)"
+       -@rm -f $(CODE_COVERAGE_OUTPUT_FILE).tmp
+       LANG=C $(GENHTML) $(code_coverage_quiet) --prefix $(CODE_COVERAGE_DIRECTORY) --output-directory "$(CODE_COVERAGE_OUTPUT_DIRECTORY)" --title "$(PACKAGE_NAME)-$(PACKAGE_VERSION) Code Coverage" --legend --show-details "$(CODE_COVERAGE_OUTPUT_FILE)" $(CODE_COVERAGE_GENHTML_OPTIONS)
        @echo "file://$(abs_builddir)/$(CODE_COVERAGE_OUTPUT_DIRECTORY)/index.html"
 else
        @echo "Need to reconfigure with --enable-code-coverage"
@@ -15410,7 +14569,151 @@ DISTCHECK_CONFIGURE_FLAGS += --disable-code-coverage
 
 
 
-CFLAGS="$CFLAGS $CODE_COVERAGE_CFLAGS"
+
+if test "x$GCC" = "xyes"; then
+
+case " $CFLAGS " in
+*[\    \ ]-Wall[\      \ ]*)
+  ;;
+*)
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Wall"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Wall" >&5
+$as_echo_n "checking whether $CC understands -Wall... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  jh_has_option=yes
+else
+  jh_has_option=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
+$as_echo "$jh_has_option" >&6; }
+  if test $jh_has_option = no; then
+    CFLAGS="$save_CFLAGS"
+  fi
+  ;;
+esac
+
+case " $CFLAGS " in
+*[\    \ ]-Werror=unused-variable[\    \ ]*)
+  ;;
+*)
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -Werror=unused-variable"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -Werror=unused-variable" >&5
+$as_echo_n "checking whether $CC understands -Werror=unused-variable... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  jh_has_option=yes
+else
+  jh_has_option=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
+$as_echo "$jh_has_option" >&6; }
+  if test $jh_has_option = no; then
+    CFLAGS="$save_CFLAGS"
+  fi
+  ;;
+esac
+
+case " $CFLAGS " in
+*[\    \ ]-fno-strict-aliasing[\       \ ]*)
+  ;;
+*)
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -fno-strict-aliasing"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -fno-strict-aliasing" >&5
+$as_echo_n "checking whether $CC understands -fno-strict-aliasing... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  jh_has_option=yes
+else
+  jh_has_option=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
+$as_echo "$jh_has_option" >&6; }
+  if test $jh_has_option = no; then
+    CFLAGS="$save_CFLAGS"
+  fi
+  ;;
+esac
+
+  case $host_os in
+  solaris*)
+    ;;
+  *)
+
+case " $CFLAGS " in
+*[\    \ ]-std=c9x[\   \ ]*)
+  ;;
+*)
+  save_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -std=c9x"
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -std=c9x" >&5
+$as_echo_n "checking whether $CC understands -std=c9x... " >&6; }
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  jh_has_option=yes
+else
+  jh_has_option=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $jh_has_option" >&5
+$as_echo "$jh_has_option" >&6; }
+  if test $jh_has_option = no; then
+    CFLAGS="$save_CFLAGS"
+  fi
+  ;;
+esac
+    ;;
+  esac
+
+fi
+
+CFLAGS="$CFLAGS $WARN_CFLAGS $CODE_COVERAGE_CFLAGS"
 LDFLAGS="$LDFLAGS $CODE_COVERAGE_CFLAGS"
 
 ac_config_files="$ac_config_files Makefile pygobject-3.0.pc pygobject-3.0-uninstalled.pc gi/Makefile gi/repository/Makefile gi/overrides/Makefile gi/_glib/Makefile gi/_gobject/Makefile examples/Makefile tests/Makefile pygtkcompat/Makefile PKG-INFO"
@@ -15552,10 +14855,6 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
   as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
-  as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
 if test -z "${HAVE_LIBFFI_TRUE}" && test -z "${HAVE_LIBFFI_FALSE}"; then
   as_fn_error $? "conditional \"HAVE_LIBFFI\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -15965,7 +15264,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.7.3, which was
+This file was extended by pygobject $as_me 3.8.0, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -16032,7 +15331,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.7.3
+pygobject config.status 3.8.0
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index dd5e078..6ad4059 100644 (file)
@@ -17,8 +17,8 @@ m4_define(python3_min_ver, 3.1)
 
 dnl the pygobject version number
 m4_define(pygobject_major_version, 3)
-m4_define(pygobject_minor_version, 7)
-m4_define(pygobject_micro_version, 3)
+m4_define(pygobject_minor_version, 8)
+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 ...
@@ -42,7 +42,7 @@ AC_SUBST(PYGOBJECT_MINOR_VERSION, pygobject_minor_version)
 AC_DEFINE(PYGOBJECT_MICRO_VERSION, pygobject_micro_version, [pygobject micro version])
 AC_SUBST(PYGOBJECT_MICRO_VERSION, pygobject_micro_version)
 
-AM_CONFIG_HEADER(config.h)
+AC_CONFIG_HEADERS(config.h)
 m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)])
 AM_INIT_AUTOMAKE([1.11.1 foreign no-dist-gzip dist-xz])
 
@@ -80,7 +80,6 @@ LT_INIT([dlopen win32-dll disable-static])
 
 AC_SEARCH_LIBS([strerror],[cposix])
 AC_PROG_CC
-AM_PROG_CC_STDC
 AM_PROG_CC_C_O
 
 # option to specify python interpreter to use; this just sets $PYTHON, so that
@@ -227,15 +226,19 @@ INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspecti
 AC_SUBST(INTROSPECTION_SCANNER)
 AC_SUBST(INTROSPECTION_COMPILER)
 
-dnl add required cflags ...
+# compiler warnings, errors, required cflags, and code coverage support
+GNOME_COMPILE_WARNINGS([maximum])
+AC_MSG_CHECKING(for Gnome code coverage support)
+m4_ifdef([GNOME_CODE_COVERAGE],
+         [AC_MSG_RESULT(yes)
+          GNOME_CODE_COVERAGE],
+         [AC_MSG_RESULT(no)
+          GNOME_CODE_COVERAGE_RULES=''
+          AC_SUBST([GNOME_CODE_COVERAGE_RULES])
+          enable_code_coverage="no"])
+
 if test "x$GCC" = "xyes"; then
   JH_ADD_CFLAG([-Wall])
-  #JH_ADD_CFLAG([-Werror=missing-prototypes])
-  JH_ADD_CFLAG([-Werror=implicit-function-declaration])
-  JH_ADD_CFLAG([-Werror=pointer-arith])
-  JH_ADD_CFLAG([-Werror=format-security])
-  JH_ADD_CFLAG([-Werror=missing-include-dirs])
-  JH_ADD_CFLAG([-Werror=format])
   JH_ADD_CFLAG([-Werror=unused-variable])
   JH_ADD_CFLAG([-fno-strict-aliasing])
 
@@ -249,9 +252,7 @@ if test "x$GCC" = "xyes"; then
 
 fi
 
-# enable code coverage support
-GNOME_CODE_COVERAGE
-CFLAGS="$CFLAGS $CODE_COVERAGE_CFLAGS"
+CFLAGS="$CFLAGS $WARN_CFLAGS $CODE_COVERAGE_CFLAGS"
 LDFLAGS="$LDFLAGS $CODE_COVERAGE_CFLAGS"
 
 AC_CONFIG_FILES(
index 2396bc0..c41f5f5 100644 (file)
@@ -185,6 +185,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
index 9f0630a..7d17d1b 100644 (file)
@@ -311,6 +311,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
index 70a4917..e8c12db 100644 (file)
@@ -83,7 +83,15 @@ def get_required_version(namespace):
     return _versions.get(namespace, None)
 
 
-# note, DeprecationWarning would be more suitable as a base, but this
-# unhelpfully isn't shown by default and thus useless
-class PyGIDeprecationWarning(RuntimeWarning):
+# Use RuntimeWarning as the base class of PyGIDeprecationWarning
+# for unstable (odd minor version) and use DeprecationWarning for
+# stable (even minor version). This is so PyGObject deprecations
+# behave the same as regular Python deprecations in stable releases.
+if version_info[1] % 2:
+    _DeprecationWarningBase = RuntimeWarning
+else:
+    _DeprecationWarningBase = DeprecationWarning
+
+
+class PyGIDeprecationWarning(_DeprecationWarningBase):
     pass
index 4f08aea..5a05798 100644 (file)
@@ -274,6 +274,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
index 5af14f8..9ba68f7 100644 (file)
@@ -137,6 +137,11 @@ static int _pyglib_init_##modname(PyObject *module)
 #define PYGLIB_PyLong_AS_LONG PyInt_AS_LONG
 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
 
+/* Python 2.7 lacks a PyInt_FromUnsignedLong function; use signed longs, and
+ * rely on PyInt_AsUnsignedLong() to interpret them correctly */
+#define PYGLIB_PyLong_FromUnsignedLong PyInt_FromLong
+#define PYGLIB_PyLong_AsUnsignedLong(o) PyInt_AsUnsignedLongMask((PyObject*)(o))
+
 #define PYGLIB_PyNumber_Long PyNumber_Int
 
 #ifndef PyVarObject_HEAD_INIT
@@ -146,6 +151,7 @@ static int _pyglib_init_##modname(PyObject *module)
 #endif
 
 #define PYGLIB_MODULE_START(symbol, modname)           \
+DL_EXPORT(void) init##symbol(void); \
 DL_EXPORT(void) init##symbol(void)                     \
 {                                                       \
     PyObject *module;                                   \
@@ -184,6 +190,7 @@ PyTypeObject symbol = {                                 \
     NULL,                                               \
     NULL                                                \
 };                                                      \
+PyMODINIT_FUNC PyInit_##symbol(void);                   \
 PyMODINIT_FUNC PyInit_##symbol(void)                    \
 {                                                       \
     PyObject *module;                                   \
@@ -223,6 +230,9 @@ PyTypeObject symbol = {                                 \
 #define PYGLIB_PyLongObject PyLongObject
 #define PYGLIB_PyLong_Type PyLong_Type
 
+#define PYGLIB_PyLong_FromUnsignedLong PyLong_FromUnsignedLong
+#define PYGLIB_PyLong_AsUnsignedLong(o) PyLong_AsUnsignedLongMask((PyObject*)(o))
+
 #define PYGLIB_PyBytes_FromString PyBytes_FromString
 #define PYGLIB_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
 #define PYGLIB_PyBytes_Resize(o, len) _PyBytes_Resize(o, len)
index 8a2353d..402a145 100644 (file)
@@ -264,6 +264,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
index 304a041..359c2c7 100644 (file)
@@ -37,7 +37,6 @@
 #include "pygpointer.h"
 #include "pygtype.h"
 
-static PyObject *_pyg_signal_accumulator_true_handled_func;
 static GHashTable *log_handlers = NULL;
 static gboolean log_handlers_disabled = FALSE;
 
@@ -340,17 +339,13 @@ create_signal (GType instance_type, const gchar *signal_name, PyObject *tuple)
        Py_DECREF(item);
     }
 
-    if (py_accum == _pyg_signal_accumulator_true_handled_func)
-        accumulator = g_signal_accumulator_true_handled;
-    else {
-        if (py_accum != NULL && py_accum != Py_None) {
-            accum_data = g_new(PyGSignalAccumulatorData, 1);
-            accum_data->callable = py_accum;
-            Py_INCREF(py_accum);
-            accum_data->user_data = py_accum_data;
-            Py_XINCREF(py_accum_data);
-            accumulator = _pyg_signal_accumulator;
-        }
+    if (py_accum != NULL && py_accum != Py_None) {
+        accum_data = g_new(PyGSignalAccumulatorData, 1);
+        accum_data->callable = py_accum;
+        Py_INCREF(py_accum);
+        accum_data->user_data = py_accum_data;
+        Py_XINCREF(py_accum_data);
+        accumulator = _pyg_signal_accumulator;
     }
 
     signal_id = g_signal_newv(signal_name, instance_type, signal_flags,
@@ -577,7 +572,7 @@ create_property (const gchar  *prop_name,
                return NULL;
 
            if (pyg_flags_get_value(prop_type, pydefault,
-                                   (gint *)&default_value))
+                                   &default_value))
                return NULL;
 
            pspec = g_param_spec_flags (prop_name, nick, blurb,
@@ -972,18 +967,18 @@ get_type_name_for_class(PyTypeObject *class)
 }
 
 
-static GStaticPrivate pygobject_construction_wrapper = G_STATIC_PRIVATE_INIT;
+static GPrivate pygobject_construction_wrapper;
 
 static inline void
 pygobject_init_wrapper_set(PyObject *wrapper)
 {
-    g_static_private_set(&pygobject_construction_wrapper, wrapper, NULL);
+    g_private_set(&pygobject_construction_wrapper, wrapper);
 }
 
 static inline PyObject *
 pygobject_init_wrapper_get(void)
 {
-    return (PyObject *) g_static_private_get(&pygobject_construction_wrapper);
+    return (PyObject *) g_private_get(&pygobject_construction_wrapper);
 }
 
 int
@@ -996,7 +991,11 @@ pygobject_constructv(PyGObject  *self,
         pygobject_init_wrapper_set((PyObject *) self);
         obj = g_object_newv(pyg_type_from_object((PyObject *) self),
                             n_parameters, parameters);
+
+        if (g_object_is_floating (obj))
+            self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
         pygobject_sink (obj);
+
         pygobject_init_wrapper_set(NULL);
         if (self->obj == NULL) {
             self->obj = obj;
@@ -1034,7 +1033,9 @@ pygobject__g_instance_init(GTypeInstance   *instance,
            * now */
         PyGILState_STATE state;
         state = pyglib_gil_state_ensure();
-        wrapper = pygobject_new_full(object, FALSE, g_class);
+        wrapper = pygobject_new_full(object,
+                                     /*steal=*/ FALSE,
+                                     g_class);
 
         /* 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
@@ -1477,7 +1478,7 @@ pyg_object_new (PyGObject *self, PyObject *args, PyObject *kwargs)
 
     if (obj) {
         pygobject_sink (obj);
-       self = (PyGObject *) pygobject_new_full((GObject *)obj, FALSE, NULL);
+       self = (PyGObject *) pygobject_new((GObject *)obj);
         g_object_unref(obj);
     } else
         self = NULL;
@@ -1665,38 +1666,6 @@ pyg_add_emission_hook(PyGObject *self, PyObject *args)
 }
 
 static PyObject *
-pyg_remove_emission_hook(PyGObject *self, PyObject *args)
-{
-    PyObject *pygtype, *repr;
-    char *name;
-    guint signal_id;
-    gulong hook_id;
-    GType gtype;
-
-    if (!PyArg_ParseTuple(args, "Osk:gobject.remove_emission_hook",
-                         &pygtype, &name, &hook_id))
-       return NULL;
-
-    if ((gtype = pyg_type_from_object(pygtype)) == 0) {
-       return NULL;
-    }
-
-    if (!g_signal_parse_name(name, gtype, &signal_id, NULL, TRUE)) {
-       repr = PyObject_Repr((PyObject*)self);
-       PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
-                 PYGLIB_PyUnicode_AsString(repr),
-                 name);
-       Py_DECREF(repr);
-       return NULL;
-    }
-
-    g_signal_remove_emission_hook(signal_id, hook_id);
-
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *
 pyg__install_metaclass(PyObject *dummy, PyTypeObject *metaclass)
 {
     Py_INCREF(metaclass);
@@ -1727,8 +1696,6 @@ static PyMethodDef _gobject_functions[] = {
       (PyCFunction)pyg_signal_accumulator_true_handled, METH_VARARGS },
     { "add_emission_hook",
       (PyCFunction)pyg_add_emission_hook, METH_VARARGS },
-    { "remove_emission_hook",
-      (PyCFunction)pyg_remove_emission_hook, METH_VARARGS },
     { "_install_metaclass",
       (PyCFunction)pyg__install_metaclass, METH_O },
 
@@ -2117,7 +2084,10 @@ struct _PyGObject_Functions pygobject_api_functions = {
   pyg_gerror_exception_check,
 
   pyglib_option_group_new,
-  pyg_type_from_object_strict
+  pyg_type_from_object_strict,
+
+  pygobject_new_full,
+  &PyGObject_Type
 };
 
 /* for addon libraries ... */
@@ -2205,7 +2175,9 @@ PYGLIB_MODULE_START(_gobject, "_gobject")
 {
     PyObject *d;
 
+#if !defined(GLIB_VERSION_2_36)
     g_type_init();
+#endif
     pyglib_init();
 
     d = PyModule_GetDict(module);
@@ -2223,10 +2195,6 @@ PYGLIB_MODULE_START(_gobject, "_gobject")
     pygobject_enum_register_types(d);
     pygobject_flags_register_types(d);
 
-      /* signal registration recognizes this special accumulator 'constant' */
-    _pyg_signal_accumulator_true_handled_func = \
-        PyDict_GetItemString(d, "signal_accumulator_true_handled");
-
     pygobject_api_functions.threads_enabled = pyglib_threads_enabled();
     _pyglib_notify_on_enabling_threads(pyg_note_threads_enabled);
 }
index a038f1b..e8ccb35 100644 (file)
@@ -149,6 +149,8 @@ class Property(object):
         @keyword maximum:  maximum allowed value (int, float, long only)
         """
 
+        self.name = None
+
         if type is None:
             type = object
         self.type = self._type_from_python(type)
@@ -166,9 +168,6 @@ class Property(object):
         # we don't want the lengthy Property class documentation showing up
         # on instances.
         self.__doc__ = blurb
-
-        if flags < 0 or flags > 32:
-            raise TypeError("invalid flag value: %r" % (flags,))
         self.flags = flags
 
         # Call after setting blurb for potential __doc__ usage.
@@ -180,7 +179,9 @@ class Property(object):
             getter = self._default_getter
             setter = self._default_setter
         self.getter(getter)
-        self.setter(setter)
+        # do not call self.setter() here, as this defines the property name
+        # already
+        self.fset = setter
 
         if minimum is not None:
             if minimum < self._get_minimum():
@@ -199,8 +200,6 @@ class Property(object):
             maximum = self._get_maximum()
         self.maximum = maximum
 
-        self.name = None
-
         self._exc = None
 
     def __repr__(self):
@@ -248,6 +247,11 @@ class Property(object):
     def setter(self, fset):
         """Set the setter function to fset. For use as a decorator."""
         self.fset = fset
+        # with a setter decorator, we must ignore the name of the method in
+        # install_properties, as this does not need to be a valid property name
+        # and does not define the property name. So set the name here.
+        if not self.name:
+            self.name = self.fget.__name__
         return self
 
     def _type_from_python(self, type_):
@@ -364,10 +368,18 @@ def install_properties(cls):
     props = []
     for name, prop in cls.__dict__.items():
         if isinstance(prop, Property):  # not same as the built-in
-            if name in gproperties:
-                raise ValueError('Property %s was already found in __gproperties__' % name)
-            prop.name = name
-            gproperties[name] = prop.get_pspec_args()
+            # if a property was defined with a decorator, it may already have
+            # a name; if it was defined with an assignment (prop = Property(...))
+            # we set the property's name to the member name
+            if not prop.name:
+                prop.name = name
+            # we will encounter the same property multiple times in case of
+            # custom setter methods
+            if prop.name in gproperties:
+                if gproperties[prop.name] == prop.get_pspec_args():
+                    continue
+                raise ValueError('Property %s was already found in __gproperties__' % prop.name)
+            gproperties[prop.name] = prop.get_pspec_args()
             props.append(prop)
 
     if not props:
index 9c3c455..89e3a06 100644 (file)
@@ -216,9 +216,9 @@ pyg_enum_add (PyObject *   module,
     int i;
 
     g_return_val_if_fail(typename != NULL, NULL);
-    if (!g_type_is_a(gtype, G_TYPE_ENUM)) {
-        g_warning("Trying to register gtype '%s' as enum when in fact it is of type '%s'",
-                  g_type_name(gtype), g_type_name(G_TYPE_FUNDAMENTAL(gtype)));
+    if (!g_type_is_a (gtype, G_TYPE_ENUM)) {
+        PyErr_Format (PyExc_TypeError, "Trying to register gtype '%s' as enum when in fact it is of type '%s'",
+                      g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype)));
         return NULL;
     }
 
index bad32c6..83aa4dc 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 1998-2003  James Henstridge
  * Copyright (C) 2004       Johan Dahlin
  *
- *   pygenum.c: GFlags wrapper
+ *   pygflags.c: GFlags wrapper
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -40,11 +40,12 @@ pyg_flags_val_new(PyObject* subclass, GType gtype, PyObject *intval)
 {
     PyObject *args, *item;
     args = Py_BuildValue("(O)", intval);
-    item =  (&PYGLIB_PyLong_Type)->tp_new((PyTypeObject*)subclass, args, NULL);
+    g_assert(PyObject_IsSubclass(subclass, (PyObject*) &PyGFlags_Type));
+    item = PYGLIB_PyLong_Type.tp_new((PyTypeObject*)subclass, args, NULL);
     Py_DECREF(args);
     if (!item)
        return NULL;
-    ((PyGEnum*)item)->gtype = gtype;
+    ((PyGFlags*)item)->gtype = gtype;
 
     return item;
 }
@@ -70,7 +71,7 @@ pyg_flags_richcompare(PyGFlags *self, PyObject *other, int op)
 }
 
 static char *
-generate_repr(GType gtype, int value)
+generate_repr(GType gtype, guint value)
 {
     GFlagsClass *flags_class;
     char *retval = NULL, *tmp;
@@ -108,13 +109,13 @@ pyg_flags_repr(PyGFlags *self)
     char *tmp, *retval;
     PyObject *pyretval;
 
-    tmp = generate_repr(self->gtype, PYGLIB_PyLong_AS_LONG(self));
+    tmp = generate_repr(self->gtype, PYGLIB_PyLong_AsUnsignedLong(self));
 
     if (tmp)
         retval = g_strdup_printf("<flags %s of type %s>", tmp,
                                  g_type_name(self->gtype));
     else
-        retval = g_strdup_printf("<flags %ld of type %s>", PYGLIB_PyLong_AS_LONG(self),
+        retval = g_strdup_printf("<flags %ld of type %s>", PYGLIB_PyLong_AsUnsignedLong(self),
                                  g_type_name(self->gtype));
     g_free(tmp);
 
@@ -128,7 +129,7 @@ static PyObject *
 pyg_flags_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 {
     static char *kwlist[] = { "value", NULL };
-    long value;
+    guint value;
     PyObject *pytc, *values, *ret, *pyint;
     GType gtype;
     GFlagsClass *eclass;
@@ -167,7 +168,7 @@ pyg_flags_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 
     g_type_class_unref(eclass);
 
-    pyint = PYGLIB_PyLong_FromLong(value);
+    pyint = PYGLIB_PyLong_FromUnsignedLong(value);
     ret = PyDict_GetItem(values, pyint);
     if (!ret) {
         PyErr_Clear();
@@ -185,10 +186,13 @@ pyg_flags_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
 }
 
 PyObject*
-pyg_flags_from_gtype (GType gtype, int value)
+pyg_flags_from_gtype (GType gtype, guint value)
 {
     PyObject *pyclass, *values, *retval, *pyint;
 
+    if (PyErr_Occurred())
+        return PYGLIB_PyLong_FromUnsignedLong(0);
+
     g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
 
     /* Get a wrapper class by:
@@ -202,11 +206,11 @@ pyg_flags_from_gtype (GType gtype, int value)
     if (!pyclass)
         pyclass = pyg_flags_add(NULL, g_type_name(gtype), NULL, gtype);
     if (!pyclass)
-       return PYGLIB_PyLong_FromLong(value);
+       return PYGLIB_PyLong_FromUnsignedLong(value);
 
     values = PyDict_GetItemString(((PyTypeObject *)pyclass)->tp_dict,
                                  "__flags_values__");
-    pyint = PYGLIB_PyLong_FromLong(value);
+    pyint = PYGLIB_PyLong_FromUnsignedLong(value);
     retval = PyDict_GetItem(values, pyint);
     if (!retval) {
        PyErr_Clear();
@@ -221,6 +225,10 @@ pyg_flags_from_gtype (GType gtype, int value)
     return retval;
 }
 
+/*
+ * pyg_flags_add
+ * Dynamically create a class derived from PyGFlags based on the given GType.
+ */
 PyObject *
 pyg_flags_add (PyObject *   module,
               const char * typename,
@@ -241,13 +249,16 @@ pyg_flags_add (PyObject *   module,
 
     state = pyglib_gil_state_ensure();
 
+    /* Create a new type derived from GFlags. This is the same as:
+     * >>> stub = type(typename, (GFlags,), {})
+     */
     instance_dict = PyDict_New();
     stub = PyObject_CallFunction((PyObject *)&PyType_Type, "s(O)O",
                                  typename, (PyObject *)&PyGFlags_Type,
                                  instance_dict);
     Py_DECREF(instance_dict);
     if (!stub) {
-       PyErr_SetString(PyExc_RuntimeError, "can't create const");
+       PyErr_SetString(PyExc_RuntimeError, "can't create GFlags subtype");
        pyglib_gil_state_release(state);
         return NULL;
     }
@@ -277,7 +288,8 @@ pyg_flags_add (PyObject *   module,
     for (i = 0; i < eclass->n_values; i++) {
       PyObject *item, *intval;
       
-      intval = PYGLIB_PyLong_FromLong(eclass->values[i].value);
+      intval = PYGLIB_PyLong_FromUnsignedLong(eclass->values[i].value);
+      g_assert(PyErr_Occurred() == NULL);
       item = pyg_flags_val_new(stub, gtype, intval);
       PyDict_SetItem(values, intval, item);
       Py_DECREF(intval);
@@ -312,7 +324,7 @@ pyg_flags_and(PyGFlags *a, PyGFlags *b)
                                                       (PyObject*)b);
 
        return pyg_flags_from_gtype(a->gtype,
-                                   PYGLIB_PyLong_AS_LONG(a) & PYGLIB_PyLong_AS_LONG(b));
+                                   PYGLIB_PyLong_AsUnsignedLong(a) & PYGLIB_PyLong_AsUnsignedLong(b));
 }
 
 static PyObject *
@@ -322,7 +334,7 @@ pyg_flags_or(PyGFlags *a, PyGFlags *b)
                return PYGLIB_PyLong_Type.tp_as_number->nb_or((PyObject*)a,
                                                      (PyObject*)b);
 
-       return pyg_flags_from_gtype(a->gtype, PYGLIB_PyLong_AS_LONG(a) | PYGLIB_PyLong_AS_LONG(b));
+       return pyg_flags_from_gtype(a->gtype, PYGLIB_PyLong_AsUnsignedLong(a) | PYGLIB_PyLong_AsUnsignedLong(b));
 }
 
 static PyObject *
@@ -333,7 +345,7 @@ pyg_flags_xor(PyGFlags *a, PyGFlags *b)
                                                       (PyObject*)b);
 
        return pyg_flags_from_gtype(a->gtype,
-                                   PYGLIB_PyLong_AS_LONG(a) ^ PYGLIB_PyLong_AS_LONG(b));
+                                   PYGLIB_PyLong_AsUnsignedLong(a) ^ PYGLIB_PyLong_AsUnsignedLong(b));
 
 }
 
@@ -356,7 +368,7 @@ pyg_flags_get_first_value_name(PyGFlags *self, void *closure)
 
   flags_class = g_type_class_ref(self->gtype);
   g_assert(G_IS_FLAGS_CLASS(flags_class));
-  flags_value = g_flags_get_first_value(flags_class, PYGLIB_PyLong_AS_LONG(self));
+  flags_value = g_flags_get_first_value(flags_class, PYGLIB_PyLong_AsUnsignedLong(self));
   if (flags_value)
       retval = PYGLIB_PyUnicode_FromString(flags_value->value_name);
   else {
@@ -378,7 +390,7 @@ pyg_flags_get_first_value_nick(PyGFlags *self, void *closure)
   flags_class = g_type_class_ref(self->gtype);
   g_assert(G_IS_FLAGS_CLASS(flags_class));
 
-  flags_value = g_flags_get_first_value(flags_class, PYGLIB_PyLong_AS_LONG(self));
+  flags_value = g_flags_get_first_value(flags_class, PYGLIB_PyLong_AsUnsignedLong(self));
   if (flags_value)
       retval = PYGLIB_PyUnicode_FromString(flags_value->value_nick);
   else {
@@ -402,7 +414,7 @@ pyg_flags_get_value_names(PyGFlags *self, void *closure)
 
   retval = PyList_New(0);
   for (i = 0; i < flags_class->n_values; i++)
-      if ((PYGLIB_PyLong_AS_LONG(self) & flags_class->values[i].value) == flags_class->values[i].value)
+      if ((PYGLIB_PyLong_AsUnsignedLong(self) & flags_class->values[i].value) == flags_class->values[i].value)
          PyList_Append(retval, PYGLIB_PyUnicode_FromString(flags_class->values[i].value_name));
 
   g_type_class_unref(flags_class);
@@ -422,8 +434,11 @@ pyg_flags_get_value_nicks(PyGFlags *self, void *closure)
 
   retval = PyList_New(0);
   for (i = 0; i < flags_class->n_values; i++)
-      if ((PYGLIB_PyLong_AS_LONG(self) & flags_class->values[i].value) == flags_class->values[i].value)
-         PyList_Append(retval, PYGLIB_PyUnicode_FromString(flags_class->values[i].value_nick));
+      if ((PYGLIB_PyLong_AsUnsignedLong(self) & flags_class->values[i].value) == flags_class->values[i].value) {
+         PyObject *py_nick = PYGLIB_PyUnicode_FromString(flags_class->values[i].value_nick);
+         PyList_Append(retval, py_nick);
+         Py_DECREF (py_nick);
+      }
 
   g_type_class_unref(flags_class);
 
index 1b1d6db..e1fc2b6 100644 (file)
@@ -107,7 +107,7 @@ GType     pyg_type_from_object_strict (PyObject *obj, gboolean strict);
 GType     pyg_type_from_object (PyObject *obj);
 
 gint pyg_enum_get_value  (GType enum_type, PyObject *obj, gint *val);
-gint pyg_flags_get_value (GType flag_type, PyObject *obj, gint *val);
+gint pyg_flags_get_value (GType flag_type, PyObject *obj, guint *val);
 int pyg_pyobj_to_unichar_conv (PyObject* py_obj, void* ptr);
 
 typedef PyObject *(* fromvaluefunc)(const GValue *value);
@@ -154,12 +154,10 @@ void          pygobject_register_class   (PyObject *dict,
                                          PyObject *bases);
 void          pygobject_register_wrapper (PyObject *self);
 PyObject *    pygobject_new              (GObject *obj);
-PyObject *    pygobject_new_full         (GObject *obj, gboolean sink, gpointer g_class);
+PyObject *    pygobject_new_full         (GObject *obj, gboolean steal, gpointer g_class);
 void          pygobject_sink             (GObject *obj);
 PyTypeObject *pygobject_lookup_class     (GType gtype);
 void          pygobject_watch_closure    (PyObject *self, GClosure *closure);
-void          pygobject_register_sinkfunc(GType type,
-                                         void (* sinkfunc)(GObject *object));
 int           pyg_type_register          (PyTypeObject *class,
                                          const gchar *type_name);
 
@@ -181,7 +179,8 @@ const gchar * pyg_constant_strip_prefix(const gchar *name, const gchar *strip_pr
 
 /* pygflags */
 typedef struct {
-       PYGLIB_PyLongObject parent;
+    PYGLIB_PyLongObject parent;
+    int zero_pad; /* must always be 0 */
     GType gtype;
 } PyGFlags;
 
@@ -194,13 +193,14 @@ extern PyObject * pyg_flags_add        (PyObject *   module,
                                        const char * strip_prefix,
                                        GType        gtype);
 extern PyObject * pyg_flags_from_gtype (GType        gtype,
-                                       int          value);
+                                       guint        value);
 
 /* pygenum */
 #define PyGEnum_Check(x) (PyObject_IsInstance((PyObject *)x, (PyObject *)&PyGEnum_Type) && g_type_is_a(((PyGFlags*)x)->gtype, G_TYPE_ENUM))
 
 typedef struct {
-       PYGLIB_PyLongObject parent;
+    PYGLIB_PyLongObject parent;
+    int zero_pad; /* must always be 0 */
     GType gtype;
 } PyGEnum;
 
index 3d0c819..93b42ee 100644 (file)
@@ -341,8 +341,14 @@ set_property_from_pspec(GObject *obj,
 
     g_value_init(&value, G_PARAM_SPEC_VALUE_TYPE(pspec));
     if (pyg_param_gvalue_from_pyobject(&value, pvalue, pspec) < 0) {
-       PyErr_SetString(PyExc_TypeError,
-                       "could not convert argument to correct param type");
+        PyObject *pvalue_str = PyObject_Str(pvalue);
+       PyErr_Format(PyExc_TypeError,
+                    "could not convert '%s' to type '%s' when setting property '%s.%s'",
+                    PYGLIB_PyUnicode_AsString(pvalue_str),
+                    g_type_name(G_PARAM_SPEC_VALUE_TYPE(pspec)),
+                    G_OBJECT_TYPE_NAME(obj),
+                    pspec->name);
+       Py_DECREF(pvalue_str);
        return FALSE;
     }
 
@@ -951,7 +957,7 @@ pygobject_lookup_class(GType gtype)
 /**
  * pygobject_new_full:
  * @obj: a GObject instance.
- * @sink: whether to sink any floating reference found on the GObject. DEPRECATED.
+ * @steal: whether to steal a ref from the GObject or add (sink) a new one.
  * @g_class: the GObjectClass
  *
  * This function gets a reference to a wrapper for the given GObject
@@ -962,19 +968,30 @@ pygobject_lookup_class(GType gtype)
  * Returns: a reference to the wrapper for the GObject.
  */
 PyObject *
-pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class)
+pygobject_new_full(GObject *obj, gboolean steal, gpointer g_class)
 {
     PyGObject *self;
 
     if (obj == NULL) {
-       Py_INCREF(Py_None);
-       return Py_None;
+        Py_RETURN_NONE;
     }
 
-    /* we already have a wrapper for this object -- return it. */
+    /* If the GObject already has a PyObject wrapper stashed in its qdata, re-use it.
+     */
     self = (PyGObject *)g_object_get_qdata(obj, pygobject_wrapper_key);
     if (self != NULL) {
-       pygobject_ref_sink(self);
+        /* Note the use of "pygobject_ref_sink" here only deals with PyObject
+         * wrapper ref counts and has nothing to do with GObject.
+         */
+        pygobject_ref_sink(self);
+
+        /* If steal is true, we also want to decref the incoming GObjects which
+         * already have a Python wrapper because the wrapper is already holding a
+         * strong reference.
+         */
+        if (steal)
+            g_object_unref (obj);
+
     } else {
        /* create wrapper */
         PyGObjectData *inst_data = pyg_object_peek_inst_data(obj);
@@ -1000,10 +1017,15 @@ pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class)
        self->weakreflist = NULL;
        self->private_flags.flags = 0;
        self->obj = obj;
-        /* if we are creating a wrapper around a newly created object, it can have
-           a floating ref (e.g. for methods like Gtk.Button.new()). Bug 640868 */
-       g_object_ref_sink(obj);
-       pygobject_register_wrapper((PyObject *)self);
+
+        /* If we are not stealing a ref or the object is floating,
+         * add a regular ref or sink the object. */
+        if (g_object_is_floating (obj))
+            self->private_flags.flags |= PYGOBJECT_GOBJECT_WAS_FLOATING;
+        if (!steal || self->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING)
+            g_object_ref_sink (obj);
+
+        pygobject_register_wrapper((PyObject *)self);
        PyObject_GC_Track((PyObject *)self);
     }
 
@@ -1014,7 +1036,9 @@ pygobject_new_full(GObject *obj, gboolean sink, gpointer g_class)
 PyObject *
 pygobject_new(GObject *obj)
 {
-    return pygobject_new_full(obj, TRUE, NULL);
+    return pygobject_new_full(obj,
+                              /*steal=*/FALSE,
+                              NULL);
 }
 
 static void
@@ -1371,6 +1395,7 @@ pygobject_set_property(PyGObject *self, PyObject *args)
     gchar *param_name;
     GParamSpec *pspec;
     PyObject *pvalue;
+    int ret = -1;
 
     if (!PyArg_ParseTuple(args, "sO:GObject.set_property", &param_name,
                          &pvalue))
@@ -1387,9 +1412,17 @@ pygobject_set_property(PyGObject *self, PyObject *args)
        return NULL;
     }
     
+    ret = pygi_set_property_value (self, pspec, pvalue);
+    if (ret == 0)
+       goto done;
+    else if (PyErr_Occurred())
+        return  NULL;
+
     if (!set_property_from_pspec(self->obj, pspec, pvalue))
        return NULL;
-    
+
+done:
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1413,6 +1446,7 @@ pygobject_set_properties(PyGObject *self, PyObject *args, PyObject *kwargs)
     while (kwargs && PyDict_Next (kwargs, &pos, &key, &value)) {
        gchar *key_str = PYGLIB_PyUnicode_AsString(key);
        GParamSpec *pspec;
+       int ret = -1;
 
        pspec = g_object_class_find_property(class, key_str);
        if (!pspec) {
@@ -1425,8 +1459,17 @@ pygobject_set_properties(PyGObject *self, PyObject *args, PyObject *kwargs)
            goto exit;
        }
 
-       if (!set_property_from_pspec(G_OBJECT(self->obj), pspec, value))
-           goto exit;
+        ret = pygi_set_property_value (self, pspec, value);
+        if (ret != 0) {
+            /* Non-zero return code means that either an error occured ...*/
+            if (PyErr_Occurred())
+                goto exit;
+
+            /* ... or the property couldn't be found , so let's try the default
+             * call. */
+            if (!set_property_from_pspec(G_OBJECT(self->obj), pspec, value))
+                goto exit;
+        }
     }
 
     result = Py_None;
@@ -1814,65 +1857,9 @@ pygobject_connect_object_after(PyGObject *self, PyObject *args)
 }
 
 static PyObject *
-pygobject_disconnect(PyGObject *self, PyObject *args)
-{
-    gulong handler_id;
-
-    if (!PyArg_ParseTuple(args, "k:GObject.disconnect", &handler_id))
-       return NULL;
-    
-    CHECK_GOBJECT(self);
-    
-    g_signal_handler_disconnect(self->obj, handler_id);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *
-pygobject_handler_is_connected(PyGObject *self, PyObject *args)
-{
-    gulong handler_id;
-
-    if (!PyArg_ParseTuple(args, "k:GObject.handler_is_connected", &handler_id))
-       return NULL;
-
-    
-    CHECK_GOBJECT(self);
-    
-    return PyBool_FromLong(g_signal_handler_is_connected(self->obj, handler_id));
-}
-
-static PyObject *
-pygobject_handler_block(PyGObject *self, PyObject *args)
-{
-    gulong handler_id;
-
-    if (!PyArg_ParseTuple(args, "k:GObject.handler_block", &handler_id))
-       return NULL;
-
-    CHECK_GOBJECT(self);
-
-    g_signal_handler_block(self->obj, handler_id);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *
-pygobject_handler_unblock(PyGObject *self, PyObject *args)
-{
-    gulong handler_id;
-
-    if (!PyArg_ParseTuple(args, "k:GObject.handler_unblock", &handler_id))
-       return NULL;
-    g_signal_handler_unblock(self->obj, handler_id);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *
 pygobject_emit(PyGObject *self, PyObject *args)
 {
-    guint signal_id, i;
+    guint signal_id, i, j;
     Py_ssize_t len;
     GQuark detail;
     PyObject *first, *py_ret, *repr = NULL;
@@ -1929,11 +1916,11 @@ pygobject_emit(PyGObject *self, PyObject *args)
            g_snprintf(buf, sizeof(buf),
                       "could not convert type %s to %s required for parameter %d",
                       Py_TYPE(item)->tp_name,
-               g_type_name(G_VALUE_TYPE(&params[i+1])), i);
+                       G_VALUE_TYPE_NAME(&params[i+1]), i);
            PyErr_SetString(PyExc_TypeError, buf);
 
-           for (i = 0; i < query.n_params + 1; i++)
-               g_value_unset(&params[i]);
+           for (j = 0; j <= i; j++)
+               g_value_unset(&params[j]);
 
            g_free(params);
            return NULL;
@@ -1961,33 +1948,6 @@ pygobject_emit(PyGObject *self, PyObject *args)
 }
 
 static PyObject *
-pygobject_stop_emission(PyGObject *self, PyObject *args)
-{
-    gchar *signal;
-    guint signal_id;
-    GQuark detail;
-    PyObject *repr = NULL;
-
-    if (!PyArg_ParseTuple(args, "s:GObject.stop_emission", &signal))
-       return NULL;
-    
-    CHECK_GOBJECT(self);
-    
-    if (!g_signal_parse_name(signal, G_OBJECT_TYPE(self->obj),
-                            &signal_id, &detail, TRUE)) {
-       repr = PyObject_Repr((PyObject*)self);
-       PyErr_Format(PyExc_TypeError, "%s: unknown signal name: %s",
-                    PYGLIB_PyUnicode_AsString(repr),
-                    signal);
-       Py_DECREF(repr);
-       return NULL;
-    }
-    g_signal_stop_emission(self->obj, signal_id, detail);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject *
 pygobject_chain_from_overridden(PyGObject *self, PyObject *args)
 {
     GSignalInvocationHint *ihint;
@@ -2219,17 +2179,10 @@ static PyMethodDef pygobject_methods[] = {
     { "connect_after", (PyCFunction)pygobject_connect_after, METH_VARARGS },
     { "connect_object", (PyCFunction)pygobject_connect_object, METH_VARARGS },
     { "connect_object_after", (PyCFunction)pygobject_connect_object_after, METH_VARARGS },
-    { "disconnect", (PyCFunction)pygobject_disconnect, METH_VARARGS },
     { "disconnect_by_func", (PyCFunction)pygobject_disconnect_by_func, METH_VARARGS },
-    { "handler_disconnect", (PyCFunction)pygobject_disconnect, METH_VARARGS },
-    { "handler_is_connected", (PyCFunction)pygobject_handler_is_connected, METH_VARARGS },
-    { "handler_block", (PyCFunction)pygobject_handler_block, METH_VARARGS },
-    { "handler_unblock", (PyCFunction)pygobject_handler_unblock,METH_VARARGS },
     { "handler_block_by_func", (PyCFunction)pygobject_handler_block_by_func, METH_VARARGS },
     { "handler_unblock_by_func", (PyCFunction)pygobject_handler_unblock_by_func, METH_VARARGS },
     { "emit", (PyCFunction)pygobject_emit, METH_VARARGS },
-    { "stop_emission", (PyCFunction)pygobject_stop_emission, METH_VARARGS },
-    { "emit_stop_by_name", (PyCFunction)pygobject_stop_emission,METH_VARARGS },
     { "chain", (PyCFunction)pygobject_chain_from_overridden,METH_VARARGS },
     { "weak_ref", (PyCFunction)pygobject_weak_ref, METH_VARARGS },
     { "__copy__", (PyCFunction)pygobject_copy, METH_NOARGS },
@@ -2256,12 +2209,18 @@ static PyObject *
 pygobject_get_refcount(PyGObject *self, void *closure)
 {
     if (self->obj == NULL) {
-       PyErr_Format(PyExc_TypeError, "GObject instance is not yet created");
-       return NULL;
+        PyErr_Format(PyExc_TypeError, "GObject instance is not yet created");
+        return NULL;
     }
     return PYGLIB_PyLong_FromLong(self->obj->ref_count);
 }
 
+static PyObject *
+pygobject_get_pointer(PyGObject *self, void *closure)
+{
+    return PYGLIB_CPointer_WrapPointer (self->obj, NULL);
+}
+
 static int
 pygobject_setattro(PyObject *self, PyObject *name, PyObject *value)
 {
@@ -2280,6 +2239,7 @@ pygobject_setattro(PyObject *self, PyObject *name, PyObject *value)
 static PyGetSetDef pygobject_getsets[] = {
     { "__dict__", (getter)pygobject_get_dict, (setter)0 },
     { "__grefcount__", (getter)pygobject_get_refcount, (setter)0, },
+    { "__gpointer__", (getter)pygobject_get_pointer, (setter)0, },
     { NULL, 0, 0 }
 };
 
@@ -2407,7 +2367,7 @@ pygobject_weak_ref_call(PyGObjectWeakRef *self, PyObject *args, PyObject *kw)
         return NULL;
 
     if (self->obj)
-        return pygobject_new_full(self->obj, FALSE, NULL);
+        return pygobject_new(self->obj);
     else {
         Py_INCREF(Py_None);
         return Py_None;
index 8879fd0..15b8807 100644 (file)
@@ -24,7 +24,8 @@ struct _PyGClosure {
 
 typedef enum {
     PYGOBJECT_USING_TOGGLE_REF = 1 << 0,
-    PYGOBJECT_IS_FLOATING_REF = 1 << 1
+    PYGOBJECT_IS_FLOATING_REF = 1 << 1,
+    PYGOBJECT_GOBJECT_WAS_FLOATING = 1 << 2,
 } PyGObjectFlags;
 
   /* closures is just an alias for what is found in the
@@ -102,7 +103,7 @@ struct _PyGObject_Functions {
     PyObject *(* type_wrapper_new)(GType type);
 
     gint (* enum_get_value)(GType enum_type, PyObject *obj, gint *val);
-    gint (* flags_get_value)(GType flag_type, PyObject *obj, gint *val);
+    gint (* flags_get_value)(GType flag_type, PyObject *obj, guint *val);
     void (* register_gtype_custom)(GType gtype,
                            PyObject *(* from_func)(const GValue *value),
                            int (* to_func)(GValue *value, PyObject *obj));
@@ -167,7 +168,7 @@ struct _PyGObject_Functions {
                           const char *type_name_,
                           const char *strip_prefix,
                           GType gtype);
-    PyObject* (*flags_from_gtype)(GType gtype, int value);
+    PyObject* (*flags_from_gtype)(GType gtype, guint value);
 
     gboolean threads_enabled;
     int       (*enable_threads) (void);
@@ -187,7 +188,10 @@ struct _PyGObject_Functions {
                                      gpointer data);
     gboolean  (*gerror_exception_check) (GError **error);
     PyObject* (*option_group_new) (GOptionGroup *group);
-    GType (* type_from_object_strict) (PyObject *obj, gboolean strict);    
+    GType (* type_from_object_strict) (PyObject *obj, gboolean strict);
+
+    PyObject *(* newgobj_full)(GObject *obj, gboolean steal, gpointer g_class);
+    PyTypeObject *object_type;
 };
 
 #ifndef _INSIDE_PYGOBJECT_
@@ -202,6 +206,8 @@ struct _PyGObject_Functions *_PyGObject_API;
 #define pygobject_register_wrapper  (_PyGObject_API->register_wrapper)
 #define pygobject_lookup_class      (_PyGObject_API->lookup_class)
 #define pygobject_new               (_PyGObject_API->newgobj)
+#define pygobject_new_full          (_PyGObject_API->newgobj_full)
+#define PyGObject_Type              (*_PyGObject_API->object_type)
 #define pyg_closure_new             (_PyGObject_API->closure_new)
 #define pygobject_watch_closure     (_PyGObject_API->object_watch_closure)
 #define pyg_closure_set_exception_handler (_PyGObject_API->closure_set_exception_handler)
index 79c8387..94014ff 100644 (file)
@@ -538,7 +538,7 @@ pyg_enum_get_value(GType enum_type, PyObject *obj, gint *val)
  * Returns: 0 on success or -1 on failure
  */
 gint
-pyg_flags_get_value(GType flag_type, PyObject *obj, gint *val)
+pyg_flags_get_value(GType flag_type, PyObject *obj, guint *val)
 {
     GFlagsClass *fclass = NULL;
     gint res = -1;
@@ -548,7 +548,7 @@ pyg_flags_get_value(GType flag_type, PyObject *obj, gint *val)
        *val = 0;
        res = 0;
     } else if (PYGLIB_PyLong_Check(obj)) {
-       *val = PYGLIB_PyLong_AsLong(obj);
+       *val = PYGLIB_PyLong_AsUnsignedLong(obj);
        res = 0;
     } else if (PyLong_Check(obj)) {
         *val = PyLong_AsLongLong(obj);
@@ -727,6 +727,63 @@ pyg_value_array_from_pyobject(GValue *value,
     return 0;
 }
 
+static int
+pyg_array_from_pyobject(GValue *value,
+                       PyObject *obj)
+{
+    int len;
+    GArray *array;
+    int i;
+
+    len = PySequence_Length(obj);
+    if (len == -1) {
+       PyErr_Clear();
+       return -1;
+    }
+
+    array = g_array_new(FALSE, TRUE, sizeof(GValue));
+
+    for (i = 0; i < len; ++i) {
+       PyObject *item = PySequence_GetItem(obj, i);
+       GType type;
+       GValue item_value = { 0, };
+       int status;
+
+       if (! item) {
+           PyErr_Clear();
+           g_array_free(array, FALSE);
+           return -1;
+       }
+
+       if (item == Py_None)
+           type = G_TYPE_POINTER; /* store None as NULL */
+       else {
+           type = pyg_type_from_object((PyObject*)Py_TYPE(item));
+           if (! type) {
+               PyErr_Clear();
+               g_array_free(array, FALSE);
+               Py_DECREF(item);
+               return -1;
+           }
+       }
+
+       g_value_init(&item_value, type);
+       status = pyg_value_from_pyobject(&item_value, item);
+       Py_DECREF(item);
+
+       if (status == -1) {
+           g_array_free(array, FALSE);
+           g_value_unset(&item_value);
+           return -1;
+       }
+
+       g_array_append_val(array, item_value);
+    }
+
+    g_value_take_boxed(value, array);
+    return 0;
+}
+
 /**
  * pyg_value_from_pyobject:
  * @value: the GValue object to store the converted value in.
@@ -766,12 +823,20 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
        }
        break;
     case G_TYPE_CHAR:
+       if (PYGLIB_PyLong_Check(obj)) {
+           glong val;
+           val = PYGLIB_PyLong_AsLong(obj);
+           if (val >= -128 && val <= 127)
+               g_value_set_schar(value, (gchar) val);
+           else
+               return -1;
+       }
 #if PY_VERSION_HEX < 0x03000000
-       if (PyString_Check(obj)) {
+       else if (PyString_Check(obj)) {
            g_value_set_schar(value, PyString_AsString(obj)[0]);
-       } else
+       }
 #endif
-       if (PyUnicode_Check(obj)) {
+       else if (PyUnicode_Check(obj)) {
            tmp = PyUnicode_AsUTF8String(obj);
            g_value_set_schar(value, PYGLIB_PyBytes_AsString(tmp)[0]);
            Py_DECREF(tmp);
@@ -786,7 +851,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
            glong val;
            val = PYGLIB_PyLong_AsLong(obj);
            if (val >= 0 && val <= 255)
-             g_value_set_uchar(value, (guchar)PYGLIB_PyLong_AsLong (obj));
+             g_value_set_uchar(value, (guchar) val);
            else
              return -1;
 #if PY_VERSION_HEX < 0x03000000
@@ -879,7 +944,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
        break;
     case G_TYPE_FLAGS:
        {
-           gint val = 0;
+           guint val = 0;
            if (pyg_flags_get_value(G_VALUE_TYPE(value), obj, &val) < 0) {
                PyErr_Clear();
                return -1;
@@ -959,6 +1024,9 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
         else if (PySequence_Check(obj) &&
                   G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY))
            return pyg_value_array_from_pyobject(value, obj, NULL);
+        else if (PySequence_Check(obj) &&
+                  G_VALUE_HOLDS(value, G_TYPE_ARRAY))
+           return pyg_array_from_pyobject(value, obj);
        else if (PYGLIB_PyUnicode_Check(obj) &&
                  G_VALUE_HOLDS(value, G_TYPE_GSTRING)) {
             GString *string;
@@ -980,7 +1048,11 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj)
        break;
     }
     case G_TYPE_PARAM:
-       if (PyGParamSpec_Check(obj))
+        /* we need to support both the wrapped _gobject.GParamSpec and the GI
+         * GObject.ParamSpec */
+        if (G_IS_PARAM_SPEC (pygobject_get (obj)))
+           g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj)));
+        else if (PyGParamSpec_Check(obj))
            g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL));
        else
            return -1;
index 76530f1..108fc77 100644 (file)
@@ -62,7 +62,9 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
     gint n_values;
     GEnumValue *g_enum_values;
     int i;
+    const gchar *namespace;
     const gchar *type_name;
+    gchar *full_name;
     GType g_type;
 
     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
@@ -79,6 +81,10 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
 
     info = (GIEnumInfo *)py_info->info;
     n_values = g_enum_info_get_n_values (info);
+
+    /* The new memory is zero filled which fulfills the registration
+     * function requirement that the last item is zeroed out as a terminator.
+     */
     g_enum_values = g_new0 (GEnumValue, n_values + 1);
 
     for (i = 0; i < n_values; i++) {
@@ -105,14 +111,39 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self,
         g_base_info_unref ((GIBaseInfo *) value_info);
     }
 
-    g_enum_values[n_values].value = 0;
-    g_enum_values[n_values].value_nick = NULL;
-    g_enum_values[n_values].value_name = NULL;
-
+    /* Obfuscate the full_name by prefixing it with "Py" to avoid conflicts
+     * with real GTypes. See: https://bugzilla.gnome.org/show_bug.cgi?id=692515
+     */
+    namespace = g_base_info_get_namespace ((GIBaseInfo *) info);
     type_name = g_base_info_get_name ((GIBaseInfo *) info);
-    type_name = g_strdup (type_name);
-    g_type = g_enum_register_static (type_name, g_enum_values);
+    full_name = g_strconcat ("Py", namespace, type_name, NULL);
+
+    /* If enum registration fails, free all the memory allocated
+     * for the values array. This needs to leak when successful
+     * as GObject keeps a reference to the data as specified in the docs.
+     */
+    g_type = g_enum_register_static (full_name, g_enum_values);
+    if (g_type == G_TYPE_INVALID) {
+        for (i = 0; i < n_values; i++) {
+            GEnumValue *enum_value = &g_enum_values[i];
+
+            /* Only free value_name if it is different from value_nick to avoid
+             * a double free. The pointer might have been is re-used in the case
+             * c_identifier was NULL in the above loop.
+             */
+            if (enum_value->value_name != enum_value->value_nick)
+                g_free ((gchar *) enum_value->value_name);
+            g_free ((gchar *) enum_value->value_nick);
+        }
+
+        PyErr_Format (PyExc_RuntimeError, "Unable to register enum '%s'", full_name);
+
+        g_free (g_enum_values);
+        g_free (full_name);
+        return NULL;
+    }
 
+    g_free (full_name);
     return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type);
 }
 
@@ -150,7 +181,9 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
     gint n_values;
     GFlagsValue *g_flags_values;
     int i;
+    const gchar *namespace;
     const gchar *type_name;
+    gchar *full_name;
     GType g_type;
 
     if (!PyArg_ParseTupleAndKeywords (args, kwargs,
@@ -167,6 +200,10 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
 
     info = (GIEnumInfo *)py_info->info;
     n_values = g_enum_info_get_n_values (info);
+
+    /* The new memory is zero filled which fulfills the registration
+     * function requirement that the last item is zeroed out as a terminator.
+     */
     g_flags_values = g_new0 (GFlagsValue, n_values + 1);
 
     for (i = 0; i < n_values; i++) {
@@ -193,14 +230,39 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self,
         g_base_info_unref ((GIBaseInfo *) value_info);
     }
 
-    g_flags_values[n_values].value = 0;
-    g_flags_values[n_values].value_nick = NULL;
-    g_flags_values[n_values].value_name = NULL;
-
+    /* Obfuscate the full_name by prefixing it with "Py" to avoid conflicts
+     * with real GTypes. See: https://bugzilla.gnome.org/show_bug.cgi?id=692515
+     */
+    namespace = g_base_info_get_namespace ((GIBaseInfo *) info);
     type_name = g_base_info_get_name ((GIBaseInfo *) info);
-    type_name = g_strdup (type_name);
-    g_type = g_flags_register_static (type_name, g_flags_values);
+    full_name = g_strconcat ("Py", namespace, type_name, NULL);
+
+    /* If enum registration fails, free all the memory allocated
+     * for the values array. This needs to leak when successful
+     * as GObject keeps a reference to the data as specified in the docs.
+     */
+    g_type = g_flags_register_static (full_name, g_flags_values);
+    if (g_type == G_TYPE_INVALID) {
+        for (i = 0; i < n_values; i++) {
+            GFlagsValue *flags_value = &g_flags_values[i];
+
+            /* Only free value_name if it is different from value_nick to avoid
+             * a double free. The pointer might have been is re-used in the case
+             * c_identifier was NULL in the above loop.
+             */
+            if (flags_value->value_name != flags_value->value_nick)
+                g_free ((gchar *) flags_value->value_name);
+            g_free ((gchar *) flags_value->value_nick);
+        }
+
+        PyErr_Format (PyExc_RuntimeError, "Unable to register flags '%s'", full_name);
+
+        g_free (g_flags_values);
+        g_free (full_name);
+        return NULL;
+    }
 
+    g_free (full_name);
     return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type);
 }
 
@@ -451,7 +513,7 @@ _wrap_pyg_variant_type_from_string (PyObject *self, PyObject *args)
 
     py_type = _pygi_type_import_by_name ("GLib", "VariantType");
 
-    py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE);
+    py_variant = _pygi_boxed_new ( (PyTypeObject *) py_type, type_string, FALSE, 0);
 
     return py_variant;
 }
index 6ae5dba..3e660d1 100644 (file)
@@ -21,6 +21,7 @@
 
 import signal
 import warnings
+import sys
 
 from ..module import get_introspection_module
 from .._gi import (variant_new_tuple, variant_type_from_string, source_new,
@@ -220,7 +221,11 @@ class Variant(GLib.Variant):
         return self.print_(True)
 
     def __repr__(self):
-        return "GLib.Variant('%s', %s)" % (self.format_string, self.print_(True))
+        if hasattr(self, 'format_string'):
+            f = self.format_string
+        else:
+            f = self.get_type_string()
+        return "GLib.Variant('%s', %s)" % (f, self.print_(False))
 
     def __eq__(self, other):
         try:
@@ -287,6 +292,11 @@ class Variant(GLib.Variant):
         if self.get_type_string().startswith('v'):
             return self.get_variant().unpack()
 
+        # maybe
+        if self.get_type_string().startswith('m'):
+            m = self.get_maybe()
+            return m.unpack() if m else None
+
         raise NotImplementedError('unsupported GVariant type ' + self.get_type_string())
 
     @classmethod
@@ -489,16 +499,17 @@ class MainLoop(GLib.MainLoop):
         def _handler(loop):
             loop.quit()
             loop._quit_by_sigint = True
-
-        # compatibility shim, keep around until we depend on glib 2.36
-        if hasattr(GLib, 'unix_signal_add'):
-            fn = GLib.unix_signal_add
-        else:
-            fn = GLib.unix_signal_add_full
-        self._signal_source = fn(GLib.PRIORITY_DEFAULT, signal.SIGINT, _handler, self)
+        if sys.platform != 'win32':
+            # compatibility shim, keep around until we depend on glib 2.36
+            if hasattr(GLib, 'unix_signal_add'):
+                fn = GLib.unix_signal_add
+            else:
+                fn = GLib.unix_signal_add_full
+            self._signal_source = fn(GLib.PRIORITY_DEFAULT, signal.SIGINT, _handler, self)
 
     def __del__(self):
-        GLib.source_remove(self._signal_source)
+        if hasattr(self, '_signal_source'):
+            GLib.source_remove(self._signal_source)
 
     def run(self):
         super(MainLoop, self).run()
@@ -528,6 +539,10 @@ class Source(GLib.Source):
         setattr(source, '__pygi_custom_source', True)
         return source
 
+    def __del__(self):
+        if hasattr(self, '__pygi_custom_source'):
+            self.unref()
+
     # Backwards compatible API for optional arguments
     def attach(self, context=None):
         id = super(Source, self).attach(context)
index c0198b3..eea8928 100644 (file)
@@ -3,7 +3,8 @@
 #
 # Copyright (C) 2012 Canonical Ltd.
 # Author: Martin Pitt <martin.pitt@ubuntu.com>
-# Copyright (C) 2012 Simon Feltman <sfeltman@src.gnome.org>
+# Copyright (C) 2012-2013 Simon Feltman <sfeltman@src.gnome.org>
+# Copyright (C) 2012 Bastian Winkler <buz@netbuz.org>
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
 # USA
 
 import sys
+import warnings
+import functools
 from collections import namedtuple
 
 import gi.overrides
 import gi.module
 from gi.overrides import override
 from gi.repository import GLib
+from gi import PyGIDeprecationWarning
 
 from gi._gobject import _gobject
 from gi._gobject import propertyhelper
@@ -129,13 +133,15 @@ TYPE_GTYPE = GObjectModule.type_from_name('GType')
 TYPE_STRV = GObjectModule.type_from_name('GStrv')
 TYPE_VARIANT = GObjectModule.type_from_name('GVariant')
 TYPE_GSTRING = GObjectModule.type_from_name('GString')
+TYPE_VALUE = GObjectModule.Value.__gtype__
 TYPE_UNICHAR = TYPE_UINT
 __all__ += ['TYPE_INVALID', 'TYPE_NONE', 'TYPE_INTERFACE', 'TYPE_CHAR',
             'TYPE_UCHAR', 'TYPE_BOOLEAN', 'TYPE_INT', 'TYPE_UINT', 'TYPE_LONG',
             'TYPE_ULONG', 'TYPE_INT64', 'TYPE_UINT64', 'TYPE_ENUM', 'TYPE_FLAGS',
             'TYPE_FLOAT', 'TYPE_DOUBLE', 'TYPE_STRING', 'TYPE_POINTER',
             'TYPE_BOXED', 'TYPE_PARAM', 'TYPE_OBJECT', 'TYPE_PYOBJECT',
-            'TYPE_GTYPE', 'TYPE_STRV', 'TYPE_VARIANT', 'TYPE_GSTRING', 'TYPE_UNICHAR']
+            'TYPE_GTYPE', 'TYPE_STRV', 'TYPE_VARIANT', 'TYPE_GSTRING',
+            'TYPE_UNICHAR', 'TYPE_VALUE']
 
 
 # Deprecated, use GLib directly
@@ -188,27 +194,149 @@ __all__ += ['GBoxed', 'GEnum', 'GFlags', 'GInterface', 'GObject',
             'Warning']
 
 
-add_emission_hook = _gobject.add_emission_hook
 features = _gobject.features
 list_properties = _gobject.list_properties
 new = _gobject.new
 pygobject_version = _gobject.pygobject_version
-remove_emission_hook = _gobject.remove_emission_hook
-signal_accumulator_true_handled = _gobject.signal_accumulator_true_handled
-signal_new = _gobject.signal_new
 threads_init = _gobject.threads_init
 type_register = _gobject.type_register
-__all__ += ['add_emission_hook', 'features', 'list_properties',
-            'new', 'pygobject_version', 'remove_emission_hook',
-            'signal_accumulator_true_handled',
-            'signal_new', 'threads_init', 'type_register']
+__all__ += ['features', 'list_properties', 'new',
+            'pygobject_version', 'threads_init', 'type_register']
 
 
 class Value(GObjectModule.Value):
+    def __new__(cls, *args, **kwargs):
+        return GObjectModule.Value.__new__(cls)
+
+    def __init__(self, value_type=None, py_value=None):
+        GObjectModule.Value.__init__(self)
+        if value_type is not None:
+            self.init(value_type)
+            if py_value is not None:
+                self.set_value(py_value)
+
     def __del__(self):
-        if self._free_on_dealloc:
+        if self._free_on_dealloc and self.g_type != TYPE_INVALID:
             self.unset()
 
+    def set_value(self, py_value):
+        gtype = self.g_type
+
+        if gtype == _gobject.TYPE_INVALID:
+            raise TypeError("GObject.Value needs to be initialized first")
+        elif gtype == TYPE_BOOLEAN:
+            self.set_boolean(py_value)
+        elif gtype == TYPE_CHAR:
+            self.set_char(py_value)
+        elif gtype == TYPE_UCHAR:
+            self.set_uchar(py_value)
+        elif gtype == TYPE_INT:
+            self.set_int(py_value)
+        elif gtype == TYPE_UINT:
+            self.set_uint(py_value)
+        elif gtype == TYPE_LONG:
+            self.set_long(py_value)
+        elif gtype == TYPE_ULONG:
+            self.set_ulong(py_value)
+        elif gtype == TYPE_INT64:
+            self.set_int64(py_value)
+        elif gtype == TYPE_UINT64:
+            self.set_uint64(py_value)
+        elif gtype == TYPE_FLOAT:
+            self.set_float(py_value)
+        elif gtype == TYPE_DOUBLE:
+            self.set_double(py_value)
+        elif gtype == TYPE_STRING:
+            if isinstance(py_value, str):
+                py_value = str(py_value)
+            elif sys.version_info < (3, 0):
+                if isinstance(py_value, unicode):
+                    py_value = py_value.encode('UTF-8')
+                else:
+                    raise ValueError("Expected string or unicode but got %s%s" %
+                                     (py_value, type(py_value)))
+            else:
+                raise ValueError("Expected string but got %s%s" %
+                                 (py_value, type(py_value)))
+            self.set_string(py_value)
+        elif gtype == TYPE_PARAM:
+            self.set_param(py_value)
+        elif gtype.is_a(TYPE_ENUM):
+            self.set_enum(py_value)
+        elif gtype.is_a(TYPE_FLAGS):
+            self.set_flags(py_value)
+        elif gtype.is_a(TYPE_BOXED):
+            self.set_boxed(py_value)
+        elif gtype == TYPE_POINTER:
+            self.set_pointer(py_value)
+        elif gtype.is_a(TYPE_OBJECT):
+            self.set_object(py_value)
+        elif gtype == TYPE_UNICHAR:
+            self.set_uint(int(py_value))
+        # elif gtype == TYPE_OVERRIDE:
+        #     pass
+        elif gtype == TYPE_GTYPE:
+            self.set_gtype(py_value)
+        elif gtype == TYPE_VARIANT:
+            self.set_variant(py_value)
+        elif gtype == TYPE_PYOBJECT:
+            self.set_boxed(py_value)
+        else:
+            raise TypeError("Unknown value type %s" % gtype)
+
+    def get_value(self):
+        gtype = self.g_type
+
+        if gtype == TYPE_BOOLEAN:
+            return self.get_boolean()
+        elif gtype == TYPE_CHAR:
+            return self.get_char()
+        elif gtype == TYPE_UCHAR:
+            return self.get_uchar()
+        elif gtype == TYPE_INT:
+            return self.get_int()
+        elif gtype == TYPE_UINT:
+            return self.get_uint()
+        elif gtype == TYPE_LONG:
+            return self.get_long()
+        elif gtype == TYPE_ULONG:
+            return self.get_ulong()
+        elif gtype == TYPE_INT64:
+            return self.get_int64()
+        elif gtype == TYPE_UINT64:
+            return self.get_uint64()
+        elif gtype == TYPE_FLOAT:
+            return self.get_float()
+        elif gtype == TYPE_DOUBLE:
+            return self.get_double()
+        elif gtype == TYPE_STRING:
+            return self.get_string()
+        elif gtype == TYPE_PARAM:
+            return self.get_param()
+        elif gtype.is_a(TYPE_ENUM):
+            return self.get_enum()
+        elif gtype.is_a(TYPE_FLAGS):
+            return self.get_flags()
+        elif gtype.is_a(TYPE_BOXED):
+            return self.get_boxed()
+        elif gtype == TYPE_POINTER:
+            return self.get_pointer()
+        elif gtype.is_a(TYPE_OBJECT):
+            return self.get_object()
+        elif gtype == TYPE_UNICHAR:
+            return self.get_uint()
+        elif gtype == TYPE_GTYPE:
+            return self.get_gtype()
+        elif gtype == TYPE_VARIANT:
+            return self.get_variant()
+        elif gtype == TYPE_PYOBJECT:
+            pass
+        else:
+            return None
+
+    def __repr__(self):
+        return '<Value (%s) %s>' % (self.g_type.name, self.get_value())
+
 Value = override(Value)
 __all__.append('Value')
 
@@ -288,6 +416,20 @@ def signal_query(id_or_name, type_=None):
 __all__.append('signal_query')
 
 
+def _get_instance_for_signal(obj):
+    if isinstance(obj, GObjectModule.Object):
+        return obj.__gpointer__
+    else:
+        raise TypeError('Unsupported object "%s" for signal function' % obj)
+
+
+def _wrap_signal_func(func):
+    @functools.wraps(func)
+    def wrapper(obj, *args, **kwargs):
+        return func(_get_instance_for_signal(obj), *args, **kwargs)
+    return wrapper
+
+
 class _HandlerBlockManager(object):
     def __init__(self, obj, handler_id):
         self.obj = obj
@@ -297,7 +439,101 @@ class _HandlerBlockManager(object):
         pass
 
     def __exit__(self, exc_type, exc_value, traceback):
-        _gobject.GObject.handler_unblock(self.obj, self.handler_id)
+        signal_handler_unblock(self.obj, self.handler_id)
+
+
+def signal_handler_block(obj, handler_id):
+    """Blocks the signal handler from being invoked until handler_unblock() is called.
+
+    Returns a context manager which optionally can be used to
+    automatically unblock the handler:
+
+    >>> with GObject.signal_handler_block(obj, id):
+    >>>    pass
+    """
+    GObjectModule.signal_handler_block(_get_instance_for_signal(obj), handler_id)
+    return _HandlerBlockManager(obj, handler_id)
+
+__all__.append('signal_handler_block')
+
+
+# The following functions wrap GI functions but coerce the first arg into
+# something compatible with gpointer
+
+signal_handler_unblock = _wrap_signal_func(GObjectModule.signal_handler_unblock)
+signal_handler_disconnect = _wrap_signal_func(GObjectModule.signal_handler_disconnect)
+signal_handler_is_connected = _wrap_signal_func(GObjectModule.signal_handler_is_connected)
+signal_stop_emission = _wrap_signal_func(GObjectModule.signal_stop_emission)
+signal_stop_emission_by_name = _wrap_signal_func(GObjectModule.signal_stop_emission_by_name)
+signal_has_handler_pending = _wrap_signal_func(GObjectModule.signal_has_handler_pending)
+signal_get_invocation_hint = _wrap_signal_func(GObjectModule.signal_get_invocation_hint)
+signal_connect_closure = _wrap_signal_func(GObjectModule.signal_connect_closure)
+signal_connect_closure_by_id = _wrap_signal_func(GObjectModule.signal_connect_closure_by_id)
+signal_handler_find = _wrap_signal_func(GObjectModule.signal_handler_find)
+signal_handlers_destroy = _wrap_signal_func(GObjectModule.signal_handlers_destroy)
+signal_handlers_block_matched = _wrap_signal_func(GObjectModule.signal_handlers_block_matched)
+signal_handlers_unblock_matched = _wrap_signal_func(GObjectModule.signal_handlers_unblock_matched)
+signal_handlers_disconnect_matched = _wrap_signal_func(GObjectModule.signal_handlers_disconnect_matched)
+
+__all__ += ['signal_handler_unblock',
+            'signal_handler_disconnect', 'signal_handler_is_connected',
+            'signal_stop_emission', 'signal_stop_emission_by_name',
+            'signal_has_handler_pending', 'signal_get_invocation_hint',
+            'signal_connect_closure', 'signal_connect_closure_by_id',
+            'signal_handler_find', 'signal_handlers_destroy',
+            'signal_handlers_block_matched', 'signal_handlers_unblock_matched',
+            'signal_handlers_disconnect_matched']
+
+
+def signal_parse_name(detailed_signal, itype, force_detail_quark):
+    """Parse a detailed signal name into (signal_id, detail).
+
+    :Raises ValueError:
+        If the given signal is unknown.
+
+    :Returns:
+        Tuple of (signal_id, detail)
+    """
+    res, signal_id, detail = GObjectModule.signal_parse_name(detailed_signal, itype,
+                                                             force_detail_quark)
+    if res:
+        return signal_id, detail
+    else:
+        raise ValueError('%s: unknown signal name: %s' % (itype, detailed_signal))
+
+__all__.append('signal_parse_name')
+
+
+def remove_emission_hook(obj, detailed_signal, hook_id):
+    signal_id, detail = signal_parse_name(detailed_signal, obj, True)
+    GObjectModule.signal_remove_emission_hook(signal_id, hook_id)
+
+__all__.append('remove_emission_hook')
+
+
+# GObject accumulators with pure Python implementations
+# These return a tuple of (continue_emission, accumulation_result)
+
+def signal_accumulator_first_wins(ihint, return_accu, handler_return, user_data=None):
+    # Stop emission but return the result of the last handler
+    return (False, handler_return)
+
+__all__.append('signal_accumulator_first_wins')
+
+
+def signal_accumulator_true_handled(ihint, return_accu, handler_return, user_data=None):
+    # Stop emission if the last handler returns True
+    return (not handler_return, handler_return)
+
+__all__.append('signal_accumulator_true_handled')
+
+
+# Statically bound signal functions which need to clobber GI (for now)
+
+add_emission_hook = _gobject.add_emission_hook
+signal_new = _gobject.signal_new
+
+__all__ += ['add_emission_hook', 'signal_new']
 
 
 class _FreezeNotifyManager(object):
@@ -333,18 +569,23 @@ class Object(GObjectModule.Object):
     # they work as gi methods.
     bind_property_full = _unsupported_method
     compat_control = _unsupported_method
-    force_floating = _unsupported_method
     interface_find_property = _unsupported_method
     interface_install_property = _unsupported_method
     interface_list_properties = _unsupported_method
-    is_floating = _unsupported_method
     notify_by_pspec = _unsupported_method
+    run_dispose = _unsupported_method
+    watch_closure = _unsupported_method
+
+    # Make all reference management methods private but still accessible.
+    _ref = GObjectModule.Object.ref
+    _ref_sink = GObjectModule.Object.ref_sink
+    _unref = GObjectModule.Object.unref
+    _force_floating = GObjectModule.Object.force_floating
+
     ref = _unsupported_method
-    ref_count = _unsupported_method
     ref_sink = _unsupported_method
-    run_dispose = _unsupported_method
     unref = _unsupported_method
-    watch_closure = _unsupported_method
+    force_floating = _unsupported_method
 
     # The following methods are static APIs which need to leap frog the
     # gi methods until we verify the gi methods can replace them.
@@ -357,38 +598,15 @@ class Object(GObjectModule.Object):
     connect_after = _gobject.GObject.connect_after
     connect_object = _gobject.GObject.connect_object
     connect_object_after = _gobject.GObject.connect_object_after
-    disconnect = _gobject.GObject.disconnect
     disconnect_by_func = _gobject.GObject.disconnect_by_func
-    handler_disconnect = _gobject.GObject.handler_disconnect
-    handler_is_connected = _gobject.GObject.handler_is_connected
     handler_block_by_func = _gobject.GObject.handler_block_by_func
     handler_unblock_by_func = _gobject.GObject.handler_unblock_by_func
     emit = _gobject.GObject.emit
-    emit_stop_by_name = _gobject.GObject.emit_stop_by_name
-    stop_emission = _gobject.GObject.stop_emission
     chain = _gobject.GObject.chain
     weak_ref = _gobject.GObject.weak_ref
     __copy__ = _gobject.GObject.__copy__
     __deepcopy__ = _gobject.GObject.__deepcopy__
 
-    def handler_block(self, handler_id):
-        """Blocks the signal handler from being invoked until handler_unblock() is called.
-
-        Returns a context manager which optionally can be used to
-        automatically unblock the handler:
-
-        >>> with obj.handler_block(id):
-        >>>    pass
-        """
-
-        # Note Object.handler_block is a static method specific to pygobject and not
-        # found in introspection. We need to continue using the static method
-        # until we figure out a technique to call the global signal_handler_block.
-        # But this requires a gpointer to the Object which we currently don't have
-        # access to in python.
-        _gobject.GObject.handler_block(self, handler_id)
-        return _HandlerBlockManager(self, handler_id)
-
     def freeze_notify(self):
         """Freezes the object's property-changed notification queue.
 
@@ -404,6 +622,28 @@ class Object(GObjectModule.Object):
         super(Object, self).freeze_notify()
         return _FreezeNotifyManager(self)
 
+    #
+    # Aliases
+    #
+
+    disconnect = signal_handler_disconnect
+    handler_block = signal_handler_block
+    handler_unblock = signal_handler_unblock
+    handler_disconnect = signal_handler_disconnect
+    handler_is_connected = signal_handler_is_connected
+    stop_emission_by_name = signal_stop_emission_by_name
+
+    #
+    # Deprecated Methods
+    #
+
+    def stop_emission(self, detailed_signal):
+        """Deprecated, please use stop_emission_by_name."""
+        warnings.warn(self.stop_emission.__doc__, PyGIDeprecationWarning, stacklevel=2)
+        return signal_stop_emission_by_name(self, detailed_signal)
+
+    emit_stop_by_name = stop_emission
+
 
 Object = override(Object)
 GObject = Object
index dc06f92..14edc70 100644 (file)
@@ -19,7 +19,7 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 # USA
 
-from ..overrides import override
+from ..overrides import override, strip_boolean_result
 from ..module import get_introspection_module
 
 import sys
@@ -251,19 +251,6 @@ gsuccess_mask_funcs = ['get_state',
                        'get_root_coords']
 
 
-def _gsuccess_mask(func):
-    def cull_success(*args):
-        result = func(*args)
-        success = result[0]
-        if not success:
-            return None
-        else:
-            if len(result) == 2:
-                return result[1]
-            else:
-                return result[1:]
-    return cull_success
-
 for event_class in event_member_classes:
     override_class = type(event_class, (getattr(Gdk, event_class),), {})
     # add the event methods
@@ -276,7 +263,7 @@ for event_class in event_member_classes:
 
         # use the _gsuccess_mask decorator if this method is whitelisted
         if name in gsuccess_mask_funcs:
-            event_method = _gsuccess_mask(event_method)
+            event_method = strip_boolean_result(event_method)
         setattr(override_class, name, event_method)
 
     setattr(module, event_class, override_class)
@@ -335,15 +322,8 @@ class Cursor(Gdk.Cursor):
 Cursor = override(Cursor)
 __all__.append('Cursor')
 
-_Gdk_color_parse = Gdk.color_parse
-
-
-@override(Gdk.color_parse)
-def color_parse(color):
-    success, color = _Gdk_color_parse(color)
-    if not success:
-        return None
-    return color
+color_parse = strip_boolean_result(Gdk.color_parse)
+__all__.append('color_parse')
 
 
 # Note, we cannot override the entire class as Gdk.Atom has no gtype, so just
@@ -421,5 +401,3 @@ if Gdk._version >= '3.0':
 import sys
 
 initialized, argv = Gdk.init_check(sys.argv)
-if not initialized:
-    raise RuntimeError("Gdk couldn't be initialized")
index 78bbd36..ab09a26 100644 (file)
@@ -21,7 +21,7 @@
 
 import sys
 from gi.repository import GObject
-from ..overrides import override
+from ..overrides import override, strip_boolean_result
 from ..module import get_introspection_module
 from gi import PyGIDeprecationWarning
 
@@ -48,17 +48,40 @@ python module to use with Gtk 2.0"
     warnings.warn(warn_msg, RuntimeWarning)
 
 
+def _construct_target_list(targets):
+    """Create a list of TargetEntry items from a list of tuples in the form (target, flags, info)
+
+    The list can also contain existing TargetEntry items in which case the existing entry
+    is re-used in the return list.
+    """
+    target_entries = []
+    for entry in targets:
+        if not isinstance(entry, Gtk.TargetEntry):
+            entry = Gtk.TargetEntry.new(*entry)
+        target_entries.append(entry)
+    return target_entries
+
+__all__.append('_construct_target_list')
+
+
 class Widget(Gtk.Widget):
 
-    def translate_coordinates(self, dest_widget, src_x, src_y):
-        success, dest_x, dest_y = super(Widget, self).translate_coordinates(
-            dest_widget, src_x, src_y)
-        if success:
-            return (dest_x, dest_y,)
+    translate_coordinates = strip_boolean_result(Gtk.Widget.translate_coordinates)
 
     def render_icon(self, stock_id, size, detail=None):
         return super(Widget, self).render_icon(stock_id, size, detail)
 
+    def drag_dest_set_target_list(self, target_list):
+        if not isinstance(target_list, Gtk.TargetList):
+            target_list = Gtk.TargetList.new(_construct_target_list(target_list))
+        super(Widget, self).drag_dest_set_target_list(target_list)
+
+    def drag_source_set_target_list(self, target_list):
+        if not isinstance(target_list, Gtk.TargetList):
+            target_list = Gtk.TargetList.new(_construct_target_list(target_list))
+        super(Widget, self).drag_source_set_target_list(target_list)
+
+
 Widget = override(Widget)
 __all__.append('Widget')
 
@@ -80,10 +103,8 @@ class Container(Gtk.Container, Widget):
     # alias for Python 2.x object protocol
     __nonzero__ = __bool__
 
-    def get_focus_chain(self):
-        success, widgets = super(Container, self).get_focus_chain()
-        if success:
-            return widgets
+    get_focus_chain = strip_boolean_result(Gtk.Container.get_focus_chain)
+
 
 Container = override(Container)
 __all__.append('Container')
@@ -92,16 +113,10 @@ __all__.append('Container')
 class Editable(Gtk.Editable):
 
     def insert_text(self, text, position):
-        pos = super(Editable, self).insert_text(text, -1, position)
+        return super(Editable, self).insert_text(text, -1, position)
 
-        return pos
+    get_selection_bounds = strip_boolean_result(Gtk.TextBuffer.get_selection_bounds, fail_ret=())
 
-    def get_selection_bounds(self):
-        success, start_pos, end_pos = super(Editable, self).get_selection_bounds()
-        if success:
-            return (start_pos, end_pos,)
-        else:
-            return tuple()
 
 Editable = override(Editable)
 __all__.append("Editable")
@@ -294,7 +309,7 @@ class UIManager(Gtk.UIManager):
         if not isinstance(buffer, _basestring):
             raise TypeError('buffer must be a string')
 
-        length = len(buffer)
+        length = len(buffer.encode('UTF-8'))
 
         return Gtk.UIManager.add_ui_from_string(self, buffer, length)
 
@@ -306,11 +321,7 @@ __all__.append('UIManager')
 
 
 class ComboBox(Gtk.ComboBox, Container):
-
-    def get_active_iter(self):
-        success, aiter = super(ComboBox, self).get_active_iter()
-        if success:
-            return aiter
+    get_active_iter = strip_boolean_result(Gtk.ComboBox.get_active_iter)
 
 ComboBox = override(ComboBox)
 __all__.append('ComboBox')
@@ -401,6 +412,9 @@ __all__.append('Builder')
 
 class Window(Gtk.Window):
     def __init__(self, type=Gtk.WindowType.TOPLEVEL, **kwds):
+        if not initialized:
+            raise RuntimeError("Gtk couldn't be initialized")
+
         # type is a construct-only property; if it is already set (e. g. by
         # GtkBuilder), do not try to set it again and just ignore it
         try:
@@ -581,20 +595,9 @@ class IconView(Gtk.IconView):
     def __init__(self, model=None, **kwds):
         Gtk.IconView.__init__(self, model=model, **kwds)
 
-    def get_item_at_pos(self, x, y):
-        success, path, cell = super(IconView, self).get_item_at_pos(x, y)
-        if success:
-            return (path, cell,)
-
-    def get_visible_range(self):
-        success, start_path, end_path = super(IconView, self).get_visible_range()
-        if success:
-            return (start_path, end_path,)
-
-    def get_dest_item_at_pos(self, drag_x, drag_y):
-        success, path, pos = super(IconView, self).get_dest_item_at_pos(drag_x, drag_y)
-        if success:
-            return path, pos
+    get_item_at_pos = strip_boolean_result(Gtk.IconView.get_item_at_pos)
+    get_visible_range = strip_boolean_result(Gtk.IconView.get_visible_range)
+    get_dest_item_at_pos = strip_boolean_result(Gtk.IconView.get_dest_item_at_pos)
 
 IconView = override(IconView)
 __all__.append('IconView')
@@ -610,22 +613,14 @@ __all__.append('ToolButton')
 
 
 class IMContext(Gtk.IMContext):
-
-    def get_surrounding(self):
-        success, text, cursor_index = super(IMContext, self).get_surrounding()
-        if success:
-            return (text, cursor_index,)
+    get_surrounding = strip_boolean_result(Gtk.IMContext.get_surrounding)
 
 IMContext = override(IMContext)
 __all__.append('IMContext')
 
 
 class RecentInfo(Gtk.RecentInfo):
-
-    def get_application_info(self, app_name):
-        success, app_exec, count, time = super(RecentInfo, self).get_application_info(app_name)
-        if success:
-            return (app_exec, count, time,)
+    get_application_info = strip_boolean_result(Gtk.RecentInfo.get_application_info)
 
 RecentInfo = override(RecentInfo)
 __all__.append('RecentInfo')
@@ -709,12 +704,7 @@ class TextBuffer(Gtk.TextBuffer):
 
         Gtk.TextBuffer.insert_at_cursor(self, text, length)
 
-    def get_selection_bounds(self):
-        success, start, end = super(TextBuffer, self).get_selection_bounds()
-        if success:
-            return (start, end)
-        else:
-            return ()
+    get_selection_bounds = strip_boolean_result(Gtk.TextBuffer.get_selection_bounds, fail_ret=())
 
 TextBuffer = override(TextBuffer)
 __all__.append('TextBuffer')
@@ -722,21 +712,8 @@ __all__.append('TextBuffer')
 
 class TextIter(Gtk.TextIter):
 
-    def forward_search(self, string, flags, limit):
-        success, match_start, match_end = super(TextIter, self).forward_search(string,
-                                                                               flags, limit)
-        if success:
-            return (match_start, match_end)
-        else:
-            return None
-
-    def backward_search(self, string, flags, limit):
-        success, match_start, match_end = super(TextIter, self).backward_search(string,
-                                                                                flags, limit)
-        if success:
-            return (match_start, match_end)
-        else:
-            return None
+    forward_search = strip_boolean_result(Gtk.TextIter.forward_search)
+    backward_search = strip_boolean_result(Gtk.TextIter.backward_search)
 
     def begins_tag(self, tag=None):
         return super(TextIter, self).begins_tag(tag)
@@ -780,6 +757,12 @@ class TreeModel(Gtk.TreeModel):
                 raise IndexError("could not find tree path '%s'" % key)
             return aiter
 
+    def _coerce_path(self, path):
+        if isinstance(path, Gtk.TreePath):
+            return path
+        else:
+            return TreePath(path)
+
     def __getitem__(self, key):
         aiter = self._getiter(key)
         return TreeModelRow(self, aiter)
@@ -795,26 +778,20 @@ class TreeModel(Gtk.TreeModel):
     def __iter__(self):
         return TreeModelRowIter(self, self.get_iter_first())
 
-    def get_iter(self, path):
-        if not isinstance(path, Gtk.TreePath):
-            path = TreePath(path)
+    get_iter_first = strip_boolean_result(Gtk.TreeModel.get_iter_first)
+    iter_children = strip_boolean_result(Gtk.TreeModel.iter_children)
+    iter_nth_child = strip_boolean_result(Gtk.TreeModel.iter_nth_child)
+    iter_parent = strip_boolean_result(Gtk.TreeModel.iter_parent)
+    get_iter_from_string = strip_boolean_result(Gtk.TreeModel.get_iter_from_string,
+                                                ValueError, 'invalid tree path')
 
+    def get_iter(self, path):
+        path = self._coerce_path(path)
         success, aiter = super(TreeModel, self).get_iter(path)
         if not success:
             raise ValueError("invalid tree path '%s'" % path)
         return aiter
 
-    def get_iter_first(self):
-        success, aiter = super(TreeModel, self).get_iter_first()
-        if success:
-            return aiter
-
-    def get_iter_from_string(self, path_string):
-        success, aiter = super(TreeModel, self).get_iter_from_string(path_string)
-        if not success:
-            raise ValueError("invalid tree path '%s'" % path_string)
-        return aiter
-
     def iter_next(self, aiter):
         next_iter = aiter.copy()
         success = super(TreeModel, self).iter_next(next_iter)
@@ -827,21 +804,6 @@ class TreeModel(Gtk.TreeModel):
         if success:
             return prev_iter
 
-    def iter_children(self, aiter):
-        success, child_iter = super(TreeModel, self).iter_children(aiter)
-        if success:
-            return child_iter
-
-    def iter_nth_child(self, parent, n):
-        success, child_iter = super(TreeModel, self).iter_nth_child(parent, n)
-        if success:
-            return child_iter
-
-    def iter_parent(self, aiter):
-        success, parent_iter = super(TreeModel, self).iter_parent(aiter)
-        if success:
-            return parent_iter
-
     def _convert_row(self, row):
         # TODO: Accept a dictionary for row
         # model.append(None,{COLUMN_ICON: icon, COLUMN_NAME: name})
@@ -872,84 +834,11 @@ class TreeModel(Gtk.TreeModel):
             self.set_value(treeiter, column, value)
 
     def _convert_value(self, column, value):
-        if value is None:
-            return None
-
-        # we may need to convert to a basic type
-        type_ = self.get_column_type(column)
-        if type_ == GObject.TYPE_STRING:
-            if isinstance(value, str):
-                value = str(value)
-            elif sys.version_info < (3, 0):
-                if isinstance(value, unicode):
-                    value = value.encode('UTF-8')
-                else:
-                    raise ValueError('Expected string or unicode for column %i but got %s%s' % (column, value, type(value)))
-            else:
-                raise ValueError('Expected a string for column %i but got %s' % (column, type(value)))
-        elif type_ == GObject.TYPE_FLOAT or type_ == GObject.TYPE_DOUBLE:
-            if isinstance(value, float):
-                value = float(value)
-            else:
-                raise ValueError('Expected a float for column %i but got %s' % (column, type(value)))
-        elif type_ == GObject.TYPE_LONG or type_ == GObject.TYPE_INT:
-            if isinstance(value, int):
-                value = int(value)
-            elif sys.version_info < (3, 0):
-                if isinstance(value, long):
-                    value = long(value)
-                else:
-                    raise ValueError('Expected an long for column %i but got %s' % (column, type(value)))
-            else:
-                raise ValueError('Expected an integer for column %i but got %s' % (column, type(value)))
-        elif type_ == GObject.TYPE_BOOLEAN:
-            cmp_classes = [int]
-            if sys.version_info < (3, 0):
-                cmp_classes.append(long)
-
-            if isinstance(value, tuple(cmp_classes)):
-                value = bool(value)
-            else:
-                raise ValueError('Expected a bool for column %i but got %s' % (column, type(value)))
-        else:
-            # use GValues directly to marshal to the correct type
-            # standard object checks should take care of validation
-            # so we don't have to do it here
-            value_container = GObject.Value()
-            value_container.init(type_)
-            if type_ == GObject.TYPE_CHAR:
-                value_container.set_char(value)
-                value = value_container
-            elif type_ == GObject.TYPE_UCHAR:
-                value_container.set_uchar(value)
-                value = value_container
-            elif type_ == GObject.TYPE_UNICHAR:
-                cmp_classes = [str]
-                if sys.version_info < (3, 0):
-                    cmp_classes.append(unicode)
-
-                if isinstance(value, tuple(cmp_classes)):
-                    value = ord(value[0])
-
-                value_container.set_uint(value)
-                value = value_container
-            elif type_ == GObject.TYPE_UINT:
-                value_container.set_uint(value)
-                value = value_container
-            elif type_ == GObject.TYPE_ULONG:
-                value_container.set_ulong(value)
-                value = value_container
-            elif type_ == GObject.TYPE_INT64:
-                value_container.set_int64(value)
-                value = value_container
-            elif type_ == GObject.TYPE_UINT64:
-                value_container.set_uint64(value)
-                value = value_container
-            elif type_ == GObject.TYPE_PYOBJECT:
-                value_container.set_boxed(value)
-                value = value_container
-
-        return value
+        '''Convert value to a GObject.Value of the expected type'''
+
+        if isinstance(value, GObject.Value):
+            return value
+        return GObject.Value(self.get_column_type(column), value)
 
     def get(self, treeiter, *columns):
         n_columns = self.get_n_columns()
@@ -969,18 +858,34 @@ class TreeModel(Gtk.TreeModel):
     def filter_new(self, root=None):
         return super(TreeModel, self).filter_new(root)
 
+    #
+    # Signals supporting python iterables as tree paths
+    #
+    def row_changed(self, path, iter):
+        return super(TreeModel, self).row_changed(self._coerce_path(path), iter)
+
+    def row_inserted(self, path, iter):
+        return super(TreeModel, self).row_inserted(self._coerce_path(path), iter)
+
+    def row_has_child_toggled(self, path, iter):
+        return super(TreeModel, self).row_has_child_toggled(self._coerce_path(path),
+                                                            iter)
+
+    def row_deleted(self, path):
+        return super(TreeModel, self).row_deleted(self._coerce_path(path))
+
+    def rows_reordered(self, path, iter, new_order):
+        return super(TreeModel, self).rows_reordered(self._coerce_path(path),
+                                                     iter, new_order)
+
+
 TreeModel = override(TreeModel)
 __all__.append('TreeModel')
 
 
 class TreeSortable(Gtk.TreeSortable, ):
 
-    def get_sort_column_id(self):
-        success, sort_column_id, order = super(TreeSortable, self).get_sort_column_id()
-        if success:
-            return (sort_column_id, order,)
-        else:
-            return (None, None,)
+    get_sort_column_id = strip_boolean_result(Gtk.TreeSortable.get_sort_column_id, fail_ret=(None, None))
 
     def set_sort_func(self, sort_column_id, sort_func, user_data=None):
         super(TreeSortable, self).set_sort_func(sort_column_id, sort_func, user_data)
@@ -1205,7 +1110,7 @@ class TreePath(Gtk.TreePath):
     def __new__(cls, path=0):
         if isinstance(path, int):
             path = str(path)
-        elif isinstance(path, tuple):
+        elif not isinstance(path, _basestring):
             path = ":".join(str(val) for val in path)
 
         if len(path) == 0:
@@ -1336,38 +1241,18 @@ class TreeView(Gtk.TreeView, Container):
         if model:
             self.set_model(model)
 
-    def get_path_at_pos(self, x, y):
-        success, path, column, cell_x, cell_y = super(TreeView, self).get_path_at_pos(x, y)
-        if success:
-            return (path, column, cell_x, cell_y,)
-
-    def get_visible_range(self):
-        success, start_path, end_path = super(TreeView, self).get_visible_range()
-        if success:
-            return (start_path, end_path,)
-
-    def get_dest_row_at_pos(self, drag_x, drag_y):
-        success, path, pos = super(TreeView, self).get_dest_row_at_pos(drag_x, drag_y)
-        if success:
-            return (path, pos,)
-
-    def _construct_target_list(self, targets):
-        # FIXME: this should most likely be part of Widget or a global helper
-        #        function
-        target_entries = []
-        for t in targets:
-            entry = Gtk.TargetEntry.new(*t)
-            target_entries.append(entry)
-        return target_entries
+    get_path_at_pos = strip_boolean_result(Gtk.TreeView.get_path_at_pos)
+    get_visible_range = strip_boolean_result(Gtk.TreeView.get_visible_range)
+    get_dest_row_at_pos = strip_boolean_result(Gtk.TreeView.get_dest_row_at_pos)
 
     def enable_model_drag_source(self, start_button_mask, targets, actions):
-        target_entries = self._construct_target_list(targets)
+        target_entries = _construct_target_list(targets)
         super(TreeView, self).enable_model_drag_source(start_button_mask,
                                                        target_entries,
                                                        actions)
 
     def enable_model_drag_dest(self, targets, actions):
-        target_entries = self._construct_target_list(targets)
+        target_entries = _construct_target_list(targets)
         super(TreeView, self).enable_model_drag_dest(target_entries,
                                                      actions)
 
@@ -1408,10 +1293,7 @@ class TreeViewColumn(Gtk.TreeViewColumn):
         for (name, value) in attributes.items():
             self.add_attribute(cell_renderer, name, value)
 
-    def cell_get_position(self, cell_renderer):
-        success, start_pos, width = super(TreeViewColumn, self).cell_get_position(cell_renderer)
-        if success:
-            return (start_pos, width,)
+    cell_get_position = strip_boolean_result(Gtk.TreeViewColumn.cell_get_position)
 
     def set_cell_data_func(self, cell_renderer, func, func_data=None):
         super(TreeViewColumn, self).set_cell_data_func(cell_renderer, func, func_data)
@@ -1592,6 +1474,11 @@ class TreeModelFilter(Gtk.TreeModelFilter):
     def set_visible_func(self, func, data=None):
         super(TreeModelFilter, self).set_visible_func(func, data)
 
+    def set_value(self, iter, column, value):
+        # Delegate to child model
+        iter = self.convert_iter_to_child_iter(iter)
+        self.get_model().set_value(iter, column, value)
+
 TreeModelFilter = override(TreeModelFilter)
 __all__.append('TreeModelFilter')
 
@@ -1609,18 +1496,8 @@ _Gtk_main_quit = Gtk.main_quit
 def main_quit(*args):
     _Gtk_main_quit()
 
-_Gtk_stock_lookup = Gtk.stock_lookup
-
-
-@override(Gtk.stock_lookup)
-def stock_lookup(*args):
-    success, item = _Gtk_stock_lookup(*args)
-    if not success:
-        return None
-
-    return item
+stock_lookup = strip_boolean_result(Gtk.stock_lookup)
+__all__.append('stock_lookup')
 
 initialized, argv = Gtk.init_check(sys.argv)
 sys.argv = list(argv)
-if not initialized:
-    raise RuntimeError("Gtk couldn't be initialized")
index 14b3f4b..feed8d4 100644 (file)
@@ -216,6 +216,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
index b7d365c..99cb152 100644 (file)
@@ -55,7 +55,8 @@ class overridefunc(object):
         if not hasattr(func, '__info__'):
             raise TypeError("func must be an gi function")
         from ..importer import modules
-        self.module = modules[func.__module__]._introspection_module
+        module_name = func.__module__.rsplit('.', 1)[-1]
+        self.module = modules[module_name]._introspection_module
 
     def __call__(self, func):
         def wrapper(*args, **kwargs):
@@ -84,3 +85,25 @@ def deprecated(fn, replacement):
                       PyGIDeprecationWarning, stacklevel=2)
         return fn(*args, **kwargs)
     return wrapped
+
+
+def strip_boolean_result(method, exc_type=None, exc_str=None, fail_ret=None):
+    '''Translate method's return value for stripping off success flag.
+
+    There are a lot of methods which return a "success" boolean and have
+    several out arguments. Translate such a method to return the out arguments
+    on success and None on failure.
+    '''
+    @functools.wraps(method)
+    def wrapped(*args, **kwargs):
+        ret = method(*args, **kwargs)
+        if ret[0]:
+            if len(ret) == 2:
+                return ret[1]
+            else:
+                return ret[1:]
+        else:
+            if exc_type:
+                raise exc_type(exc_str or 'call failed')
+            return fail_ret
+    return wrapped
index 4e3c464..4cf82d0 100644 (file)
 #include <pyglib-python-compat.h>
 #include <pyglib.h>
 
+#include "pygi-marshal-from-py.h"
+#include "pygi-marshal-to-py.h"
+
+
 static gboolean
 gi_argument_to_gssize (GIArgument *arg_in,
                        GITypeTag  type_tag,
@@ -410,7 +414,8 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info,
             /* No check; every Python object has a truth value. */
             break;
         case GI_TYPE_TAG_UINT8:
-            /* UINT8 types can be characters */
+        case GI_TYPE_TAG_INT8:
+            /* (U)INT8 types can be characters */
             if (PYGLIB_PyBytes_Check(object)) {
                 if (PYGLIB_PyBytes_Size(object) != 1) {
                     PyErr_Format (PyExc_TypeError, "Must be a single character");
@@ -420,7 +425,6 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info,
 
                 break;
             }
-        case GI_TYPE_TAG_INT8:
         case GI_TYPE_TAG_INT16:
         case GI_TYPE_TAG_UINT16:
         case GI_TYPE_TAG_INT32:
@@ -476,11 +480,15 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info,
                               PyString_AS_STRING (upper_str));
 #else
                 {
-                    PyObject *lower_pybytes_obj = PyUnicode_AsUTF8String (lower_str);
-                    if (!lower_pybytes_obj)
+                    PyObject *lower_pybytes_obj;
+                    PyObject *upper_pybytes_obj;
+
+                    lower_pybytes_obj = PyUnicode_AsUTF8String (lower_str);
+                    if (!lower_pybytes_obj) {
                         goto utf8_fail;
+                    }
 
-                    PyObject *upper_pybytes_obj = PyUnicode_AsUTF8String (upper_str);                    
+                    upper_pybytes_obj = PyUnicode_AsUTF8String (upper_str);
                     if (!upper_pybytes_obj) {
                         Py_DECREF(lower_pybytes_obj);
                         goto utf8_fail;
@@ -754,8 +762,12 @@ check_number_release:
  * _pygi_argument_to_array
  * @arg: The argument to convert
  * @args: Arguments to method invocation, possibly contaning the array length.
- *        Set to NULL if this is not for a method call
- * @callable_info: Info on the callable, if this a method call; otherwise NULL
+ *        Set to %NULL if this is not for a method call or @args_values is
+ *        specified.
+ * @args_values: GValue Arguments to method invocation, possibly contaning the
+ *               array length. Set to %NULL if this is not for a method call or
+ *               @args is specified.
+ * @callable_info: Info on the callable, if this a method call; otherwise %NULL
  * @type_info: The type info for @arg
  * @out_free_array: A return location for a gboolean that indicates whether
  *                  or not the wrapped GArray should be freed
@@ -773,6 +785,7 @@ check_number_release:
 GArray *
 _pygi_argument_to_array (GIArgument  *arg,
                          GIArgument  *args[],
+                         const GValue *args_values,
                          GICallableInfo *callable_info,                  
                          GITypeInfo  *type_info,
                          gboolean    *out_free_array)
@@ -803,30 +816,38 @@ _pygi_argument_to_array (GIArgument  *arg,
             } else {
                 length = g_type_info_get_array_fixed_size (type_info);
                 if (length < 0) {
-                    if (G_UNLIKELY (args == NULL)) {
+                    gint length_arg_pos;
+                    GIArgInfo length_arg_info;
+                    GITypeInfo length_type_info;
+
+                    if (G_UNLIKELY (args == NULL && args_values == NULL)) {
                         g_critical ("Unable to determine array length for %p",
                                     arg->v_pointer);
                         g_array = g_array_new (is_zero_terminated, FALSE, item_size);
                         *out_free_array = TRUE;
                         return g_array;
                     }
-                    gint length_arg_pos;
-                    GIArgInfo *length_arg_info;
-                    GITypeInfo *length_type_info;
 
                     length_arg_pos = g_type_info_get_array_length (type_info);
                     g_assert (length_arg_pos >= 0);
                     g_assert (callable_info);
-                    length_arg_info = g_callable_info_get_arg (callable_info, length_arg_pos);
-                    length_type_info = g_arg_info_get_type (length_arg_info);
-                    g_base_info_unref ( (GIBaseInfo *) length_arg_info);
-                    if (!gi_argument_to_gssize (args[length_arg_pos],
-                                                g_type_info_get_tag (length_type_info),
-                                                &length)) {
-                        g_base_info_unref ( (GIBaseInfo *) length_type_info);
-                        return NULL;
+                    g_callable_info_load_arg (callable_info, length_arg_pos, &length_arg_info);
+                    g_arg_info_load_type (&length_arg_info, &length_type_info);
+
+                    if (args != NULL) {
+                        if (!gi_argument_to_gssize (args[length_arg_pos],
+                                                    g_type_info_get_tag (&length_type_info),
+                                                    &length))
+                            return NULL;
+                    } else {
+                        /* get it from args_values */
+                        GIArgument length_arg = _pygi_argument_from_g_value (&(args_values[length_arg_pos]),
+                                &length_type_info);
+                        if (!gi_argument_to_gssize (&length_arg,
+                                                    g_type_info_get_tag (&length_type_info),
+                                                    &length))
+                            return NULL;
                     }
-                    g_base_info_unref ( (GIBaseInfo *) length_type_info);
                 }
             }
 
@@ -834,6 +855,7 @@ _pygi_argument_to_array (GIArgument  *arg,
 
             g_array = g_array_new (is_zero_terminated, FALSE, item_size);
 
+            g_free (g_array->data);
             g_array->data = arg->v_pointer;
             g_array->len = length;
             *out_free_array = TRUE;
@@ -1234,55 +1256,20 @@ array_success:
 
                     /* Handle special cases first. */
                     if (g_type_is_a (type, G_TYPE_VALUE)) {
-                        GValue *value;
-                        GType object_type;
-                        gint retval;
-
-                        object_type = pyg_type_from_object_strict ( (PyObject *) object->ob_type, FALSE);
-                        if (object_type == G_TYPE_INVALID) {
-                            PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
-                            break;
-                        }
-
                         g_warn_if_fail (transfer == GI_TRANSFER_NOTHING);
+                        /* This will currently leak the GValue that is allocated and
+                         * stashed in arg.v_pointer. Out argument marshaling for caller
+                         * allocated GValues already pass in memory for the GValue.
+                         * Further re-factoring is needed to fix this leak.
+                         * See: https://bugzilla.gnome.org/show_bug.cgi?id=693405
+                         */
+                        pygi_marshal_from_py_gvalue (object,
+                                                     &arg,
+                                                     transfer,
+                                                     FALSE /*is_allocated*/);
 
-                        value = g_slice_new0 (GValue);
-
-                        /* if already a gvalue, copy, else marshal into gvalue */
-                        if (object_type == G_TYPE_VALUE) {
-                            /* src GValue's lifecycle is handled by Python
-                             * so we have to copy it into the destination's
-                             * GValue which is freed during the cleanup of
-                             * invoke.
-                             */
-                            GValue *src = (GValue *)((PyGObject *) object)->obj;
-                            g_value_init (value, G_VALUE_TYPE (src));
-                            g_value_copy(src, value);
-                        } else {
-                            g_value_init (value, object_type);
-                            retval = pyg_value_from_pyobject (value, object);
-                            if (retval < 0) {
-                                g_slice_free (GValue, value);
-                                PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
-                                break;
-                            }
-                        }
-
-                        arg.v_pointer = value;
                     } else if (g_type_is_a (type, G_TYPE_CLOSURE)) {
-                        GClosure *closure;
-
-                        if (pyg_type_from_object_strict (object, FALSE) == G_TYPE_CLOSURE) {
-                            closure = (GClosure *)pyg_boxed_get (object, void);
-                        } else {
-                            closure = pyg_closure_new (object, NULL, NULL);
-                            if (closure == NULL) {
-                                PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
-                                break;
-                            }
-                        }
-
-                        arg.v_pointer = closure;
+                        pygi_marshal_from_py_gclosure (object, &arg);
                     } else if (g_struct_info_is_foreign (info)) {
                         pygi_struct_foreign_convert_to_g_argument (object, info, transfer, &arg);
                     } else if (g_type_is_a (type, G_TYPE_BOXED)) {
@@ -1328,17 +1315,10 @@ array_success:
                 }
                 case GI_INFO_TYPE_INTERFACE:
                 case GI_INFO_TYPE_OBJECT:
-                    if (object == Py_None) {
-                        arg.v_pointer = NULL;
-                        break;
-                    }
-
-                    arg.v_pointer = pygobject_get (object);
-                    if (transfer == GI_TRANSFER_EVERYTHING) {
-                        g_object_ref (arg.v_pointer);
-                    }
-
+                    /* An error within this call will result in a NULL arg */
+                    pygi_marshal_from_py_gobject (object, &arg, transfer);
                     break;
+
                 default:
                     g_assert_not_reached();
             }
@@ -1773,7 +1753,7 @@ _pygi_argument_to_object (GIArgument  *arg,
                         if (py_type == NULL)
                             break;
 
-                        object = _pygi_boxed_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING);
+                        object = _pygi_boxed_new ( (PyTypeObject *) py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING, 0);
 
                         Py_DECREF (py_type);
                     } else if (g_type_is_a (type, G_TYPE_POINTER)) {
@@ -1855,27 +1835,27 @@ _pygi_argument_to_object (GIArgument  *arg,
                 }
                 case GI_INFO_TYPE_INTERFACE:
                 case GI_INFO_TYPE_OBJECT:
-                    if (arg->v_pointer == NULL) {
-                        object = Py_None;
-                        Py_INCREF (object);
-                        break;
-                    }
-
-                    if (G_IS_PARAM_SPEC (arg->v_pointer)) {
-                      object = pyg_param_spec_new (arg->v_pointer);
-                      break;
-                    }
-
-                    /* since we will unref the object when the
-                     * wrapper is destroyed and we don't want
-                     * GTK removing the object while the
-                     * wrapper is live, we take a gobject reference
-                     * when one is not transfered to us
+                    /* HACK:
+                     * The following hack is to work around GTK+ sending signals which
+                     * contain floating widgets in them. This assumes control of how
+                     * references are added by the PyGObject wrapper and avoids the sink
+                     * behavior by explicitly passing GI_TRANSFER_EVERYTHING as the transfer
+                     * mode and then re-forcing the object as floating afterwards.
+                     *
+                     * This can be deleted once the following ticket is fixed:
+                     * https://bugzilla.gnome.org/show_bug.cgi?id=693400
                      */
-                    if (transfer == GI_TRANSFER_NOTHING)
-                        g_object_ref (G_OBJECT(arg->v_pointer));
+                    if (arg->v_pointer &&
+                            !G_IS_PARAM_SPEC (arg->v_pointer) &&
+                            transfer == GI_TRANSFER_NOTHING &&
+                            g_object_is_floating (arg->v_pointer)) {
+                        g_object_ref (arg->v_pointer);
+                        object = pygi_marshal_to_py_object (arg, GI_TRANSFER_EVERYTHING);
+                        g_object_force_floating (arg->v_pointer);
+                    } else {
+                        object = pygi_marshal_to_py_object (arg, transfer);
+                    }
 
-                    object = pygobject_new (arg->v_pointer);
                     break;
                 default:
                     g_assert_not_reached();
@@ -2084,7 +2064,11 @@ _pygi_argument_from_g_value(const GValue *value,
             break;
         case GI_TYPE_TAG_ARRAY:
         case GI_TYPE_TAG_GHASH:
-            arg.v_pointer = g_value_get_boxed (value);
+            if (G_VALUE_HOLDS_BOXED (value))
+                arg.v_pointer = g_value_get_boxed (value);
+            else
+                /* e. g. GSettings::change-event */
+                arg.v_pointer = g_value_get_pointer (value);
             break;
         case GI_TYPE_TAG_INTERFACE:
         {
index a1420ee..ed88214 100644 (file)
@@ -50,6 +50,7 @@ gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info,
 
 GArray* _pygi_argument_to_array (GIArgument  *arg,
                                  GIArgument  *args[],
+                                 const GValue *args_values,
                                  GICallableInfo *callable_info,
                                  GITypeInfo  *type_info,
                                  gboolean    *out_free_array);
index ff3db9b..cac2b0d 100644 (file)
@@ -53,24 +53,19 @@ _pygi_boxed_alloc (GIBaseInfo *info, gsize *size_out)
 {
     gsize size;
 
-    /* FIXME: Remove when bgo#622711 is fixed */
-    if (g_registered_type_info_get_g_type (info) == G_TYPE_VALUE) {
-        size = sizeof (GValue);
-    } else {
-        switch (g_base_info_get_type (info)) {
-            case GI_INFO_TYPE_UNION:
-                size = g_union_info_get_size ( (GIUnionInfo *) info);
-                break;
-            case GI_INFO_TYPE_BOXED:
-            case GI_INFO_TYPE_STRUCT:
-                size = g_struct_info_get_size ( (GIStructInfo *) info);
-                break;
-            default:
-                PyErr_Format (PyExc_TypeError,
-                              "info should be Boxed or Union, not '%d'",
-                              g_base_info_get_type (info));
-                return NULL;
-        }
+    switch (g_base_info_get_type (info)) {
+        case GI_INFO_TYPE_UNION:
+            size = g_union_info_get_size ( (GIUnionInfo *) info);
+            break;
+        case GI_INFO_TYPE_BOXED:
+        case GI_INFO_TYPE_STRUCT:
+            size = g_struct_info_get_size ( (GIStructInfo *) info);
+            break;
+        default:
+            PyErr_Format (PyExc_TypeError,
+                          "info should be Boxed or Union, not '%d'",
+                          g_base_info_get_type (info));
+            return NULL;
     }
 
     if( size_out != NULL)
@@ -109,7 +104,7 @@ _boxed_new (PyTypeObject *type,
         goto out;
     }
 
-    self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, TRUE);
+    self = (PyGIBoxed *) _pygi_boxed_new (type, boxed, TRUE, size);
     if (self == NULL) {
         g_slice_free1 (size, boxed);
         goto out;
@@ -138,7 +133,8 @@ PYGLIB_DEFINE_TYPE("gi.Boxed", PyGIBoxed_Type, PyGIBoxed);
 PyObject *
 _pygi_boxed_new (PyTypeObject *type,
                  gpointer      boxed,
-                 gboolean      free_on_dealloc)
+                 gboolean      free_on_dealloc,
+                 gsize         allocated_slice)
 {
     PyGIBoxed *self;
 
@@ -159,8 +155,13 @@ _pygi_boxed_new (PyTypeObject *type,
     ( (PyGBoxed *) self)->gtype = pyg_type_from_object ( (PyObject *) type);
     ( (PyGBoxed *) self)->boxed = boxed;
     ( (PyGBoxed *) self)->free_on_dealloc = free_on_dealloc;
-    self->size = 0;
-    self->slice_allocated = FALSE;
+    if (allocated_slice > 0) {
+        self->size = allocated_slice;
+        self->slice_allocated = TRUE;
+    } else {
+        self->size = 0;
+        self->slice_allocated = FALSE;
+    }
 
     return (PyObject *) self;
 }
index a84ec4e..38ac928 100644 (file)
@@ -30,7 +30,8 @@ extern PyTypeObject PyGIBoxed_Type;
 
 PyObject * _pygi_boxed_new (PyTypeObject *type,
                             gpointer      boxed,
-                            gboolean      free_on_dealloc);
+                            gboolean      free_on_dealloc,
+                            gsize         allocated_slice);
 
 void * _pygi_boxed_alloc (GIBaseInfo *info,
                           gsize *size);
index 2a44c02..99f49cf 100644 (file)
@@ -480,6 +480,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
             child_cache = _arg_cache_alloc ();
         } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
                    child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
+            arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
             return TRUE;
         }
 
@@ -1461,6 +1462,20 @@ _pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
 
     cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);
 
+    if (g_base_info_is_deprecated (callable_info)) {
+        const gchar *deprecated = g_base_info_get_attribute (callable_info, "deprecated");
+        gchar *warning;
+        if (deprecated != NULL)
+            warning = g_strdup_printf ("%s.%s is deprecated: %s",
+                                       g_base_info_get_namespace (callable_info), cache->name,
+                                       deprecated);
+        else
+            warning = g_strdup_printf ("%s.%s is deprecated",
+                                       g_base_info_get_namespace (callable_info), cache->name);
+        PyErr_WarnEx(PyExc_DeprecationWarning, warning, 0);
+        g_free (warning);
+    }
+
     if (type == GI_INFO_TYPE_FUNCTION) {
         GIFunctionInfoFlags flags;
 
index 0e49c72..e70fd86 100644 (file)
@@ -72,9 +72,37 @@ _pygi_closure_assign_pyobj_to_retval (gpointer retval, PyObject *object,
         case GI_TYPE_TAG_DOUBLE:
            *((gdouble *) retval) = arg.v_double;
            break;
-        default:
-           *((GIArgument *) retval) = arg;
+        case GI_TYPE_TAG_GTYPE:
+           *((ffi_arg *) retval) = arg.v_ulong;
            break;
+        case GI_TYPE_TAG_UNICHAR:
+            *((ffi_arg *) retval) = arg.v_uint32;
+            break;
+        case GI_TYPE_TAG_INTERFACE:
+            {
+                GIBaseInfo* interface_info;
+                GIInfoType interface_type;
+
+                interface_info = g_type_info_get_interface(type_info);
+                interface_type = g_base_info_get_type(interface_info);
+
+                switch (interface_type) {
+                case GI_INFO_TYPE_ENUM:
+                    *(ffi_sarg *) retval = arg.v_int;
+                    break;
+                case GI_INFO_TYPE_FLAGS:
+                    *(ffi_arg *) retval = arg.v_uint;
+                    break;
+                default:
+                    *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
+                    break;
+                }
+
+                g_base_info_unref (interface_info);
+            }
+        default:
+            *(ffi_arg *) retval = (ffi_arg) arg.v_pointer;
+            break;
       }
 }
 
@@ -123,6 +151,12 @@ _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
         case GI_TYPE_TAG_DOUBLE:
            *((gdouble *) out_arg) = arg.v_double;
            break;
+        case GI_TYPE_TAG_GTYPE:
+           *((gulong *) out_arg) = arg.v_ulong;
+           break;
+        case GI_TYPE_TAG_UNICHAR:
+            *((guint32 *) out_arg) = arg.v_uint32;
+            break;
         case GI_TYPE_TAG_INTERFACE:
         {
            GIBaseInfo *interface;
@@ -131,21 +165,34 @@ _pygi_closure_assign_pyobj_to_out_argument (gpointer out_arg, PyObject *object,
            interface = g_type_info_get_interface (type_info);
            interface_type = g_base_info_get_type (interface);
 
-           if (!g_type_info_is_pointer (type_info) &&
-               interface_type == GI_INFO_TYPE_STRUCT) {
-               if (object == Py_None) {
-                   arg.v_pointer = NULL;
-               } else {
-                   gsize item_size = _pygi_g_type_info_size (type_info);
-                   memcpy (out_arg, arg.v_pointer, item_size);
+           switch (interface_type) {
+           case GI_INFO_TYPE_ENUM:
+               *(gint *) out_arg = arg.v_int;
+               break;
+           case GI_INFO_TYPE_FLAGS:
+               *(guint *) out_arg = arg.v_uint;
+               break;
+           case GI_INFO_TYPE_STRUCT:
+               if (!g_type_info_is_pointer (type_info)) {
+                   if (object != Py_None) {
+                       gsize item_size = _pygi_g_type_info_size (type_info);
+                       memcpy (out_arg, arg.v_pointer, item_size);
+                   }
+                   break;
                }
+
+           /* Fall through if pointer */
+           default:
+               *((gpointer *) out_arg) = arg.v_pointer;
                break;
            }
+
+           g_base_info_unref (interface);
+           break;
         }
 
-        /* Fall through */
         default:
-           *((GIArgument *) out_arg) = arg;
+           *((gpointer *) out_arg) = arg.v_pointer;
            break;
       }
 }
@@ -154,8 +201,8 @@ static GIArgument *
 _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
 {
     gint num_args, i;
-    GIArgInfo *arg_info;
-    GITypeInfo *arg_type;
+    GIArgInfo arg_info;
+    GITypeInfo arg_type;
     GITypeTag tag;
     GIDirection direction;
     GIArgument *g_args;
@@ -164,10 +211,10 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
     g_args = g_new0 (GIArgument, num_args);
 
     for (i = 0; i < num_args; i++) {
-        arg_info = g_callable_info_get_arg (callable_info, i);
-        arg_type = g_arg_info_get_type (arg_info);
-        tag = g_type_info_get_tag (arg_type);
-        direction = g_arg_info_get_direction (arg_info);
+        g_callable_info_load_arg (callable_info, i, &arg_info);
+        g_arg_info_load_type (&arg_info, &arg_type);
+        tag = g_type_info_get_tag (&arg_type);
+        direction = g_arg_info_get_direction (&arg_info);
 
         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
             g_args[i].v_pointer = * (gpointer *) args[i];
@@ -214,7 +261,7 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
                     GIBaseInfo *interface;
                     GIInfoType interface_type;
 
-                    interface = g_type_info_get_interface (arg_type);
+                    interface = g_type_info_get_interface (&arg_type);
                     interface_type = g_base_info_get_type (interface);
 
                     if (interface_type == GI_INFO_TYPE_OBJECT ||
@@ -249,8 +296,6 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args)
                     g_args[i].v_pointer = 0;
             }
         }
-        g_base_info_unref ( (GIBaseInfo *) arg_info);
-        g_base_info_unref ( (GIBaseInfo *) arg_type);
     }
     return g_args;
 }
@@ -279,23 +324,31 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
     g_args = _pygi_closure_convert_ffi_arguments (callable_info, args);
 
     for (i = 0; i < n_args; i++) {
+        GIArgInfo arg_info;
+        GIDirection direction;
+
         /* Special case callbacks and skip over userdata and Destroy Notify */
         if (i == user_data_arg || i == destroy_notify_arg)
             continue;
 
-        GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
-        GIDirection direction = g_arg_info_get_direction (arg_info);
+        g_callable_info_load_arg (callable_info, i, &arg_info);
+        direction = g_arg_info_get_direction (&arg_info);
 
         if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
-            GITypeInfo *arg_type = g_arg_info_get_type (arg_info);
-            GITypeTag arg_tag = g_type_info_get_tag (arg_type);
-            GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
+            GITypeInfo arg_type;
+            GITypeTag arg_tag;
+            GITransfer transfer;
             PyObject *value;
             GIArgument *arg;
-            gboolean free_array = FALSE;
+            gboolean free_array;
+
+            g_arg_info_load_type (&arg_info, &arg_type);
+            arg_tag = g_type_info_get_tag (&arg_type);
+            transfer = g_arg_info_get_ownership_transfer (&arg_info);
+            free_array = FALSE;
 
             if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID &&
-                    g_type_info_is_pointer (arg_type)) {
+                    g_type_info_is_pointer (&arg_type)) {
 
                 if (user_data == NULL) {
                     Py_INCREF (Py_None);
@@ -310,7 +363,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
                 GIBaseInfo *info;
                 GIInfoType info_type;
 
-                info = g_type_info_get_interface (arg_type);
+                info = g_type_info_get_interface (&arg_type);
                 info_type = g_base_info_get_type (info);
 
                 arg = (GIArgument*) &g_args[i];
@@ -318,10 +371,10 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
                 if (info_type == GI_INFO_TYPE_CALLBACK) {
                     gpointer user_data = NULL;
                     GDestroyNotify destroy_notify = NULL;
-                    GIScopeType scope = g_arg_info_get_scope(arg_info);
+                    GIScopeType scope = g_arg_info_get_scope(&arg_info);
 
-                    user_data_arg = g_arg_info_get_closure(arg_info);
-                    destroy_notify_arg = g_arg_info_get_destroy(arg_info);
+                    user_data_arg = g_arg_info_get_closure(&arg_info);
+                    destroy_notify_arg = g_arg_info_get_destroy(&arg_info);
 
                     if (user_data_arg != -1)
                         user_data = g_args[user_data_arg].v_pointer;
@@ -335,39 +388,31 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
                                                 (GIFunctionInfo *) info,
                                                 destroy_notify);
                 } else
-                    value = _pygi_argument_to_object (arg, arg_type, transfer);
+                    value = _pygi_argument_to_object (arg, &arg_type, transfer);
 
                 g_base_info_unref (info);
-                if (value == NULL) {
-                    g_base_info_unref (arg_type);
-                    g_base_info_unref (arg_info);
+                if (value == NULL)
                     goto error;
-                }
             } else {
                 if (direction == GI_DIRECTION_IN)
                     arg = (GIArgument*) &g_args[i];
                 else
                     arg = (GIArgument*) g_args[i].v_pointer;
                 
-                if (g_type_info_get_tag (arg_type) == GI_TYPE_TAG_ARRAY)
-                    arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, 
-                                                              callable_info, arg_type, &free_array);
+                if (g_type_info_get_tag (&arg_type) == GI_TYPE_TAG_ARRAY)
+                    arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, NULL,
+                                                              callable_info, &arg_type, &free_array);
 
-                value = _pygi_argument_to_object (arg, arg_type, transfer);
+                value = _pygi_argument_to_object (arg, &arg_type, transfer);
                 
                 if (free_array)
                     g_array_free (arg->v_pointer, FALSE);
                 
-                if (value == NULL) {
-                    g_base_info_unref (arg_type);
-                    g_base_info_unref (arg_info);
+                if (value == NULL)
                     goto error;
-                }
             }
             PyTuple_SET_ITEM (*py_args, n_in_args, value);
             n_in_args++;
-
-            g_base_info_unref (arg_type);
         }
 
         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
@@ -375,7 +420,6 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
             n_out_args++;
         }
 
-        g_base_info_unref (arg_info);
     }
 
     if (_PyTuple_Resize (py_args, n_in_args) == -1)
@@ -399,37 +443,39 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
                                  void *resp)
 {
     int n_args, i, i_py_retval, i_out_args;
-    GITypeInfo *return_type_info;
+    GITypeInfo return_type_info;
     GITypeTag return_type_tag;
 
     i_py_retval = 0;
-    return_type_info = g_callable_info_get_return_type (callable_info);
-    return_type_tag = g_type_info_get_tag (return_type_info);
+    g_callable_info_load_return_type (callable_info, &return_type_info);
+    return_type_tag = g_type_info_get_tag (&return_type_info);
     if (return_type_tag != GI_TYPE_TAG_VOID) {
         GITransfer transfer = g_callable_info_get_caller_owns (callable_info);
         if (PyTuple_Check (py_retval)) {
             PyObject *item = PyTuple_GET_ITEM (py_retval, 0);
             _pygi_closure_assign_pyobj_to_retval (resp, item,
-                return_type_info, transfer);
+                &return_type_info, transfer);
         } else {
             _pygi_closure_assign_pyobj_to_retval (resp, py_retval,
-                return_type_info, transfer);
+                &return_type_info, transfer);
         }
         i_py_retval++;
     }
-    g_base_info_unref (return_type_info);
 
     i_out_args = 0;
     n_args = g_callable_info_get_n_args (callable_info);
-    for (i = 1; i < n_args; i++) {
-        GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i);
-        GITypeInfo *type_info = g_arg_info_get_type (arg_info);
-        GIDirection direction = g_arg_info_get_direction (arg_info);
+    for (i = 0; i < n_args; i++) {
+        GIArgInfo arg_info;
+        GITypeInfo type_info;
+        GIDirection direction;
+        g_callable_info_load_arg (callable_info, i, &arg_info);
+        g_arg_info_load_type (&arg_info, &type_info);
+        direction = g_arg_info_get_direction (&arg_info);
 
         if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
-            GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info);
+            GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info);
 
-            if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ERROR) {
+            if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ERROR) {
                 /* TODO: check if an exception has been set and convert it to a GError */
                 out_args[i_out_args].v_pointer = NULL;
                 i_out_args++;
@@ -439,10 +485,10 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
             if (PyTuple_Check (py_retval)) {
                 PyObject *item = PyTuple_GET_ITEM (py_retval, i_py_retval);
                 _pygi_closure_assign_pyobj_to_out_argument (
-                    out_args[i_out_args].v_pointer, item, type_info, transfer);
+                    out_args[i_out_args].v_pointer, item, &type_info, transfer);
             } else if (i_py_retval == 0) {
                 _pygi_closure_assign_pyobj_to_out_argument (
-                    out_args[i_out_args].v_pointer, py_retval, type_info,
+                    out_args[i_out_args].v_pointer, py_retval, &type_info,
                     transfer);
             } else
                 g_assert_not_reached();
@@ -450,8 +496,6 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info,
             i_out_args++;
             i_py_retval++;
         }
-        g_base_info_unref (type_info);
-        g_base_info_unref (arg_info);
     }
 }
 
@@ -511,8 +555,6 @@ _pygi_closure_handle (ffi_cif *cif,
 end:
     g_free (out_args);
 
-    PyGILState_Release (state);
-
     /* Now that the closure has finished we can make a decision about how
        to free it.  Scope call gets free'd at the end of wrap_g_function_info_invoke.
        Scope notified will be freed when the notify is called.
@@ -535,6 +577,8 @@ end:
             g_error ("Invalid scope reached inside %s.  Possibly a bad annotation?",
                      g_base_info_get_name (closure->info));
     }
+
+    PyGILState_Release (state);
 }
 
 void _pygi_invoke_closure_free (gpointer data)
index ef5abaa..7537399 100644 (file)
@@ -42,7 +42,7 @@ typedef struct {
 static GPtrArray *foreign_structs = NULL;
 
 static void
-init_foreign_structs ()
+init_foreign_structs (void)
 {
     foreign_structs = g_ptr_array_new ();
 }
index e726b2d..362e7cd 100644 (file)
@@ -88,8 +88,6 @@ _base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op)
     return res;
 }
 
-static PyMethodDef _PyGIBaseInfo_methods[];
-
 PYGLIB_DEFINE_TYPE("gi.BaseInfo", PyGIBaseInfo_Type, PyGIBaseInfo);
 
 static PyObject *
@@ -406,11 +404,14 @@ _g_arg_get_pytype_hint (PyGIBaseInfo *self)
 {
     GIArgInfo *arg_info = (GIArgInfo*)self->info;
     GITypeInfo type_info;
+    GITypeTag type_tag;
+    PyObject *py_type;
+
     g_arg_info_load_type(arg_info, &type_info);
-    GITypeTag type_tag = g_type_info_get_tag(&type_info);
+    type_tag = g_type_info_get_tag(&type_info);
 
     /* First attempt getting a python type object. */
-    PyObject *py_type = _pygi_get_py_type_hint(type_tag);
+    py_type = _pygi_get_py_type_hint(type_tag);
     if (py_type != Py_None && PyObject_HasAttrString(py_type, "__name__")) {
        PyObject *name = PyObject_GetAttrString(py_type, "__name__");
        Py_DecRef(py_type);
@@ -422,8 +423,9 @@ _g_arg_get_pytype_hint (PyGIBaseInfo *self)
            gchar *name = g_strdup_printf("%s.%s",
                    g_base_info_get_namespace(iface),
                    g_base_info_get_name (iface));
+        PyObject *py_string;
            g_base_info_unref(iface);
-           PyObject *py_string = PYGLIB_PyUnicode_FromString(name);
+           py_string = PYGLIB_PyUnicode_FromString(name);
            g_free(name);
            return py_string;
        }
@@ -908,11 +910,11 @@ pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
     for (i = 0; i < n_field_infos && is_simple; i++) {
         GIFieldInfo *field_info;
         GITypeInfo *field_type_info;
+        GITypeTag field_type_tag;
 
         field_info = g_struct_info_get_field (struct_info, i);
         field_type_info = g_field_info_get_type (field_info);
 
-        GITypeTag field_type_tag;
 
         field_type_tag = g_type_info_get_tag (field_type_info);
 
@@ -1243,7 +1245,7 @@ _wrap_g_constant_info_get_value (PyGIBaseInfo *self)
     type_info = g_constant_info_get_type ( (GIConstantInfo *) self->info);
 
     if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ARRAY) {
-        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
+        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL, NULL,
                                                    type_info, &free_array);
     }
 
@@ -1376,7 +1378,7 @@ _wrap_g_field_info_get_value (PyGIBaseInfo *self,
     }
 
     if (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_ARRAY) {
-        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL,
+        value.v_pointer = _pygi_argument_to_array (&value, NULL, NULL, NULL,
                                                    field_type_info, &free_array);
     }
 
@@ -1510,14 +1512,15 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self,
 
         g_base_info_unref (info);
     } else if (g_type_info_is_pointer (field_type_info)
-            && g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID) {
-
+            && (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID
+                || g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_UTF8)) {
+        int offset;
         value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING);
         if (PyErr_Occurred()) {
             goto out;
         }
 
-        int offset = g_field_info_get_offset ((GIFieldInfo *) self->info);
+        offset = g_field_info_get_offset ((GIFieldInfo *) self->info);
         G_STRUCT_MEMBER (gpointer, pointer, offset) = (gpointer)value.v_pointer;
 
         retval = Py_None;
index 195a830..0cbb9ca 100644 (file)
@@ -366,7 +366,7 @@ static gboolean _caller_alloc (PyGIInvokeState *state,
 
         state->out_args[out_count].v_pointer = NULL;
         state->args[arg_count] = &state->out_args[out_count];
-        if (iface_cache->g_type == G_TYPE_BOXED) {
+        if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
             state->args[arg_count]->v_pointer =
                 _pygi_boxed_alloc (iface_cache->interface_info, NULL);
         } else if (iface_cache->g_type == G_TYPE_VALUE) {
@@ -501,6 +501,7 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
 
         c_arg = state->args[i];
         if (arg_cache->from_py_marshaller != NULL) {
+            gboolean success;
             if (!arg_cache->allow_none && py_arg == Py_None) {
                 PyErr_Format (PyExc_TypeError,
                               "Argument %zd does not allow None as a value",
@@ -511,7 +512,7 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
                                                                    i - 1);
                  return FALSE;
             }
-            gboolean success = arg_cache->from_py_marshaller (state,
+            success = arg_cache->from_py_marshaller (state,
                                                               cache,
                                                               arg_cache,
                                                               py_arg,
index 0246f31..d7d1b63 100644 (file)
 static inline void
 _cleanup_caller_allocates (PyGIInvokeState    *state,
                            PyGIArgCache       *cache,
-                           gpointer            data)
+                           gpointer            data,
+                           gboolean            was_processed)
 {
     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)cache;
 
-    if (iface_cache->g_type == G_TYPE_BOXED) {
+    if (g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
         gsize size;
+        if (was_processed)
+            return; /* will be cleaned up at deallocation */
         size = g_struct_info_get_size (iface_cache->interface_info);
         g_slice_free1 (size, data);
     } else if (iface_cache->g_type == G_TYPE_VALUE) {
+        if (was_processed)
+            g_value_unset (data);
         g_slice_free (GValue, data);
     } else if (iface_cache->is_foreign) {
+        if (was_processed)
+            return; /* will be cleaned up at deallocation */
         pygi_struct_foreign_release ((GIBaseInfo *)iface_cache->interface_info,
                                      data);
     } else {
+        if (was_processed)
+            return; /* will be cleaned up at deallocation */
         g_free (data);
     }
 }
@@ -92,6 +101,12 @@ pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState   *state,
                 arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON &&
                     state->args[i]->v_pointer != NULL)
             cleanup_func (state, arg_cache, state->args[i]->v_pointer, TRUE);
+
+        if (cleanup_func &&
+                arg_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL &&
+                    state->args_data[i] != NULL) {
+            cleanup_func (state, arg_cache, state->args_data[i], TRUE);
+        }
     }
 }
 
@@ -99,6 +114,7 @@ void
 pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState   *state,
                                                  PyGICallableCache *cache)
 {
+    GSList *cache_item;
     /* clean up the return if available */
     if (cache->return_cache != NULL) {
         PyGIMarshalCleanupFunc cleanup_func = cache->return_cache->to_py_cleanup;
@@ -110,7 +126,7 @@ pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState   *state,
     }
 
     /* Now clean up args */
-    GSList *cache_item = cache->to_py_args;
+    cache_item = cache->to_py_args;
     while (cache_item) {
         PyGIArgCache *arg_cache = (PyGIArgCache *) cache_item->data;
         PyGIMarshalCleanupFunc cleanup_func = arg_cache->to_py_cleanup;
@@ -121,6 +137,12 @@ pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState   *state,
                           arg_cache,
                           data,
                           TRUE);
+        else if (arg_cache->is_caller_allocates && data != NULL) {
+            _cleanup_caller_allocates (state,
+                                       arg_cache,
+                                       data,
+                                       TRUE);
+        }
 
         cache_item = cache_item->next;
     }
@@ -151,7 +173,8 @@ pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState   *state,
         } else if (arg_cache->is_caller_allocates && data != NULL) {
             _cleanup_caller_allocates (state,
                                        arg_cache,
-                                       data);
+                                       data,
+                                       FALSE);
         }
     }
 }
@@ -351,8 +374,17 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
                 else if (sequence_cache->item_cache->is_pointer)
                     item = g_array_index (array_, gpointer, i);
                 /* case 3: C array or GArray with simple types or structs */
-                else
+                else {
                     item = array_->data + i * sequence_cache->item_size;
+                    /* special-case hack: GValue array items do not get slice
+                     * allocated in _pygi_marshal_from_py_array(), so we must
+                     * not try to deallocate it as a slice and thus
+                     * short-circuit cleanup_func. */
+                    if (cleanup_func == _pygi_marshal_cleanup_from_py_interface_struct_gvalue) {
+                        g_value_unset ((GValue*) item);
+                        continue;
+                    }
+                }
 
                 cleanup_func (state, sequence_cache->item_cache, item, TRUE);
             }
index dc14ca5..1111545 100644 (file)
 #include "pygi-marshal-cleanup.h"
 #include "pygi-marshal-from-py.h"
 
-gboolean
+#ifdef _WIN32
+#ifdef _MSC_VER
+#include <math.h>
+
+#ifndef NAN
+static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
+#define NAN (*(const float *) __nan)
+#endif
+
+#ifndef INFINITY
+#define INFINITY HUGE_VAL
+#endif
+
+#endif
+#endif
+
+static gboolean
 gi_argument_from_py_ssize_t (GIArgument   *arg_out,
                              Py_ssize_t    size_in,
                              GITypeTag     type_tag)                             
@@ -134,7 +150,7 @@ gi_argument_from_py_ssize_t (GIArgument   *arg_out,
     return FALSE;
 }
 
-gboolean
+static gboolean
 gi_argument_from_c_long (GIArgument *arg_out,
                          long        c_long_in,
                          GITypeTag   type_tag)
@@ -235,7 +251,11 @@ _pygi_marshal_from_py_void (PyGIInvokeState   *state,
 {
     g_warn_if_fail (arg_cache->transfer == GI_TRANSFER_NOTHING);
 
-    arg->v_pointer = py_arg;
+    if (PYGLIB_CPointer_Check(py_arg)) {
+        arg->v_pointer = PYGLIB_CPointer_GetPointer (py_arg, NULL);
+    } else {
+        arg->v_pointer = py_arg;
+    }
 
     return TRUE;
 }
@@ -262,22 +282,30 @@ _pygi_marshal_from_py_int8 (PyGIInvokeState   *state,
     PyObject *py_long;
     long long_;
 
-    if (!PyNumber_Check (py_arg)) {
-        PyErr_Format (PyExc_TypeError, "Must be number, not %s",
-                      py_arg->ob_type->tp_name);
-        return FALSE;
-    }
+    if (PYGLIB_PyBytes_Check (py_arg)) {
 
-    py_long = PYGLIB_PyNumber_Long (py_arg);
-    if (!py_long)
-        return FALSE;
+        if (PYGLIB_PyBytes_Size (py_arg) != 1) {
+            PyErr_Format (PyExc_TypeError, "Must be a single character");
+            return FALSE;
+        }
 
-    long_ = PYGLIB_PyLong_AsLong (py_long);
-    Py_DECREF (py_long);
+        long_ = (char)(PYGLIB_PyBytes_AsString (py_arg)[0]);
+    } else if (PyNumber_Check (py_arg)) {
+        py_long = PYGLIB_PyNumber_Long (py_arg);
+        if (!py_long)
+            return FALSE;
 
-    if (PyErr_Occurred ()) {
-        PyErr_Clear ();
-        PyErr_Format (PyExc_ValueError, "%ld not in range %d to %d", long_, -128, 127);
+        long_ = PYGLIB_PyLong_AsLong (py_long);
+        Py_DECREF (py_long);
+
+        if (PyErr_Occurred ()) {
+            PyErr_Clear ();
+            PyErr_Format (PyExc_ValueError, "%ld not in range %d to %d", long_, -128, 127);
+            return FALSE;
+        }
+    } else {
+        PyErr_Format (PyExc_TypeError, "Must be number or single byte string, not %s",
+                      py_arg->ob_type->tp_name);
         return FALSE;
     }
 
@@ -651,6 +679,23 @@ _pygi_marshal_from_py_uint64 (PyGIInvokeState   *state,
     return TRUE;
 }
 
+static gboolean
+check_valid_double (double x, double min, double max)
+{
+    char buf[100];
+
+    if ((x < min || x > max) && x != INFINITY && x != -INFINITY && x != NAN) {
+        if (PyErr_Occurred())
+            PyErr_Clear ();
+
+        /* we need this as PyErr_Format() does not support float types */
+        snprintf (buf, sizeof (buf), "%g not in range %g to %g", x, min, max);
+        PyErr_SetString (PyExc_ValueError, buf);
+        return FALSE;
+    }
+    return TRUE;
+}
+
 gboolean
 _pygi_marshal_from_py_float (PyGIInvokeState   *state,
                              PyGICallableCache *callable_cache,
@@ -674,16 +719,8 @@ _pygi_marshal_from_py_float (PyGIInvokeState   *state,
     double_ = PyFloat_AsDouble (py_float);
     Py_DECREF (py_float);
 
-    if (PyErr_Occurred ()) {
-        PyErr_Clear ();
-        PyErr_Format (PyExc_ValueError, "%f not in range %f to %f", double_, -G_MAXFLOAT, G_MAXFLOAT);
-        return FALSE;
-    }
-
-    if (double_ < -G_MAXFLOAT || double_ > G_MAXFLOAT) {
-        PyErr_Format (PyExc_ValueError, "%f not in range %f to %f", double_, -G_MAXFLOAT, G_MAXFLOAT);
+    if (PyErr_Occurred () || !check_valid_double (double_, -G_MAXFLOAT, G_MAXFLOAT))
         return FALSE;
-    }
 
     arg->v_float = double_;
 
@@ -713,16 +750,8 @@ _pygi_marshal_from_py_double (PyGIInvokeState   *state,
     double_ = PyFloat_AsDouble (py_float);
     Py_DECREF (py_float);
 
-    if (PyErr_Occurred ()) {
-        PyErr_Clear ();
-        PyErr_Format (PyExc_ValueError, "%f not in range %f to %f", double_, -G_MAXDOUBLE, G_MAXDOUBLE);
-        return FALSE;
-    }
-
-    if (double_ < -G_MAXDOUBLE || double_ > G_MAXDOUBLE) {
-        PyErr_Format (PyExc_ValueError, "%f not in range %f to %f", double_, -G_MAXDOUBLE, G_MAXDOUBLE);
+    if (PyErr_Occurred () || !check_valid_double (double_, -G_MAXDOUBLE, G_MAXDOUBLE))
         return FALSE;
-    }
 
     arg->v_double = double_;
 
@@ -880,7 +909,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
                              GIArgument        *arg)
 {
     PyGIMarshalFromPyFunc from_py_marshaller;
-    int i;
+    int i = 0;
     Py_ssize_t length;
     gssize item_size;
     gboolean is_ptr_array;
@@ -986,14 +1015,10 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
                             g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
                             g_value_copy ((GValue*) item.v_pointer, dest);
                         }
-
-                        if (from_py_cleanup) {
+                        /* we free the original copy already, the new one is a plain struct
+                         * in an array. _pygi_marshal_cleanup_from_py_array() does not free it again */
+                        if (from_py_cleanup)
                             from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE);
-                            /* we freed the original copy already, the new one is a 
-                             * struct in an array. _pygi_marshal_cleanup_from_py_array()
-                             * must not free it again */
-                            item_arg_cache->from_py_cleanup = NULL;
-                        }
                     } else if (!is_boxed) {
                         /* HACK: Gdk.Atom is merely an integer wrapped in a pointer,
                          * so we must not dereference it; just copy the pointer
@@ -1009,6 +1034,12 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
                             if (from_py_cleanup)
                                 from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE);
                         }
+                    } else if (is_boxed && !item_iface_cache->arg_cache.is_pointer) {
+                        /* The array elements are not expected to be pointers, but the
+                         * elements obtained are boxed pointers themselves, so insert
+                         * the pointed to data.
+                         */
+                        g_array_insert_vals (array_, i, item.v_pointer, 1);
                     } else {
                         g_array_insert_val (array_, i, item);
                     }
@@ -1073,6 +1104,10 @@ array_success:
     if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
         arg->v_pointer = array_->data;
         g_array_free (array_, FALSE);
+        /* remember the originally allocated array in args_data, as args and
+         * in_args get changed for (inout) arguments */
+        if (arg_cache->transfer == GI_TRANSFER_NOTHING)
+            state->args_data[arg_cache->c_arg_index] = arg->v_pointer;
     } else {
         arg->v_pointer = array_;
     }
@@ -1369,10 +1404,11 @@ _pygi_destroy_notify_create (void)
     if (!global_destroy_notify) {
 
         PyGICClosure *destroy_notify = g_slice_new0 (PyGICClosure);
+        GIBaseInfo* glib_destroy_notify;
 
         g_assert (destroy_notify);
 
-        GIBaseInfo* glib_destroy_notify = g_irepository_find_by_name (NULL, "GLib", "DestroyNotify");
+        glib_destroy_notify = g_irepository_find_by_name (NULL, "GLib", "DestroyNotify");
         g_assert (glib_destroy_notify != NULL);
         g_assert (g_base_info_get_type (glib_destroy_notify) == GI_INFO_TYPE_CALLBACK);
 
@@ -1610,53 +1646,11 @@ _pygi_marshal_from_py_interface_struct (PyGIInvokeState   *state,
      */
 
     if (iface_cache->g_type == G_TYPE_CLOSURE) {
-        GClosure *closure;
-        GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE);
-
-        if ( !(PyCallable_Check(py_arg) || 
-               g_type_is_a (object_gtype, G_TYPE_CLOSURE))) {
-            PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
-                          py_arg->ob_type->tp_name);
-            return FALSE;
-        }
-
-        if (g_type_is_a (object_gtype, G_TYPE_CLOSURE))
-            closure = (GClosure *)pyg_boxed_get (py_arg, void);
-        else
-            closure = pyg_closure_new (py_arg, NULL, NULL);
-
-        if (closure == NULL) {
-            PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
-            return FALSE;
-        }
-
-        arg->v_pointer = closure;
-        return TRUE;
+        return pygi_marshal_from_py_gclosure (py_arg, arg);
     } else if (iface_cache->g_type == G_TYPE_VALUE) {
-        GValue *value;
-        GType object_type;
-
-        object_type = pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
-        if (object_type == G_TYPE_INVALID) {
-            PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
-            return FALSE;
-        }
-
-        /* if already a gvalue, use that, else marshal into gvalue */
-        if (object_type == G_TYPE_VALUE) {
-            value = (GValue *)( (PyGObject *)py_arg)->obj;
-        } else {
-            value = g_slice_new0 (GValue);
-            g_value_init (value, object_type);
-            if (pyg_value_from_pyobject (value, py_arg) < 0) {
-                g_slice_free (GValue, value);
-                PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
-                return FALSE;
-            }
-        }
-
-        arg->v_pointer = value;
-        return TRUE;
+        return pygi_marshal_from_py_gvalue(py_arg, arg,
+                                           arg_cache->transfer,
+                                           arg_cache->is_caller_allocates);
     } else if (iface_cache->is_foreign) {
         PyObject *success;
         success = pygi_struct_foreign_convert_to_g_argument (py_arg,
@@ -1741,11 +1735,7 @@ _pygi_marshal_from_py_interface_object (PyGIInvokeState   *state,
         return FALSE;
     }
 
-    arg->v_pointer = pygobject_get(py_arg);
-    if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
-        g_object_ref (arg->v_pointer);
-
-    return TRUE;
+    return pygi_marshal_from_py_gobject (py_arg, arg, arg_cache->transfer);
 }
 
 gboolean
@@ -1836,3 +1826,149 @@ gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState   *state,
 
    return TRUE;
 }
+
+/* pygi_marshal_from_py_gobject:
+ * py_arg: (in):
+ * arg: (out):
+ */
+gboolean
+pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
+                              GIArgument *arg,  /*out*/
+                              GITransfer transfer) {
+    GObject *gobj;
+
+    if (py_arg == Py_None) {
+        arg->v_pointer = NULL;
+        return TRUE;
+    }
+
+    if (!pygobject_check (py_arg, &PyGObject_Type)) {
+        PyObject *repr = PyObject_Repr (py_arg);
+        PyErr_Format(PyExc_TypeError, "expected GObject but got %s",
+                     PYGLIB_PyUnicode_AsString (repr));
+        Py_DECREF (repr);
+        return FALSE;
+    }
+
+    gobj = pygobject_get (py_arg);
+    if (transfer == GI_TRANSFER_EVERYTHING) {
+        /* An easy case of adding a new ref that the caller will take ownership of.
+         * Pythons existing ref to the GObject will be managed normally with the wrapper.
+         */
+        g_object_ref (gobj);
+
+    } else if (py_arg->ob_refcnt == 1 && gobj->ref_count == 1) {
+        /* If both object ref counts are only 1 at this point (the reference held
+         * in a return tuple), we assume the GObject will be free'd before reaching
+         * its target and become invalid. So instead of getting invalid object errors
+         * we add a new GObject ref.
+         */
+        g_object_ref (gobj);
+
+        if (((PyGObject *)py_arg)->private_flags.flags & PYGOBJECT_GOBJECT_WAS_FLOATING) {
+            /* HACK:
+             * We want to re-float instances that were floating and the Python
+             * wrapper assumed ownership. With the additional caveat that there
+             * are not any strong references beyond the return tuple.
+             * This should be removed once the following ticket is fixed:
+             * https://bugzilla.gnome.org/show_bug.cgi?id=693393
+             */
+            g_object_force_floating (gobj);
+
+        } else {
+            PyObject *repr = PyObject_Repr (py_arg);
+            gchar *msg = g_strdup_printf ("Expecting to marshal a borrowed reference for %s, "
+                                          "but nothing in Python is holding a reference to this object. "
+                                          "See: https://bugzilla.gnome.org/show_bug.cgi?id=687522",
+                                          PYGLIB_PyUnicode_AsString(repr));
+            Py_DECREF (repr);
+            if (PyErr_WarnEx (PyExc_RuntimeWarning, msg, 2)) {
+                g_free (msg);
+                return FALSE;
+            }
+            g_free (msg);
+        }
+    }
+
+    arg->v_pointer = gobj;
+    return TRUE;
+}
+
+/* pygi_marshal_from_py_gvalue:
+ * py_arg: (in):
+ * arg: (out):
+ * transfer:
+ * is_allocated: TRUE if arg->v_pointer is an already allocated GValue
+ */
+gboolean
+pygi_marshal_from_py_gvalue (PyObject *py_arg,
+                             GIArgument *arg,
+                             GITransfer transfer,
+                             gboolean is_allocated) {
+    GValue *value;
+    GType object_type;
+
+    object_type = pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
+    if (object_type == G_TYPE_INVALID) {
+        PyErr_SetString (PyExc_RuntimeError, "unable to retrieve object's GType");
+        return FALSE;
+    }
+
+    if (is_allocated)
+        value = (GValue *)arg->v_pointer;
+    else
+        value = g_slice_new0 (GValue);
+
+    /* if already a gvalue, use that, else marshal into gvalue */
+    if (object_type == G_TYPE_VALUE) {
+        GValue *source_value = pyg_boxed_get (py_arg, GValue);
+        if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
+            g_value_init (value, G_VALUE_TYPE (source_value));
+        g_value_copy (source_value, value);
+    } else {
+        if (G_VALUE_TYPE (value) == G_TYPE_INVALID)
+            g_value_init (value, object_type);
+
+        if (pyg_value_from_pyobject (value, py_arg) < 0) {
+            if (!is_allocated)
+                g_slice_free (GValue, value);
+            PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GValue failed");
+            return FALSE;
+        }
+    }
+
+    arg->v_pointer = value;
+    return TRUE;
+}
+
+/* pygi_marshal_from_py_gclosure:
+ * py_arg: (in):
+ * arg: (out):
+ */
+gboolean
+pygi_marshal_from_py_gclosure(PyObject *py_arg,
+                              GIArgument *arg)
+{
+    GClosure *closure;
+    GType object_gtype = pyg_type_from_object_strict (py_arg, FALSE);
+
+    if ( !(PyCallable_Check(py_arg) ||
+           g_type_is_a (object_gtype, G_TYPE_CLOSURE))) {
+        PyErr_Format (PyExc_TypeError, "Must be callable, not %s",
+                      py_arg->ob_type->tp_name);
+        return FALSE;
+    }
+
+    if (g_type_is_a (object_gtype, G_TYPE_CLOSURE))
+        closure = (GClosure *)pyg_boxed_get (py_arg, void);
+    else
+        closure = pyg_closure_new (py_arg, NULL, NULL);
+
+    if (closure == NULL) {
+        PyErr_SetString (PyExc_RuntimeError, "PyObject conversion to GClosure failed");
+        return FALSE;
+    }
+
+    arg->v_pointer = closure;
+    return TRUE;
+}
index b82f890..e0a57d3 100644 (file)
@@ -184,6 +184,20 @@ gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState   *state,
                                                    PyObject          *py_arg,
                                                    GIArgument        *arg);
 
+/* Simplified marshalers shared between vfunc/closure and direct function calls. */
+
+gboolean pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
+                                       GIArgument *arg,  /*out*/
+                                       GITransfer transfer);
+
+gboolean pygi_marshal_from_py_gvalue (PyObject *py_arg, /*in*/
+                                      GIArgument *arg,  /*out*/
+                                      GITransfer transfer,
+                                      gboolean is_allocated);
+
+gboolean pygi_marshal_from_py_gclosure(PyObject *py_arg, /*in*/
+                                       GIArgument *arg); /*out*/
+
 G_END_DECLS
 
 #endif /* __PYGI_MARSHAL_from_py_PY__ */
index 950895d..6dde41d 100644 (file)
@@ -34,7 +34,7 @@
 #include "pygi-marshal-cleanup.h"
 #include "pygi-marshal-to-py.h"
 
-gboolean
+static gboolean
 gi_argument_to_c_long (GIArgument *arg_in,
                        long *c_long_out,
                        GITypeTag type_tag)
@@ -72,7 +72,7 @@ gi_argument_to_c_long (GIArgument *arg_in,
     }
 }
 
-gboolean
+static gboolean
 gi_argument_to_gsize (GIArgument *arg_in,
                       gsize      *gsize_out,
                       GITypeTag   type_tag)
@@ -434,13 +434,15 @@ _pygi_marshal_to_py_array (PyGIInvokeState   *state,
                                 item_arg.v_pointer = g_variant_ref_sink (g_array_index (array_, gpointer, i));
                               else
                                 item_arg.v_pointer = g_array_index (array_, gpointer, i);
-                            } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
+                            } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && !item_arg_cache->is_pointer &&
+                                       !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
+                                /* array elements are structs */
                                 gpointer *_struct = g_malloc (item_size);
                                 memcpy (_struct, array_->data + i * item_size,
                                         item_size);
                                 item_arg.v_pointer = _struct;
                             } else if (item_arg_cache->is_pointer)
-                                /* this is the case for GAtom* arrays */
+                                /* array elements are pointers to values */
                                 item_arg.v_pointer = g_array_index (array_, gpointer, i);
                             else
                                 item_arg.v_pointer = array_->data + i * item_size;
@@ -813,8 +815,10 @@ _pygi_marshal_to_py_interface_struct (PyGIInvokeState   *state,
         py_obj = pygi_struct_foreign_convert_from_g_argument (iface_cache->interface_info,
                                                               arg->v_pointer);
     } else if (g_type_is_a (type, G_TYPE_BOXED)) {
-        py_obj = _pygi_boxed_new ( (PyTypeObject *)iface_cache->py_type, arg->v_pointer, 
-                                  arg_cache->transfer == GI_TRANSFER_EVERYTHING);
+        py_obj = _pygi_boxed_new ( (PyTypeObject *)iface_cache->py_type, arg->v_pointer,
+                                  arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->is_caller_allocates,
+                                  arg_cache->is_caller_allocates ?
+                                          g_struct_info_get_size(iface_cache->interface_info) : 0);
     } else if (g_type_is_a (type, G_TYPE_POINTER)) {
         if (iface_cache->py_type == NULL ||
                 !PyType_IsSubtype ( (PyTypeObject *)iface_cache->py_type, &PyGIStruct_Type)) {
@@ -874,28 +878,7 @@ _pygi_marshal_to_py_interface_object (PyGIInvokeState   *state,
                                       PyGIArgCache      *arg_cache,
                                       GIArgument        *arg)
 {
-    PyObject *py_obj;
-
-    if (arg->v_pointer == NULL) {
-        py_obj = Py_None;
-        Py_INCREF (py_obj);
-        return py_obj;
-    }
-
-    if (G_IS_PARAM_SPEC(arg->v_pointer))
-    {
-       py_obj = pyg_param_spec_new (arg->v_pointer);
-       if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
-                       g_param_spec_unref (arg->v_pointer);
-    }
-    else
-    {
-       py_obj = pygobject_new (arg->v_pointer);
-       if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
-               g_object_unref (arg->v_pointer);
-    }
-
-    return py_obj;
+    return pygi_marshal_to_py_object(arg, arg_cache->transfer);
 }
 
 PyObject *
@@ -910,3 +893,25 @@ _pygi_marshal_to_py_interface_union  (PyGIInvokeState   *state,
                   "Marshalling for this type is not implemented yet");
     return py_obj;
 }
+
+PyObject *
+pygi_marshal_to_py_object (GIArgument *arg, GITransfer transfer) {
+    PyObject *pyobj;
+
+    if (arg->v_pointer == NULL) {
+        pyobj = Py_None;
+        Py_INCREF (pyobj);
+
+    } else if (G_IS_PARAM_SPEC(arg->v_pointer)) {
+        pyobj = pyg_param_spec_new (arg->v_pointer);
+        if (transfer == GI_TRANSFER_EVERYTHING)
+            g_param_spec_unref (arg->v_pointer);
+
+    } else {
+         pyobj = pygobject_new_full (arg->v_pointer,
+                                     /*steal=*/ transfer == GI_TRANSFER_EVERYTHING,
+                                     /*type=*/  NULL);
+    }
+
+    return pyobj;
+}
index a07a13e..f2e1a5c 100644 (file)
@@ -139,6 +139,11 @@ PyObject *_pygi_marshal_to_py_interface_union  (PyGIInvokeState   *state,
                                                 PyGIArgCache      *arg_cache,
                                                 GIArgument        *arg);
 
+/* Simplified marshalers shared between vfunc/closure and direct function calls. */
+
+PyObject *pygi_marshal_to_py_object (GIArgument *arg,
+                                     GITransfer transfer);
+
 G_END_DECLS
 
 #endif /* __PYGI_MARSHAL_TO_PY_H__ */
index 1f59fdf..97eced5 100644 (file)
@@ -51,6 +51,7 @@ G_BEGIN_DECLS
             } \
         } \
         PyErr_Restore(py_error_type, py_error_value, py_error_traceback); \
+        Py_DECREF(py_error_prefix); \
     } \
 } G_STMT_END
 
index 6079efc..ae49f08 100644 (file)
@@ -95,6 +95,15 @@ _pygi_lookup_property_from_g_type (GType g_type, const gchar *attr_name)
     return ret;
 }
 
+static inline gpointer
+g_value_get_or_dup_boxed (const GValue *value, GITransfer transfer)
+{
+    if (transfer == GI_TRANSFER_EVERYTHING)
+        return g_value_dup_boxed (value);
+    else
+        return g_value_get_boxed (value);
+}
+
 PyObject *
 pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
 {
@@ -104,6 +113,7 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
     PyObject *py_value = NULL;
     GITypeInfo *type_info = NULL;
     GITransfer transfer;
+    GITypeTag type_tag;
 
     /* The owner_type of the pspec gives us the exact type that introduced the
      * property, even if it is a parent class of the instance in question. */
@@ -118,7 +128,7 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
     type_info = g_property_info_get_type (property_info);
     transfer = g_property_info_get_ownership_transfer (property_info);
 
-    GITypeTag type_tag = g_type_info_get_tag (type_info);
+    type_tag = g_type_info_get_tag (type_info);
     switch (type_tag) {
         case GI_TYPE_TAG_BOOLEAN:
             arg.v_boolean = g_value_get_boolean (&value);
@@ -193,7 +203,7 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
                 case GI_INFO_TYPE_UNION:
 
                     if (g_type_is_a (type, G_TYPE_BOXED)) {
-                        arg.v_pointer = g_value_get_boxed (&value);
+                        arg.v_pointer = g_value_dup_boxed (&value);
                     } else if (g_type_is_a (type, G_TYPE_POINTER)) {
                         arg.v_pointer = g_value_get_pointer (&value);
                     } else if (g_type_is_a (type, G_TYPE_VARIANT)) {
@@ -213,11 +223,14 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
             break;
         }
         case GI_TYPE_TAG_GHASH:
-            arg.v_pointer = g_value_get_boxed (&value);
+            arg.v_pointer = g_value_get_or_dup_boxed (&value, transfer);
             break;
         case GI_TYPE_TAG_GLIST:
         case GI_TYPE_TAG_GSLIST:
-            arg.v_pointer = g_value_get_pointer (&value);
+            if (G_VALUE_HOLDS_BOXED(&value))
+                arg.v_pointer = g_value_get_or_dup_boxed (&value, transfer);
+            else
+                arg.v_pointer = g_value_get_pointer (&value);
             break;
         case GI_TYPE_TAG_ARRAY:
         {
@@ -225,7 +238,7 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
             GArray *arg_items;
             int i;
 
-            strings = g_value_get_boxed (&value);
+            strings = g_value_get_or_dup_boxed (&value, transfer);
             if (strings == NULL)
                 arg.v_pointer = NULL;
             else {
@@ -246,6 +259,7 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec)
     }
 
     py_value = _pygi_argument_to_object (&arg, type_info, transfer);
+    g_value_unset (&value);
 
 out:
     if (property_info != NULL)
@@ -384,7 +398,10 @@ pygi_set_property_value_real (PyGObject *instance,
             g_value_set_boxed (&value, arg.v_pointer);
             break;
         case GI_TYPE_TAG_GLIST:
-            g_value_set_pointer (&value, arg.v_pointer);
+            if (G_VALUE_HOLDS_BOXED(&value))
+                g_value_set_boxed (&value, arg.v_pointer);
+            else
+                g_value_set_pointer (&value, arg.v_pointer);
             break;
         case GI_TYPE_TAG_ARRAY:
         {
@@ -403,7 +420,7 @@ pygi_set_property_value_real (PyGObject *instance,
                 strings[i] = g_array_index (arg_items, GIArgument, i).v_string;
             }
             strings[arg_items->len] = NULL;
-            g_value_set_boxed (&value, strings);
+            g_value_take_boxed (&value, strings);
             g_array_free (arg_items, TRUE);
             break;
         }
@@ -415,6 +432,7 @@ pygi_set_property_value_real (PyGObject *instance,
     }
 
     g_object_set_property (instance->obj, pspec->name, &value);
+    g_value_unset (&value);
 
     ret_value = 0;
 
index 7de293a..d54326d 100644 (file)
@@ -27,8 +27,6 @@
 
 PyObject *PyGIRepositoryError;
 
-static PyMethodDef _PyGIRepository_methods[];
-
 PYGLIB_DEFINE_TYPE("gi.Repository", PyGIRepository_Type, PyGIRepository);
 
 static PyObject *
index 36ea168..6e026de 100644 (file)
@@ -141,7 +141,8 @@ pygi_signal_closure_marshal(GClosure *closure,
             arg = _pygi_argument_from_g_value(&param_values[i], &type_info);
             
             if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ARRAY) {
-                arg.v_pointer = _pygi_argument_to_array (&arg, NULL, NULL,
+                /* Skip the self argument of param_values */
+                arg.v_pointer = _pygi_argument_to_array (&arg, NULL, param_values + 1, signal_info,
                                                          &type_info, &free_array);
             }
             
index 73772bd..66bbc3c 100644 (file)
@@ -232,7 +232,7 @@ pyg_source_set_callback(PyGObject *self_module, PyObject *args)
  * GSourceFuncs which call back to Python.
  */
 PyObject*
-pyg_source_new ()
+pyg_source_new (void)
 {
     PyGRealSource *source = NULL;
     PyObject      *py_type;
@@ -240,7 +240,8 @@ pyg_source_new ()
     source = (PyGRealSource*) g_source_new (&pyg_source_funcs, sizeof (PyGRealSource));
 
     py_type = _pygi_type_import_by_name ("GLib", "Source");
-    source->obj = _pygi_boxed_new ( (PyTypeObject *) py_type, source, FALSE);
+    /* g_source_new uses malloc, not slices */
+    source->obj = _pygi_boxed_new ( (PyTypeObject *) py_type, source, FALSE, 0);
 
     return source->obj;
 }
index 024cf15..a602767 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef __PYGI_SOURCE_H__
 #define __PYGI_SOURCE_H__
 
-PyObject *pyg_source_new ();
+PyObject *pyg_source_new (void);
 PyObject *pyg_source_set_callback (PyGObject *self, PyObject *args);
 
 #endif /* __PYGI_SOURCE_H__ */
index 4a1456d..8299864 100644 (file)
@@ -30,7 +30,7 @@ static PyTypeObject *_PyGTypeWrapper_Type;
 
 #define PyGTypeWrapper_Type (*_PyGTypeWrapper_Type)
 
-__attribute__ ( (unused))
+G_GNUC_UNUSED
 static int
 _pygobject_import (void)
 {
index 91b5cc1..4a9c4be 100644 (file)
@@ -1,8 +1,10 @@
+from __future__ import absolute_import
 import warnings
+
 from gi import PyGIDeprecationWarning
 
 warnings.warn('gi.pygtkcompat is being deprecated in favor of using "pygtkcompat" directly.',
-              PyGIDeprecationWarning, stacklevel=2)
+              PyGIDeprecationWarning)
 
 # pyflakes.ignore
 from pygtkcompat import (enable,
index ed0ae40..6f3c096 100644 (file)
@@ -216,6 +216,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
index f049da7..c44833d 100644 (file)
@@ -100,14 +100,14 @@ def wraps_callable_info(info):
     def update_func(func):
         func.__info__ = info
         func.__name__ = info.get_name()
-        func.__module__ = info.get_namespace()
+        func.__module__ = 'gi.repository.' + info.get_namespace()
         func.__doc__ = get_callable_info_doc_string(info)
         return func
     return update_func
 
 
 def Function(info):
-    """Warps GIFunctionInfo"""
+    """Wraps GIFunctionInfo"""
     @wraps_callable_info(info)
     def function(*args, **kwargs):
         return info.invoke(*args, **kwargs)
@@ -128,7 +128,7 @@ class NativeVFunc(object):
 
 
 def Constructor(info):
-    """Warps GIFunctionInfo with get_constructor() == True"""
+    """Wraps GIFunctionInfo with get_constructor() == True"""
     @wraps_callable_info(info)
     def constructor(cls, *args, **kwargs):
         cls_name = info.get_container().get_name()
diff --git a/pygobject.doap b/pygobject.doap
new file mode 100644 (file)
index 0000000..63214b7
--- /dev/null
@@ -0,0 +1,65 @@
+<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
+         xmlns:foaf="http://xmlns.com/foaf/0.1/"
+         xmlns:gnome="http://api.gnome.org/doap-extensions#"
+         xmlns="http://usefulinc.com/ns/doap#">
+
+  <name xml:lang="en">PyGObject</name>
+  <shortdesc xml:lang="en">Python bindings for GObject Introspection</shortdesc>
+  <description>
+GObject is a object system used by GTK+,  GStreamer and other libraries.
+
+PyGObject provides a convenient wrapper for use in Python programs when accessing GObject libraries.
+
+Like the GObject library itself PyGObject is licensed under the GNU LGPL, so is suitable for use in both free software and proprietary applications. It is already in use in many applications ranging from small single purpose scripts up to large full featured applications.
+
+PyGObject now dynamically accesses any GObject libraries that uses GObject Introspection. It replaces the need for separate modules such as PyGTK, GIO and python-gnome to build a full GNOME 3.0 application. Once new functionality is added to gobject library it is instantly available as a Python API without the need for intermediate Python glue.
+  </description>
+  <homepage rdf:resource="http://live.gnome.org/PyGObject" />
+  <mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/python-hackers-list" />
+  <category rdf:resource="http://api.gnome.org/doap-extensions#bindings" />
+  <download-page rdf:resource="http://download.gnome.org/sources/pygobject/" />
+  <bug-database rdf:resource="https://bugzilla.gnome.org/browse.cgi?product=pygobject" />
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Tomeu Vizoso</foaf:name>
+      <foaf:mbox rdf:resource="mailto:tomeu.vizoso@collabora.co.uk" />
+      <gnome:userid>tomeuv</gnome:userid>
+    </foaf:Person>
+  </maintainer>
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Martin Pitt</foaf:name>
+      <foaf:mbox rdf:resource="mailto:martinpitt@gnome.org" />
+      <gnome:userid>martinpitt</gnome:userid>
+    </foaf:Person>
+  </maintainer>
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Paolo Borelli</foaf:name>
+      <foaf:mbox rdf:resource="mailto:pborelli@gnome.org" />
+      <gnome:userid>pborelli</gnome:userid>
+    </foaf:Person>
+  </maintainer>
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Ignacio Casal Quinteiro</foaf:name>
+      <foaf:mbox rdf:resource="mailto:icq@gnome.org" />
+      <gnome:userid>icq</gnome:userid>
+    </foaf:Person>
+  </maintainer>
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Sebastian Pölsterl</foaf:name>
+      <foaf:mbox rdf:resource="mailto:sebp@k-d-w.org" />
+      <gnome:userid>sebp</gnome:userid>
+    </foaf:Person>
+  </maintainer>
+  <maintainer>
+    <foaf:Person>
+      <foaf:name>Simon Feltman</foaf:name>
+      <foaf:mbox rdf:resource="mailto:s.feltman@gmail.com" />
+      <gnome:userid>sfeltman</gnome:userid>
+    </foaf:Person>
+  </maintainer>
+</Project>
index 6a73cb4..914b3e2 100644 (file)
@@ -2,6 +2,7 @@ pygtkcompatdir = $(pyexecdir)/pygtkcompat
 
 pygtkcompat_PYTHON = \
        __init__.py \
+       generictreemodel.py \
        pygtkcompat.py
 
 # if we build in a separate tree, we need to symlink the *.py files from the
index cc97cc7..990e5e8 100644 (file)
@@ -216,6 +216,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -275,6 +276,7 @@ top_srcdir = @top_srcdir@
 pygtkcompatdir = $(pyexecdir)/pygtkcompat
 pygtkcompat_PYTHON = \
        __init__.py \
+       generictreemodel.py \
        pygtkcompat.py
 
 all: all-am
diff --git a/pygtkcompat/generictreemodel.py b/pygtkcompat/generictreemodel.py
new file mode 100644 (file)
index 0000000..b5e66b0
--- /dev/null
@@ -0,0 +1,420 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# generictreemodel - GenericTreeModel implementation for pygtk compatibility.
+# Copyright (C) 2013 Simon Feltman
+#
+#   generictreemodel.py: GenericTreeModel implementation for pygtk compatibility
+#
+# This library 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 2.1 of the License, or (at your option) any later version.
+#
+# This library 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 Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+# USA
+
+
+# System
+import sys
+import random
+import collections
+import ctypes
+
+# GObject
+from gi.repository import GObject
+from gi.repository import Gtk
+
+
+class _CTreeIter(ctypes.Structure):
+    _fields_ = [('stamp', ctypes.c_int),
+                ('user_data', ctypes.c_void_p),
+                ('user_data2', ctypes.c_void_p),
+                ('user_data3', ctypes.c_void_p)]
+
+    @classmethod
+    def from_iter(cls, iter):
+        offset = sys.getsizeof(object())  # size of PyObject_HEAD
+        return ctypes.POINTER(cls).from_address(id(iter) + offset)
+
+
+def _get_user_data_as_pyobject(iter):
+    citer = _CTreeIter.from_iter(iter)
+    return ctypes.cast(citer.contents.user_data, ctypes.py_object).value
+
+
+def handle_exception(default_return):
+    """Returns a function which can act as a decorator for wrapping exceptions and
+    returning "default_return" upon an exception being thrown.
+
+    This is used to wrap Gtk.TreeModel "do_" method implementations so we can return
+    a proper value from the override upon an exception occurring with client code
+    implemented by the "on_" methods.
+    """
+    def decorator(func):
+        def wrapped_func(*args, **kargs):
+            try:
+                return func(*args, **kargs)
+            except:
+                # Use excepthook directly to avoid any printing to the screen
+                # if someone installed an except hook.
+                sys.excepthook(*sys.exc_info())
+            return default_return
+        return wrapped_func
+    return decorator
+
+
+class GenericTreeModel(GObject.GObject, Gtk.TreeModel):
+    """A base implementation of a Gtk.TreeModel for python.
+
+    The GenericTreeModel eases implementing the Gtk.TreeModel interface in Python.
+    The class can be subclassed to provide a TreeModel implementation which works
+    directly with Python objects instead of iterators.
+
+    All of the on_* methods should be overridden by subclasses to provide the
+    underlying implementation a way to access custom model data. For the purposes of
+    this API, all custom model data supplied or handed back through the overridable
+    API will use the argument names: node, parent, and child in regards to user data
+    python objects.
+
+    The create_tree_iter, set_user_data, invalidate_iters, iter_is_valid methods are
+    available to help manage Gtk.TreeIter objects and their Python object references.
+
+    GenericTreeModel manages a pool of user data nodes that have been used with iters.
+    This pool stores a references to user data nodes as a dictionary value with the
+    key being the integer id of the data. This id is what the Gtk.TreeIter objects
+    use to reference data in the pool.
+    References will be removed from the pool when the model is deleted or explicitly
+    by using the optional "node" argument to the "row_deleted" method when notifying
+    the model of row deletion.
+    """
+
+    leak_references = GObject.Property(default=True, type=bool,
+                                       blurb="If True, strong references to user data attached to iters are "
+                                       "stored in a dictionary pool (default). Otherwise the user data is "
+                                       "stored as a raw pointer to a python object without a reference.")
+
+    #
+    # Methods
+    #
+    def __init__(self):
+        """Initialize. Make sure to call this from derived classes if overridden."""
+        super(GenericTreeModel, self).__init__()
+        self.stamp = 0
+
+        #: Dictionary of (id(user_data): user_data), used when leak-refernces=False
+        self._held_refs = dict()
+
+        # Set initial stamp
+        self.invalidate_iters()
+
+    def iter_depth_first(self):
+        """Depth-first iteration of the entire TreeModel yielding the python nodes."""
+        stack = collections.deque([None])
+        while stack:
+            it = stack.popleft()
+            if it is not None:
+                yield self.get_user_data(it)
+            children = [self.iter_nth_child(it, i) for i in range(self.iter_n_children(it))]
+            stack.extendleft(reversed(children))
+
+    def invalidate_iter(self, iter):
+        """Clear user data and its reference from the iter and this model."""
+        iter.stamp = 0
+        if iter.user_data:
+            if iter.user_data in self._held_refs:
+                del self._held_refs[iter.user_data]
+            iter.user_data = None
+
+    def invalidate_iters(self):
+        """
+        This method invalidates all TreeIter objects associated with this custom tree model
+        and frees their locally pooled references.
+        """
+        self.stamp = random.randint(-2147483648, 2147483647)
+        self._held_refs.clear()
+
+    def iter_is_valid(self, iter):
+        """
+        :Returns:
+            True if the gtk.TreeIter specified by iter is valid for the custom tree model.
+        """
+        return iter.stamp == self.stamp
+
+    def get_user_data(self, iter):
+        """Get the user_data associated with the given TreeIter.
+
+        GenericTreeModel stores arbitrary Python objects mapped to instances of Gtk.TreeIter.
+        This method allows to retrieve the Python object held by the given iterator.
+        """
+        if self.leak_references:
+            return self._held_refs[iter.user_data]
+        else:
+            return _get_user_data_as_pyobject(iter)
+
+    def set_user_data(self, iter, user_data):
+        """Applies user_data and stamp to the given iter.
+
+        If the models "leak_references" property is set, a reference to the
+        user_data is stored with the model to ensure we don't run into bad
+        memory problems with the TreeIter.
+        """
+        iter.user_data = id(user_data)
+
+        if user_data is None:
+            self.invalidate_iter(iter)
+        else:
+            iter.stamp = self.stamp
+            if self.leak_references:
+                self._held_refs[iter.user_data] = user_data
+
+    def create_tree_iter(self, user_data):
+        """Create a Gtk.TreeIter instance with the given user_data specific for this model.
+
+        Use this method to create Gtk.TreeIter instance instead of directly calling
+        Gtk.Treeiter(), this will ensure proper reference managment of wrapped used_data.
+        """
+        iter = Gtk.TreeIter()
+        self.set_user_data(iter, user_data)
+        return iter
+
+    def _create_tree_iter(self, data):
+        """Internal creation of a (bool, TreeIter) pair for returning directly
+        back to the view interfacing with this model."""
+        if data is None:
+            return (False, None)
+        else:
+            it = self.create_tree_iter(data)
+            return (True, it)
+
+    def row_deleted(self, path, node=None):
+        """Notify the model a row has been deleted.
+
+        Use the node parameter to ensure the user_data reference associated
+        with the path is properly freed by this model.
+
+        :Parameters:
+            path : Gtk.TreePath
+                Path to the row that has been deleted.
+            node : object
+                Python object used as the node returned from "on_get_iter". This is
+                optional but ensures the model will not leak references to this object.
+        """
+        super(GenericTreeModel, self).row_deleted(path)
+        node_id = id(node)
+        if node_id in self._held_refs:
+            del self._held_refs[node_id]
+
+    #
+    # GtkTreeModel Interface Implementation
+    #
+    @handle_exception(0)
+    def do_get_flags(self):
+        """Internal method."""
+        return self.on_get_flags()
+
+    @handle_exception(0)
+    def do_get_n_columns(self):
+        """Internal method."""
+        return self.on_get_n_columns()
+
+    @handle_exception(GObject.TYPE_INVALID)
+    def do_get_column_type(self, index):
+        """Internal method."""
+        return self.on_get_column_type(index)
+
+    @handle_exception((False, None))
+    def do_get_iter(self, path):
+        """Internal method."""
+        return self._create_tree_iter(self.on_get_iter(path))
+
+    @handle_exception(False)
+    def do_iter_next(self, iter):
+        """Internal method."""
+        if iter is None:
+            next_data = self.on_iter_next(None)
+        else:
+            next_data = self.on_iter_next(self.get_user_data(iter))
+
+        self.set_user_data(iter, next_data)
+        return next_data is not None
+
+    @handle_exception(None)
+    def do_get_path(self, iter):
+        """Internal method."""
+        path = self.on_get_path(self.get_user_data(iter))
+        if path is None:
+            return None
+        else:
+            return Gtk.TreePath(path)
+
+    @handle_exception(None)
+    def do_get_value(self, iter, column):
+        """Internal method."""
+        return self.on_get_value(self.get_user_data(iter), column)
+
+    @handle_exception((False, None))
+    def do_iter_children(self, parent):
+        """Internal method."""
+        data = self.get_user_data(parent) if parent else None
+        return self._create_tree_iter(self.on_iter_children(data))
+
+    @handle_exception(False)
+    def do_iter_has_child(self, parent):
+        """Internal method."""
+        return self.on_iter_has_child(self.get_user_data(parent))
+
+    @handle_exception(0)
+    def do_iter_n_children(self, iter):
+        """Internal method."""
+        if iter is None:
+            return self.on_iter_n_children(None)
+        return self.on_iter_n_children(self.get_user_data(iter))
+
+    @handle_exception((False, None))
+    def do_iter_nth_child(self, parent, n):
+        """Internal method."""
+        if parent is None:
+            data = self.on_iter_nth_child(None, n)
+        else:
+            data = self.on_iter_nth_child(self.get_user_data(parent), n)
+        return self._create_tree_iter(data)
+
+    @handle_exception((False, None))
+    def do_iter_parent(self, child):
+        """Internal method."""
+        return self._create_tree_iter(self.on_iter_parent(self.get_user_data(child)))
+
+    @handle_exception(None)
+    def do_ref_node(self, iter):
+        self.on_ref_node(self.get_user_data(iter))
+
+    @handle_exception(None)
+    def do_unref_node(self, iter):
+        self.on_unref_node(self.get_user_data(iter))
+
+    #
+    # Python Subclass Overridables
+    #
+    def on_get_flags(self):
+        """Overridable.
+
+        :Returns Gtk.TreeModelFlags:
+            The flags for this model. See: Gtk.TreeModelFlags
+        """
+        raise NotImplementedError
+
+    def on_get_n_columns(self):
+        """Overridable.
+
+        :Returns:
+            The number of columns for this model.
+        """
+        raise NotImplementedError
+
+    def on_get_column_type(self, index):
+        """Overridable.
+
+        :Returns:
+            The column type for the given index.
+        """
+        raise NotImplementedError
+
+    def on_get_iter(self, path):
+        """Overridable.
+
+        :Returns:
+            A python object (node) for the given TreePath.
+        """
+        raise NotImplementedError
+
+    def on_iter_next(self, node):
+        """Overridable.
+
+        :Parameters:
+            node : object
+                Node at current level.
+
+        :Returns:
+            A python object (node) following the given node at the current level.
+        """
+        raise NotImplementedError
+
+    def on_get_path(self, node):
+        """Overridable.
+
+        :Returns:
+            A TreePath for the given node.
+        """
+        raise NotImplementedError
+
+    def on_get_value(self, node, column):
+        """Overridable.
+
+        :Parameters:
+            node : object
+            column : int
+                Column index to get the value from.
+
+        :Returns:
+            The value of the column for the given node."""
+        raise NotImplementedError
+
+    def on_iter_children(self, parent):
+        """Overridable.
+
+        :Returns:
+            The first child of parent or None if parent has no children.
+            If parent is None, return the first node of the model.
+        """
+        raise NotImplementedError
+
+    def on_iter_has_child(self, node):
+        """Overridable.
+
+        :Returns:
+            True if the given node has children.
+        """
+        raise NotImplementedError
+
+    def on_iter_n_children(self, node):
+        """Overridable.
+
+        :Returns:
+            The number of children for the given node. If node is None,
+            return the number of top level nodes.
+        """
+        raise NotImplementedError
+
+    def on_iter_nth_child(self, parent, n):
+        """Overridable.
+
+        :Parameters:
+            parent : object
+            n : int
+                Index of child within parent.
+
+        :Returns:
+            The child for the given parent index starting at 0. If parent None,
+            return the top level node corresponding to "n".
+            If "n" is larger then available nodes, return None.
+        """
+        raise NotImplementedError
+
+    def on_iter_parent(self, child):
+        """Overridable.
+
+        :Returns:
+            The parent node of child or None if child is a top level node."""
+        raise NotImplementedError
+
+    def on_ref_node(self, node):
+        pass
+
+    def on_unref_node(self, node):
+        pass
index 18ebd7b..4267a60 100644 (file)
@@ -100,7 +100,7 @@ def enable():
 _unset = object()
 
 
-def enable_gtk(version='2.0'):
+def enable_gtk(version='3.0'):
     # set the default encoding like PyGTK
     reload(sys)
     if sys.version_info < (3, 0):
@@ -190,6 +190,12 @@ def enable_gtk(version='2.0'):
     Gdk.screen_width = Gdk.Screen.width
     Gdk.screen_height = Gdk.Screen.height
 
+    orig_gdk_window_get_geometry = Gdk.Window.get_geometry
+
+    def gdk_window_get_geometry(window):
+        return orig_gdk_window_get_geometry(window) + (window.get_visual().get_best_depth(),)
+    Gdk.Window.get_geometry = gdk_window_get_geometry
+
     # gtk
     gi.require_version('Gtk', version)
     from gi.repository import Gtk
@@ -371,6 +377,8 @@ def enable_gtk(version='2.0'):
 
     # Widget
 
+    Gtk.Widget.window = property(fget=Gtk.Widget.get_window)
+
     Gtk.widget_get_default_direction = Gtk.Widget.get_default_direction
     orig_size_request = Gtk.Widget.size_request
 
@@ -405,6 +413,62 @@ def enable_gtk(version='2.0'):
             return Styles(instance)
     Gtk.Widget.style = StyleDescriptor()
 
+    # TextView
+
+    orig_text_view_scroll_to_mark = Gtk.TextView.scroll_to_mark
+
+    def text_view_scroll_to_mark(self, mark, within_margin,
+                                 use_align=False, xalign=0.5, yalign=0.5):
+        return orig_text_view_scroll_to_mark(self, mark, within_margin,
+                                             use_align, xalign, yalign)
+    Gtk.TextView.scroll_to_mark = text_view_scroll_to_mark
+
+    # Window
+
+    orig_set_geometry_hints = Gtk.Window.set_geometry_hints
+
+    def set_geometry_hints(self, geometry_widget=None,
+                           min_width=-1, min_height=-1, max_width=-1, max_height=-1,
+                           base_width=-1, base_height=-1, width_inc=-1, height_inc=-1,
+                           min_aspect=-1.0, max_aspect=-1.0):
+
+        geometry = Gdk.Geometry()
+        geom_mask = Gdk.WindowHints(0)
+
+        if min_width >= 0 or min_height >= 0:
+            geometry.min_width = max(min_width, 0)
+            geometry.min_height = max(min_height, 0)
+            geom_mask |= Gdk.WindowHints.MIN_SIZE
+
+        if max_width >= 0 or max_height >= 0:
+            geometry.max_width = max(max_width, 0)
+            geometry.max_height = max(max_height, 0)
+            geom_mask |= Gdk.WindowHints.MAX_SIZE
+
+        if base_width >= 0 or base_height >= 0:
+            geometry.base_width = max(base_width, 0)
+            geometry.base_height = max(base_height, 0)
+            geom_mask |= Gdk.WindowHints.BASE_SIZE
+
+        if width_inc >= 0 or height_inc >= 0:
+            geometry.width_inc = max(width_inc, 0)
+            geometry.height_inc = max(height_inc, 0)
+            geom_mask |= Gdk.WindowHints.RESIZE_INC
+
+        if min_aspect >= 0.0 or max_aspect >= 0.0:
+            if min_aspect <= 0.0 or max_aspect <= 0.0:
+                raise TypeError("aspect ratios must be positive")
+
+            geometry.min_aspect = min_aspect
+            geometry.max_aspect = max_aspect
+            geom_mask |= Gdk.WindowHints.ASPECT
+
+        return orig_set_geometry_hints(self, geometry_widget, geometry, geom_mask)
+
+    Gtk.Window.set_geometry_hints = set_geometry_hints
+    Gtk.window_list_toplevels = Gtk.Window.list_toplevels
+    Gtk.window_set_default_icon_name = Gtk.Window.set_default_icon_name
+
     # gtk.unixprint
 
     class UnixPrint(object):
@@ -427,6 +491,9 @@ def enable_gtk(version='2.0'):
             value = getattr(Gdk, name)
             setattr(keysyms, target, value)
 
+    from . import generictreemodel
+    Gtk.GenericTreeModel = generictreemodel.GenericTreeModel
+
 
 def enable_vte():
     gi.require_version('Vte', '0.0')
index 77efd2e..140fa2b 100644 (file)
@@ -84,6 +84,7 @@ EXTRA_DIST = \
        test-unknown.h \
        te_ST@nouppera \
        org.gnome.test.gschema.xml \
+       test_gio.py \
        test_glib.py \
        test_gobject.py \
        test_gtype.py \
@@ -91,6 +92,7 @@ EXTRA_DIST = \
        test_internal_api.py \
        test_iochannel.py \
        test_mainloop.py \
+       test_object_marshaling.py \
        test_option.py \
        test_properties.py \
        test_signal.py \
@@ -101,12 +103,12 @@ EXTRA_DIST = \
        test_gi.py \
        test_gdbus.py \
        test_overrides.py \
-       test_overrides_gio.py \
        test_overrides_glib.py \
        test_overrides_pango.py \
        test_overrides_gdk.py \
        test_overrides_gtk.py \
        test_atoms.py \
+       test_generictreemodel.py \
        compat_test_pygtk.py \
        gi/__init__.py \
        gi/overrides/__init__.py \
@@ -124,6 +126,7 @@ RUN_TESTS_ENV_VARS= \
        XDG_DATA_DIRS=$$XDG_DATA_DIRS:/usr/share \
        MALLOC_PERTURB_=85 \
        MALLOC_CHECK_=3 \
+       G_SLICE=debug-blocks \
        TESTS_BUILDDIR=$(builddir)
 
 # pygtkcompat tests need to be run in a separate process as they
@@ -136,7 +139,7 @@ check-local: $(LTLIBRARIES:.la=.so) $(test_typelibs) gschemas.compiled
                if type pep8 >/dev/null 2>&1; then pep8 --ignore=E501,E123,E124 --repeat --show-source $(top_srcdir); else echo "skipped, pep8 not installed"; fi; \
        fi
        export `$(DBUS_LAUNCH)` && \
-       $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; \
+       $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; \
        [ "$$rc" -ne 0 ] || [ -n "$$TEST_NAMES" ] || { TEST_NAMES=compat_test_pygtk $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; }; \
        kill $$DBUS_SESSION_BUS_PID; \
        exit $$rc
@@ -148,4 +151,4 @@ check.nemiver:
        EXEC_NAME="nemiver" $(MAKE) check
 
 check.valgrind:
-       EXEC_NAME="valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_SLICE=always-malloc G_DEBUG=gc-friendly $(MAKE) check
+       EXEC_NAME="valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
index 5aa69dc..6f3cd5e 100644 (file)
@@ -243,6 +243,7 @@ SHELL = @SHELL@
 STRIP = @STRIP@
 THREADING_CFLAGS = @THREADING_CFLAGS@
 VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
 abs_builddir = @abs_builddir@
 abs_srcdir = @abs_srcdir@
 abs_top_builddir = @abs_top_builddir@
@@ -330,6 +331,7 @@ EXTRA_DIST = \
        test-unknown.h \
        te_ST@nouppera \
        org.gnome.test.gschema.xml \
+       test_gio.py \
        test_glib.py \
        test_gobject.py \
        test_gtype.py \
@@ -337,6 +339,7 @@ EXTRA_DIST = \
        test_internal_api.py \
        test_iochannel.py \
        test_mainloop.py \
+       test_object_marshaling.py \
        test_option.py \
        test_properties.py \
        test_signal.py \
@@ -347,12 +350,12 @@ EXTRA_DIST = \
        test_gi.py \
        test_gdbus.py \
        test_overrides.py \
-       test_overrides_gio.py \
        test_overrides_glib.py \
        test_overrides_pango.py \
        test_overrides_gdk.py \
        test_overrides_gtk.py \
        test_atoms.py \
+       test_generictreemodel.py \
        compat_test_pygtk.py \
        gi/__init__.py \
        gi/overrides/__init__.py \
@@ -367,6 +370,7 @@ RUN_TESTS_ENV_VARS = \
        XDG_DATA_DIRS=$$XDG_DATA_DIRS:/usr/share \
        MALLOC_PERTURB_=85 \
        MALLOC_CHECK_=3 \
+       G_SLICE=debug-blocks \
        TESTS_BUILDDIR=$(builddir)
 
 all: all-am
@@ -758,7 +762,7 @@ check-local: $(LTLIBRARIES:.la=.so) $(test_typelibs) gschemas.compiled
                if type pep8 >/dev/null 2>&1; then pep8 --ignore=E501,E123,E124 --repeat --show-source $(top_srcdir); else echo "skipped, pep8 not installed"; fi; \
        fi
        export `$(DBUS_LAUNCH)` && \
-       $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; \
+       $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; \
        [ "$$rc" -ne 0 ] || [ -n "$$TEST_NAMES" ] || { TEST_NAMES=compat_test_pygtk $(RUN_TESTS_ENV_VARS) $(EXEC_NAME) $(PYTHON) -Wd -Werror::PendingDeprecationWarning -Werror::DeprecationWarning -Werror::RuntimeWarning $(srcdir)/runtests.py; rc=$$?; }; \
        kill $$DBUS_SESSION_BUS_PID; \
        exit $$rc
@@ -770,7 +774,7 @@ check.nemiver:
        EXEC_NAME="nemiver" $(MAKE) check
 
 check.valgrind:
-       EXEC_NAME="valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_SLICE=always-malloc G_DEBUG=gc-friendly $(MAKE) check
+       EXEC_NAME="valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
index 9f3a7ec..d3a4f47 100755 (executable)
@@ -18,6 +18,13 @@ if sys.version_info[:2] == (2, 6):
     unittest.skipUnless = skipUnless
     unittest.expectedFailure = lambda obj: obj
 
+    def skipIf(condition, reason):
+        if condition:
+            sys.stderr.write('[expected failure] ')
+        return lambda obj: obj
+
+    unittest.skipIf = skipIf
+
     def assertGreater(self, a, b, msg=None):
         if not a > b:
             self.fail('%s not greater than %s' % (repr(a), repr(b)))
@@ -26,12 +33,22 @@ if sys.version_info[:2] == (2, 6):
         if not a >= b:
             self.fail('%s not greater than or equal to %s' % (repr(a), repr(b)))
 
+    def assertLess(self, a, b, msg=None):
+        if not a < b:
+            self.fail('%s not less than %s' % (repr(a), repr(b)))
+
+    def assertLessEqual(self, a, b, msg=None):
+        if not a <= b:
+            self.fail('%s not less than or equal to %s' % (repr(a), repr(b)))
+
     def assertIsInstance(self, obj, cls, msg=None):
         if not isinstance(obj, cls):
             self.fail('%s is not an instance of %r' % (repr(obj), cls))
 
     unittest.TestCase.assertGreaterEqual = assertGreaterEqual
     unittest.TestCase.assertGreater = assertGreater
+    unittest.TestCase.assertLessEqual = assertLessEqual
+    unittest.TestCase.assertLess = assertLess
     unittest.TestCase.assertIsInstance = assertIsInstance
 
 if sys.version_info[:2] == (2, 7):
@@ -59,6 +76,7 @@ os.environ['G_DEBUG'] = 'fatal-warnings fatal-criticals'
 # first.
 os.environ['GSETTINGS_BACKEND'] = 'memory'
 os.environ['GSETTINGS_SCHEMA_DIR'] = tests_builddir
+os.environ['G_FILENAME_ENCODING'] = 'UTF-8'
 
 # Load tests.
 if 'TEST_NAMES' in os.environ:
index 0f5b909..438cb97 100644 (file)
@@ -43,8 +43,7 @@ other_thread_cb (TestThread *self)
 static void
 test_thread_emit_signal (TestThread *self)
 {
-  self->thread = g_thread_create ((GThreadFunc)other_thread_cb,
-                                 self, TRUE, NULL);
+  self->thread = g_thread_new ("t", (GThreadFunc)other_thread_cb, self);
 }
 
 static void test_thread_init (TestThread *self) {}
index f1f14b7..3c820d7 100644 (file)
@@ -218,7 +218,6 @@ class TestEverything(unittest.TestCase):
                          GObject.G_MAXDOUBLE)
         self.assertEqual(Everything.test_double(GObject.G_MINDOUBLE),
                          GObject.G_MINDOUBLE)
-        self.assertRaises(ValueError, Everything.test_double, GObject.G_MAXDOUBLE * 2)
 
         (two, three) = Everything.test_multi_double_args(2.5)
         self.assertAlmostEqual(two, 5.0)
@@ -675,17 +674,14 @@ class TestCallbacks(unittest.TestCase):
         self.assertEqual(TestCallbacks.called, 2)
         self.assertEqual(sys.getrefcount(callback), refcount)
 
-    # FIXME: TypeError: callback() takes 2 positional arguments but 4 were given
-    # does not remove the array length arguments
-    @unittest.expectedFailure
     def test_callback_scope_call_array(self):
         # This tests a callback that gets called multiple times from a
         # single scope call in python with array arguments
         TestCallbacks.callargs = []
 
-        # works with:
-        #def callback(one, one_length, two, two_length):
-        def callback(one, two):
+        # FIXME: would be cleaner without the explicit length args:
+        # def callback(one, two):
+        def callback(one, one_length, two, two_length):
             TestCallbacks.callargs.append((one, two))
             return len(TestCallbacks.callargs)
 
@@ -1195,6 +1191,28 @@ class TestSignals(unittest.TestCase):
         obj.emit_sig_with_uint64()
         self.assertEqual(obj.callback_i, GObject.G_MAXUINT64)
 
+    def test_intarray_ret(self):
+        obj = Everything.TestObj()
+
+        def callback(obj, i):
+            obj.callback_i = i
+            return [i, i + 1]
+
+        obj.callback_i = None
+
+        try:
+            obj.connect('sig-with-intarray-ret', callback)
+        except TypeError as e:
+            # compat with g-i 1.34.x
+            if 'unknown signal' in str(e):
+                return
+            raise
+
+        rv = obj.emit('sig-with-intarray-ret', 42)
+        self.assertEqual(obj.callback_i, 42)
+        self.assertEqual(type(rv), GLib.Array)
+        self.assertEqual(rv.len, 2)
+
 
 @unittest.skipUnless(has_cairo, 'built without cairo support')
 @unittest.skipUnless(Gtk, 'Gtk not available')
diff --git a/tests/test_generictreemodel.py b/tests/test_generictreemodel.py
new file mode 100644 (file)
index 0000000..ff0f523
--- /dev/null
@@ -0,0 +1,406 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# test_generictreemodel - Tests for GenericTreeModel
+# Copyright (C) 2013 Simon Feltman
+#
+#   test_generictreemodel.py: Tests for GenericTreeModel
+#
+# This library 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 2.1 of the License, or (at your option) any later version.
+#
+# This library 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 Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+# USA
+
+
+# system
+import gc
+import sys
+import weakref
+import unittest
+
+# pygobject
+from gi.repository import GObject
+from gi.repository import Gtk
+from pygtkcompat.generictreemodel import GenericTreeModel
+from pygtkcompat.generictreemodel import _get_user_data_as_pyobject
+
+
+class Node(object):
+    """Represents a generic node with name, value, and children."""
+    def __init__(self, name, value, *children):
+        self.name = name
+        self.value = value
+        self.children = list(children)
+        self.parent = None
+        self.next = None
+
+        for i, child in enumerate(children):
+            child.parent = weakref.ref(self)
+            if i < len(children) - 1:
+                child.next = weakref.ref(children[i + 1])
+
+    def __repr__(self):
+        return 'Node("%s", %s)' % (self.name, self.value)
+
+
+class TesterModel(GenericTreeModel):
+    def __init__(self):
+        super(TesterModel, self).__init__()
+        self.root = Node('root', 0,
+                         Node('spam', 1,
+                              Node('sushi', 2),
+                              Node('bread', 3)
+                         ),
+                         Node('eggs', 4)
+                        )
+
+    def on_get_flags(self):
+        return 0
+
+    def on_get_n_columns(self):
+        return 2
+
+    def on_get_column_type(self, n):
+        return (str, int)[n]
+
+    def on_get_iter(self, path):
+        node = self.root
+        path = list(path)
+        idx = path.pop(0)
+        while path:
+            idx = path.pop(0)
+            node = node.children[idx]
+        return node
+
+    def on_get_path(self, node):
+        def rec_get_path(n):
+            for i, child in enumerate(n.children):
+                if child == node:
+                    return [i]
+                else:
+                    res = rec_get_path(child)
+                    if res:
+                        res.insert(0, i)
+
+        return rec_get_path(self.root)
+
+    def on_get_value(self, node, column):
+        if column == 0:
+            return node.name
+        elif column == 1:
+            return node.value
+
+    def on_iter_has_child(self, node):
+        return bool(node.children)
+
+    def on_iter_next(self, node):
+        if node.next:
+            return node.next()
+
+    def on_iter_children(self, node):
+        if node:
+            return node.children[0]
+        else:
+            return self.root
+
+    def on_iter_n_children(self, node):
+        if node is None:
+            return 1
+        return len(node.children)
+
+    def on_iter_nth_child(self, node, n):
+        if node is None:
+            assert n == 0
+            return self.root
+        return node.children[n]
+
+    def on_iter_parent(self, child):
+        if child.parent:
+            return child.parent()
+
+
+class TestReferences(unittest.TestCase):
+    def setUp(self):
+        pass
+
+    def test_c_tree_iter_user_data_as_pyobject(self):
+        obj = object()
+        obj_id = id(obj)
+        ref_count = sys.getrefcount(obj)
+
+        # This is essentially a stolen ref in the context of _CTreeIter.get_user_data_as_pyobject
+        it = Gtk.TreeIter()
+        it.user_data = obj_id
+
+        obj2 = _get_user_data_as_pyobject(it)
+        self.assertEqual(obj, obj2)
+        self.assertEqual(sys.getrefcount(obj), ref_count + 1)
+
+    def test_leak_references_on(self):
+        model = TesterModel()
+        obj_ref = weakref.ref(model.root)
+        # Initial refcount is 1 for model.root + the temporary
+        self.assertEqual(sys.getrefcount(model.root), 2)
+
+        # Iter increases by 1 do to assignment to iter.user_data
+        res, it = model.do_get_iter([0])
+        self.assertEqual(id(model.root), it.user_data)
+        self.assertEqual(sys.getrefcount(model.root), 3)
+
+        # Verify getting a TreeIter more then once does not further increase
+        # the ref count.
+        res2, it2 = model.do_get_iter([0])
+        self.assertEqual(id(model.root), it2.user_data)
+        self.assertEqual(sys.getrefcount(model.root), 3)
+
+        # Deleting the iter does not decrease refcount because references
+        # leak by default (they are stored in the held_refs pool)
+        del it
+        gc.collect()
+        self.assertEqual(sys.getrefcount(model.root), 3)
+
+        # Deleting a model should free all held references to user data
+        # stored by TreeIters
+        del model
+        gc.collect()
+        self.assertEqual(obj_ref(), None)
+
+    def test_row_deleted_frees_refs(self):
+        model = TesterModel()
+        obj_ref = weakref.ref(model.root)
+        # Initial refcount is 1 for model.root + the temporary
+        self.assertEqual(sys.getrefcount(model.root), 2)
+
+        # Iter increases by 1 do to assignment to iter.user_data
+        res, it = model.do_get_iter([0])
+        self.assertEqual(id(model.root), it.user_data)
+        self.assertEqual(sys.getrefcount(model.root), 3)
+
+        # Notifying the underlying model of a row_deleted should decrease the
+        # ref count.
+        model.row_deleted(Gtk.TreePath('0'), model.root)
+        self.assertEqual(sys.getrefcount(model.root), 2)
+
+        # Finally deleting the actual object should collect it completely
+        del model.root
+        gc.collect()
+        self.assertEqual(obj_ref(), None)
+
+    def test_leak_references_off(self):
+        model = TesterModel()
+        model.leak_references = False
+
+        obj_ref = weakref.ref(model.root)
+        # Initial refcount is 1 for model.root + the temporary
+        self.assertEqual(sys.getrefcount(model.root), 2)
+
+        # Iter does not increas count by 1 when leak_references is false
+        res, it = model.do_get_iter([0])
+        self.assertEqual(id(model.root), it.user_data)
+        self.assertEqual(sys.getrefcount(model.root), 2)
+
+        # Deleting the iter does not decrease refcount because assigning user_data
+        # eats references and does not release them.
+        del it
+        gc.collect()
+        self.assertEqual(sys.getrefcount(model.root), 2)
+
+        # Deleting the model decreases the final ref, and the object is collected
+        del model
+        gc.collect()
+        self.assertEqual(obj_ref(), None)
+
+    def test_iteration_refs(self):
+        # Pull iterators off the model using the wrapped C API which will
+        # then call back into the python overrides.
+        model = TesterModel()
+        nodes = [node for node in model.iter_depth_first()]
+        values = [node.value for node in nodes]
+
+        # Verify depth first ordering
+        self.assertEqual(values, [0, 1, 2, 3, 4])
+
+        # Verify ref counts for each of the nodes.
+        # 5 refs for each node at this point:
+        #   1 - ref held in getrefcount function
+        #   2 - ref held by "node" var during iteration
+        #   3 - ref held by local "nodes" var
+        #   4 - ref held by the root/children graph itself
+        #   5 - ref held by the model "held_refs" instance var
+        for node in nodes:
+            self.assertEqual(sys.getrefcount(node), 5)
+
+        # A second iteration and storage of the nodes in a new list
+        # should only increase refcounts by 1 even though new
+        # iterators are created and assigned.
+        nodes2 = [node for node in model.iter_depth_first()]
+        for node in nodes2:
+            self.assertEqual(sys.getrefcount(node), 6)
+
+        # Hold weak refs and start verifying ref collection.
+        node_refs = [weakref.ref(node) for node in nodes]
+
+        # First round of collection
+        del nodes2
+        gc.collect()
+        for node in nodes:
+            self.assertEqual(sys.getrefcount(node), 5)
+
+        # Second round of collection, no more local lists of nodes.
+        del nodes
+        gc.collect()
+        for ref in node_refs:
+            node = ref()
+            self.assertEqual(sys.getrefcount(node), 4)
+
+        # Using invalidate_iters or row_deleted(path, node) will clear out
+        # the pooled refs held internal to the GenericTreeModel implementation.
+        model.invalidate_iters()
+        self.assertEqual(len(model._held_refs), 0)
+        gc.collect()
+        for ref in node_refs:
+            node = ref()
+            self.assertEqual(sys.getrefcount(node), 3)
+
+        # Deleting the root node at this point should allow all nodes to be collected
+        # as there is no longer a way to reach the children
+        del node  # node still in locals() from last iteration
+        del model.root
+        gc.collect()
+        for ref in node_refs:
+            self.assertEqual(ref(), None)
+
+
+class TestIteration(unittest.TestCase):
+    def test_iter_next_root(self):
+        model = TesterModel()
+        it = model.get_iter([0])
+        self.assertEqual(it.user_data, id(model.root))
+        self.assertEqual(model.root.next, None)
+
+        it = model.iter_next(it)
+        self.assertEqual(it, None)
+
+    def test_iter_next_multiple(self):
+        model = TesterModel()
+        it = model.get_iter([0, 0])
+        self.assertEqual(it.user_data, id(model.root.children[0]))
+
+        it = model.iter_next(it)
+        self.assertEqual(it.user_data, id(model.root.children[1]))
+
+        it = model.iter_next(it)
+        self.assertEqual(it, None)
+
+
+class ErrorModel(GenericTreeModel):
+    # All on_* methods will raise a NotImplementedError by default
+    pass
+
+
+class ExceptHook(object):
+    """
+    Temporarily installs an exception hook in a context which
+    expects the given exc_type to be raised. This allows verification
+    of exceptions that occur within python gi callbacks but
+    are never bubbled through from python to C back to python.
+    This works because exception hooks are called in PyErr_Print.
+    """
+    def __init__(self, exc_type):
+        self._exc_type = exc_type
+        self._exceptions = []
+
+    def _excepthook(self, exc_type, value, traceback):
+        self._exceptions.append(exc_type)
+
+    def __enter__(self):
+        self._oldhook = sys.excepthook
+        sys.excepthook = self._excepthook
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        sys.excepthook = self._oldhook
+        assert len(self._exceptions) == 1, 'Expecting exactly one exception of type %s' % self._exc_type
+        assert issubclass(self._exceptions[0], self._exc_type), 'Expecting exactly one exception of type %s' % self._exc_type
+
+
+class TestReturnsAfterError(unittest.TestCase):
+    def setUp(self):
+        self.model = ErrorModel()
+
+    def test_get_flags(self):
+        with ExceptHook(NotImplementedError):
+            flags = self.model.get_flags()
+        self.assertEqual(flags, 0)
+
+    def test_get_n_columns(self):
+        with ExceptHook(NotImplementedError):
+            count = self.model.get_n_columns()
+        self.assertEqual(count, 0)
+
+    def test_get_column_type(self):
+        with ExceptHook(NotImplementedError):
+            col_type = self.model.get_column_type(0)
+        self.assertEqual(col_type, GObject.TYPE_INVALID)
+
+    def test_get_iter(self):
+        with ExceptHook(NotImplementedError):
+            self.assertRaises(ValueError, self.model.get_iter, Gtk.TreePath(0))
+
+    def test_get_path(self):
+        it = self.model.create_tree_iter('foo')
+        with ExceptHook(NotImplementedError):
+            path = self.model.get_path(it)
+        self.assertEqual(path, None)
+
+    def test_get_value(self):
+        it = self.model.create_tree_iter('foo')
+        with ExceptHook(NotImplementedError):
+            try:
+                self.model.get_value(it, 0)
+            except TypeError:
+                pass  # silence TypeError converting None to GValue
+
+    def test_iter_has_child(self):
+        it = self.model.create_tree_iter('foo')
+        with ExceptHook(NotImplementedError):
+            res = self.model.iter_has_child(it)
+        self.assertEqual(res, False)
+
+    def test_iter_next(self):
+        it = self.model.create_tree_iter('foo')
+        with ExceptHook(NotImplementedError):
+            res = self.model.iter_next(it)
+        self.assertEqual(res, None)
+
+    def test_iter_children(self):
+        with ExceptHook(NotImplementedError):
+            res = self.model.iter_children(None)
+        self.assertEqual(res, None)
+
+    def test_iter_n_children(self):
+        with ExceptHook(NotImplementedError):
+            res = self.model.iter_n_children(None)
+        self.assertEqual(res, 0)
+
+    def test_iter_nth_child(self):
+        with ExceptHook(NotImplementedError):
+            res = self.model.iter_nth_child(None, 0)
+        self.assertEqual(res, None)
+
+    def test_iter_parent(self):
+        child = self.model.create_tree_iter('foo')
+        with ExceptHook(NotImplementedError):
+            res = self.model.iter_parent(child)
+        self.assertEqual(res, None)
+
+if __name__ == '__main__':
+    unittest.main()
index a2664f1..2671588 100644 (file)
@@ -12,6 +12,7 @@ import locale
 import subprocess
 import gc
 import weakref
+import warnings
 from io import StringIO, BytesIO
 
 import gi
@@ -812,6 +813,18 @@ class TestArray(unittest.TestCase):
 
         GIMarshallingTests.array_struct_in([struct1, struct2, struct3])
 
+    @unittest.skipUnless(hasattr(GIMarshallingTests, 'array_struct_value_in'),
+                         'too old gobject-introspection')
+    def test_array_boxed_struct_value_in(self):
+        struct1 = GIMarshallingTests.BoxedStruct()
+        struct1.long_ = 1
+        struct2 = GIMarshallingTests.BoxedStruct()
+        struct2.long_ = 2
+        struct3 = GIMarshallingTests.BoxedStruct()
+        struct3.long_ = 3
+
+        GIMarshallingTests.array_struct_value_in([struct1, struct2, struct3])
+
     def test_array_boxed_struct_take_in(self):
         struct1 = GIMarshallingTests.BoxedStruct()
         struct1.long_ = 1
@@ -824,13 +837,11 @@ class TestArray(unittest.TestCase):
 
         self.assertEqual(1, struct1.long_)
 
-    @unittest.expectedFailure
     def test_array_boxed_struct_return(self):
         (struct1, struct2, struct3) = GIMarshallingTests.array_zero_terminated_return_struct()
         self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct1))
         self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct2))
         self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct3))
-        # FIXME: gets bogus values
         self.assertEqual(42, struct1.long_)
         self.assertEqual(43, struct2.long_)
         self.assertEqual(44, struct3.long_)
@@ -1042,8 +1053,8 @@ class TestGBytes(unittest.TestCase):
         self.assertFalse(b.equal(a2))
 
         self.assertEqual(0, a1.compare(a2))
-        self.assertEqual(1, a1.compare(b))
-        self.assertEqual(-1, b.compare(a1))
+        self.assertLess(0, a1.compare(b))
+        self.assertGreater(0, b.compare(a1))
 
 
 class TestGByteArray(unittest.TestCase):
@@ -1213,32 +1224,24 @@ class TestGValue(unittest.TestCase):
 
     def test_gvalue_in(self):
         GIMarshallingTests.gvalue_in(42)
-        value = GObject.Value()
-        value.init(GObject.TYPE_INT)
-        value.set_int(42)
+        value = GObject.Value(GObject.TYPE_INT, 42)
         GIMarshallingTests.gvalue_in(value)
 
     def test_gvalue_int64_in(self):
-        value = GObject.Value()
-        value.init(GObject.TYPE_INT64)
-        value.set_int64(GObject.G_MAXINT64)
+        value = GObject.Value(GObject.TYPE_INT64, GObject.G_MAXINT64)
         GIMarshallingTests.gvalue_int64_in(value)
 
     def test_gvalue_in_with_type(self):
-        value = GObject.Value()
-        value.init(GObject.TYPE_STRING)
-        value.set_string('foo')
+        value = GObject.Value(GObject.TYPE_STRING, 'foo')
         GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_STRING)
 
-        value = GObject.Value()
-        value.init(GIMarshallingTests.Flags.__gtype__)
-        value.set_flags(GIMarshallingTests.Flags.VALUE1)
+        value = GObject.Value(GIMarshallingTests.Flags.__gtype__,
+                              GIMarshallingTests.Flags.VALUE1)
         GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_FLAGS)
 
     def test_gvalue_in_enum(self):
-        value = GObject.Value()
-        value.init(GIMarshallingTests.Enum.__gtype__)
-        value.set_enum(GIMarshallingTests.Enum.VALUE3)
+        value = GObject.Value(GIMarshallingTests.Enum.__gtype__,
+                              GIMarshallingTests.Enum.VALUE3)
         GIMarshallingTests.gvalue_in_enum(value)
 
     def test_gvalue_out(self):
@@ -1252,9 +1255,7 @@ class TestGValue(unittest.TestCase):
 
     def test_gvalue_inout(self):
         self.assertEqual('42', GIMarshallingTests.gvalue_inout(42))
-        value = GObject.Value()
-        value.init(GObject.TYPE_INT)
-        value.set_int(42)
+        value = GObject.Value(int, 42)
         self.assertEqual('42', GIMarshallingTests.gvalue_inout(value))
 
     def test_gvalue_flat_array_in(self):
@@ -1350,13 +1351,15 @@ class TestGValue(unittest.TestCase):
 
 class TestGClosure(unittest.TestCase):
 
-    def test_gclosure_in(self):
+    def test_in(self):
         GIMarshallingTests.gclosure_in(lambda: 42)
 
+    def test_pass(self):
         # test passing a closure between two C calls
         closure = GIMarshallingTests.gclosure_return()
         GIMarshallingTests.gclosure_in(closure)
 
+    def test_type_error(self):
         self.assertRaises(TypeError, GIMarshallingTests.gclosure_in, 42)
         self.assertRaises(TypeError, GIMarshallingTests.gclosure_in, None)
 
@@ -1367,13 +1370,11 @@ class TestCallbacks(unittest.TestCase):
             return 5
         self.assertEqual(GIMarshallingTests.callback_return_value_only(cb), 5)
 
-    @unittest.expectedFailure
     def test_one_out_arg(self):
         def cb():
             return 5.5
         self.assertAlmostEqual(GIMarshallingTests.callback_one_out_parameter(cb), 5.5)
 
-    @unittest.expectedFailure
     def test_multiple_out_args(self):
         def cb():
             return (5.5, 42.0)
@@ -1381,7 +1382,6 @@ class TestCallbacks(unittest.TestCase):
         self.assertAlmostEqual(res[0], 5.5)
         self.assertAlmostEqual(res[1], 42.0)
 
-    @unittest.expectedFailure
     def test_return_and_one_out_arg(self):
         def cb():
             return (5, 42.0)
@@ -1389,7 +1389,6 @@ class TestCallbacks(unittest.TestCase):
         self.assertEqual(res[0], 5)
         self.assertAlmostEqual(res[1], 42.0)
 
-    @unittest.expectedFailure
     def test_return_and_multiple_out_arg(self):
         def cb():
             return (5, 42, -1000)
@@ -1477,6 +1476,45 @@ class TestEnum(unittest.TestCase):
         self.assertTrue(hasattr(GIMarshallingTests.Enum, "VALUE1"))
         self.assertRaises(AttributeError, getattr, GIMarshallingTests.SecondEnum, "VALUE1")
 
+    def test_enum_gtype_name_is_namespaced(self):
+        self.assertEqual(GIMarshallingTests.Enum.__gtype__.name,
+                         'PyGIMarshallingTestsEnum')
+
+    def test_enum_double_registration_error(self):
+        # a warning is printed for double registration and pygobject will
+        # also raise a RuntimeError.
+        old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
+        try:
+            self.assertRaises(RuntimeError,
+                              gi._gi.enum_register_new_gtype_and_add,
+                              GIMarshallingTests.Enum.__info__)
+        finally:
+            GLib.log_set_always_fatal(old_mask)
+
+    def test_enum_add_type_error(self):
+        self.assertRaises(TypeError,
+                          gi._gi.enum_add,
+                          GIMarshallingTests.NoTypeFlags.__gtype__)
+
+
+@unittest.skipUnless(hasattr(GIMarshallingTests.Object, 'vfunc_return_enum'),
+                     'GIMarshallingTests too old')
+class TestEnumVFuncResults(unittest.TestCase):
+    class EnumTester(GIMarshallingTests.Object):
+        def do_vfunc_return_enum(self):
+            return GIMarshallingTests.Enum.VALUE2
+
+        def do_vfunc_out_enum(self):
+            return GIMarshallingTests.Enum.VALUE3
+
+    def test_vfunc_return_enum(self):
+        tester = self.EnumTester()
+        self.assertEqual(tester.vfunc_return_enum(), GIMarshallingTests.Enum.VALUE2)
+
+    def test_vfunc_out_enum(self):
+        tester = self.EnumTester()
+        self.assertEqual(tester.vfunc_out_enum(), GIMarshallingTests.Enum.VALUE3)
+
 
 class TestGEnum(unittest.TestCase):
 
@@ -1609,6 +1647,21 @@ class TestNoTypeFlags(unittest.TestCase):
         self.assertTrue(isinstance(flags, GIMarshallingTests.NoTypeFlags))
         self.assertEqual(flags, GIMarshallingTests.NoTypeFlags.VALUE1)
 
+    def test_flags_gtype_name_is_namespaced(self):
+        self.assertEqual(GIMarshallingTests.NoTypeFlags.__gtype__.name,
+                         'PyGIMarshallingTestsNoTypeFlags')
+
+    def test_flags_double_registration_error(self):
+        # a warning is printed for double registration and pygobject will
+        # also raise a RuntimeError.
+        old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
+        try:
+            self.assertRaises(RuntimeError,
+                              gi._gi.flags_register_new_gtype_and_add,
+                              GIMarshallingTests.NoTypeFlags.__info__)
+        finally:
+            GLib.log_set_always_fatal(old_mask)
+
 
 class TestStructure(unittest.TestCase):
 
@@ -1704,6 +1757,8 @@ class TestStructure(unittest.TestCase):
 
         del struct
 
+    @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'),
+                         'too old gobject-introspection')
     def test_boxed_struct(self):
         self.assertTrue(issubclass(GIMarshallingTests.BoxedStruct, GObject.GBoxed))
 
@@ -1711,30 +1766,44 @@ class TestStructure(unittest.TestCase):
         self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct))
 
         self.assertEqual(0, struct.long_)
+        self.assertEqual(None, struct.string_)
         self.assertEqual([], struct.g_strv)
 
         del struct
 
+    @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'),
+                         'too old gobject-introspection')
     def test_boxed_struct_new(self):
         struct = GIMarshallingTests.BoxedStruct.new()
         self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct))
+        self.assertEqual(struct.long_, 0)
+        self.assertEqual(struct.string_, None)
 
         del struct
 
+    @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'),
+                         'too old gobject-introspection')
     def test_boxed_struct_copy(self):
         struct = GIMarshallingTests.BoxedStruct()
+        struct.long_ = 42
+        struct.string_ = 'hello'
 
         new_struct = struct.copy()
         self.assertTrue(isinstance(new_struct, GIMarshallingTests.BoxedStruct))
+        self.assertEqual(new_struct.long_, 42)
+        self.assertEqual(new_struct.string_, 'hello')
 
         del new_struct
         del struct
 
+    @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'),
+                         'too old gobject-introspection')
     def test_boxed_struct_return(self):
         struct = GIMarshallingTests.boxed_struct_returnv()
 
         self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct))
         self.assertEqual(42, struct.long_)
+        self.assertEqual('hello', struct.string_)
         self.assertEqual(['0', '1', '2'], struct.g_strv)
 
         del struct
@@ -1767,6 +1836,14 @@ class TestStructure(unittest.TestCase):
         del in_struct
         del out_struct
 
+    def test_struct_field_assignment(self):
+        struct = GIMarshallingTests.BoxedStruct()
+
+        struct.long_ = 42
+        struct.string_ = 'hello'
+        self.assertEqual(struct.long_, 42)
+        self.assertEqual(struct.string_, 'hello')
+
     def test_union(self):
         union = GIMarshallingTests.Union()
 
@@ -2172,21 +2249,8 @@ class TestMultiOutputArgs(unittest.TestCase):
         self.assertEqual((6, 7), GIMarshallingTests.int_return_out())
 
 
-class TestGErrorException(unittest.TestCase):
-    def test_gerror_exception(self):
-        self.assertRaises(GObject.GError, GIMarshallingTests.gerror)
-        try:
-            GIMarshallingTests.gerror()
-        except Exception:
-            etype, e = sys.exc_info()[:2]
-            self.assertEqual(e.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN)
-            self.assertEqual(e.code, GIMarshallingTests.CONSTANT_GERROR_CODE)
-            self.assertEqual(e.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE)
-
-
 # Interface
 
-
 class TestInterfaces(unittest.TestCase):
 
     class TestInterfaceImpl(GObject.GObject, GIMarshallingTests.Interface):
@@ -2396,19 +2460,17 @@ class TestDir(unittest.TestCase):
         # self.assertTrue('DoNotImportDummyTests' in list)
 
 
-class TestGErrorArrayInCrash(unittest.TestCase):
-    # Previously there was a bug in invoke, in which C arrays were unwrapped
-    # from inside GArrays to be passed to the C function. But when a GError was
-    # set, invoke would attempt to free the C array as if it were a GArray.
-    # This crash is only for C arrays. It does not happen for C functions which
-    # take in GArrays. See https://bugzilla.gnome.org/show_bug.cgi?id=642708
-    def test_gerror_array_in_crash(self):
+class TestGError(unittest.TestCase):
+    def test_array_in_crash(self):
+        # Previously there was a bug in invoke, in which C arrays were unwrapped
+        # from inside GArrays to be passed to the C function. But when a GError was
+        # set, invoke would attempt to free the C array as if it were a GArray.
+        # This crash is only for C arrays. It does not happen for C functions which
+        # take in GArrays. See https://bugzilla.gnome.org/show_bug.cgi?id=642708
         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):
+    def test_out(self):
+        # See https://bugzilla.gnome.org/show_bug.cgi?id=666098
         error, debug = GIMarshallingTests.gerror_out()
 
         self.assertIsInstance(error, GObject.GError)
@@ -2417,10 +2479,8 @@ class TestGErrorOut(unittest.TestCase):
         self.assertEqual(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE)
         self.assertEqual(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):
+    def test_out_transfer_none(self):
+        # See https://bugzilla.gnome.org/show_bug.cgi?id=666098
         error, debug = GIMarshallingTests.gerror_out_transfer_none()
 
         self.assertIsInstance(error, GObject.GError)
@@ -2429,10 +2489,8 @@ class TestGErrorOutTransferNone(unittest.TestCase):
         self.assertEqual(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE)
         self.assertEqual(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):
+    def test_return(self):
+        # See https://bugzilla.gnome.org/show_bug.cgi?id=666098
         error = GIMarshallingTests.gerror_return()
 
         self.assertIsInstance(error, GObject.GError)
@@ -2440,8 +2498,27 @@ class TestGErrorReturn(unittest.TestCase):
         self.assertEqual(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE)
         self.assertEqual(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE)
 
+    def test_exception(self):
+        self.assertRaises(GObject.GError, GIMarshallingTests.gerror)
+        try:
+            GIMarshallingTests.gerror()
+        except Exception:
+            etype, e = sys.exc_info()[:2]
+            self.assertEqual(e.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN)
+            self.assertEqual(e.code, GIMarshallingTests.CONSTANT_GERROR_CODE)
+            self.assertEqual(e.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE)
+
 
 class TestParamSpec(unittest.TestCase):
+    # https://bugzilla.gnome.org/show_bug.cgi?id=682355
+    @unittest.skipUnless(hasattr(GIMarshallingTests, 'param_spec_in_bool'),
+                         'too old gobject-introspection')
+    @unittest.expectedFailure
+    def test_param_spec_in_bool(self):
+        ps = GObject.param_spec_boolean('mybool', 'test-bool', 'boolblurb',
+                                        True, GObject.ParamFlags.READABLE)
+        GIMarshallingTests.param_spec_in_bool(ps)
+
     def test_param_spec_return(self):
         obj = GIMarshallingTests.param_spec_return()
         self.assertEqual(obj.name, 'test-param')
@@ -2528,18 +2605,10 @@ class TestPropertiesObject(unittest.TestCase):
         obj = GIMarshallingTests.PropertiesObject(some_boolean=True)
         self.assertEqual(obj.props.some_boolean, True)
 
-    @unittest.expectedFailure
     def test_char(self):
-        # gobject-introspection thinks it has a guint8 type tag, which is
-        # wrong; this will raise an assertion critical which we need to ignore
-        old_mask = GLib.log_set_always_fatal(
-            GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_ERROR)
-        try:
-            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)
-        finally:
-            GLib.log_set_always_fatal(old_mask)
+        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)
 
         obj = GIMarshallingTests.PropertiesObject(some_char=-42)
         self.assertEqual(obj.props.some_char, -42)
@@ -2686,6 +2755,27 @@ class TestPropertiesObject(unittest.TestCase):
         obj = GIMarshallingTests.PropertiesObject(some_boxed_struct=struct1)
         self.assertEqual(obj.props.some_boxed_struct.long_, 1)
 
+    @unittest.skipUnless(hasattr(GIMarshallingTests.PropertiesObject, 'some_boxed_glist'),
+                         'too old gobject-introspection')
+    def test_boxed_glist(self):
+        self.assertEqual(self.obj.props.some_boxed_glist, [])
+
+        l = [GObject.G_MININT, 42, GObject.G_MAXINT]
+        self.obj.props.some_boxed_glist = l
+        self.assertEqual(self.obj.props.some_boxed_glist, l)
+        self.obj.props.some_boxed_glist = []
+        self.assertEqual(self.obj.props.some_boxed_glist, [])
+
+        self.assertRaises(TypeError, setattr, self.obj.props, 'some_boxed_glist', 1)
+        self.assertRaises(TypeError, setattr, self.obj.props, 'some_boxed_glist', 'foo')
+        self.assertRaises(TypeError, setattr, self.obj.props, 'some_boxed_glist', ['a'])
+
+    @unittest.expectedFailure
+    def test_boxed_glist_ctor(self):
+        l = [GObject.G_MININT, 42, GObject.G_MAXINT]
+        obj = GIMarshallingTests.PropertiesObject(some_boxed_glist=l)
+        self.assertEqual(obj.props.some_boxed_glist, l)
+
     @unittest.skipUnless(hasattr(GIMarshallingTests.PropertiesObject, 'some_variant'),
                          'too old gobject-introspection')
     def test_variant(self):
@@ -2708,6 +2798,12 @@ class TestPropertiesObject(unittest.TestCase):
         self.assertEqual(obj.props.some_variant.get_type_string(), 'b')
         self.assertEqual(obj.props.some_variant.get_boolean(), True)
 
+    def test_setting_several_properties(self):
+        obj = GIMarshallingTests.PropertiesObject()
+        obj.set_properties(some_uchar=54, some_int=42)
+        self.assertEqual(42, obj.props.some_int)
+        self.assertEqual(54, obj.props.some_uchar)
+
 
 class TestKeywords(unittest.TestCase):
     def test_method(self):
@@ -2824,3 +2920,12 @@ class TestSignatureArgs(unittest.TestCase):
     def test_overridden_doc_is_not_clobbered(self):
         self.assertEqual(GIMarshallingTests.OverridesObject.method.__doc__,
                          'Overridden doc string.')
+
+
+class TestDeprecation(unittest.TestCase):
+    def test_method(self):
+        d = GLib.Date.new()
+        with warnings.catch_warnings(record=True) as warn:
+            warnings.simplefilter('always')
+            d.set_time(1)
+            self.assertTrue(issubclass(warn[0].category, DeprecationWarning))
similarity index 60%
rename from tests/test_overrides_gio.py
rename to tests/test_gio.py
index 10d634e..57ab013 100644 (file)
@@ -119,3 +119,85 @@ class TestGSettings(unittest.TestCase):
         self.assertEqual(len(empty), 0)
         self.assertEqual(bool(empty), True)
         self.assertEqual(empty.keys(), [])
+
+    def test_change_event(self):
+        changed_log = []
+        change_event_log = []
+
+        def on_changed(settings, key):
+            changed_log.append((settings, key))
+
+        def on_change_event(settings, keys, n_keys):
+            change_event_log.append((settings, keys, n_keys))
+
+        self.settings.connect('changed', on_changed)
+        self.settings.connect('change-event', on_change_event)
+        self.settings['test-string'] = 'Moo'
+        self.assertEqual(changed_log, [(self.settings, 'test-string')])
+        self.assertEqual(change_event_log, [(self.settings,
+                                             [GLib.quark_from_static_string('test-string')],
+                                             1)])
+
+
+class TestGFile(unittest.TestCase):
+    def setUp(self):
+        self.file, self.io_stream = Gio.File.new_tmp('TestGFile.XXXXXX')
+
+    def tearDown(self):
+        try:
+            self.file.delete(None)
+            # test_delete and test_delete_async already remove it
+        except GLib.GError:
+            pass
+
+    def test_replace_contents(self):
+        content = b'hello\0world\x7F!'
+        succ, etag = self.file.replace_contents(content, None, False,
+                                                Gio.FileCreateFlags.NONE, None)
+        new_succ, new_content, new_etag = self.file.load_contents(None)
+
+        self.assertTrue(succ)
+        self.assertTrue(new_succ)
+        self.assertEqual(etag, new_etag)
+        self.assertEqual(content, new_content)
+
+    # https://bugzilla.gnome.org/show_bug.cgi?id=690525
+    def disabled_test_replace_contents_async(self):
+        content = b''.join(bytes(chr(i), 'utf-8') for i in range(128))
+
+        def callback(f, result, d):
+            # Quit so in case of failed assertations loop doesn't keep running.
+            main_loop.quit()
+            succ, etag = self.file.replace_contents_finish(result)
+            new_succ, new_content, new_etag = self.file.load_contents(None)
+            d['succ'], d['etag'] = self.file.replace_contents_finish(result)
+            load = self.file.load_contents(None)
+            d['new_succ'], d['new_content'], d['new_etag'] = load
+
+        data = {}
+        self.file.replace_contents_async(content, None, False,
+                                         Gio.FileCreateFlags.NONE, None,
+                                         callback, data)
+        main_loop = GLib.MainLoop()
+        main_loop.run()
+        self.assertTrue(data['succ'])
+        self.assertTrue(data['new_succ'])
+        self.assertEqual(data['etag'], data['new_etag'])
+        self.assertEqual(content, data['new_content'])
+
+    def test_tmp_exists(self):
+        # A simple test to check if Gio.File.new_tmp is working correctly.
+        self.assertTrue(self.file.query_exists(None))
+
+    def test_delete(self):
+        self.file.delete(None)
+        self.assertFalse(self.file.query_exists(None))
+
+    def test_delete_async(self):
+        def callback(f, result, data):
+            main_loop.quit()
+
+        self.file.delete_async(0, None, callback, None)
+        main_loop = GLib.MainLoop()
+        main_loop.run()
+        self.assertFalse(self.file.query_exists(None))
index 9ef60e4..3cde168 100644 (file)
@@ -202,5 +202,5 @@ https://my.org/q?x=1&y=2
     def test_pyglib_version(self):
         (major, minor, micro) = GLib.pyglib_version
         self.assertGreaterEqual(major, 3)
-        self.assertGreaterEqual(minor, 7)
-        self.assertGreaterEqual(micro, 2)
+        self.assertGreaterEqual(minor, 0)
+        self.assertGreaterEqual(micro, 0)
index 99f471b..ec4cb44 100644 (file)
@@ -5,7 +5,7 @@ import gc
 import unittest
 import warnings
 
-from gi.repository import GObject
+from gi.repository import GObject, GLib
 from gi import PyGIDeprecationWarning
 from gi.module import get_introspection_module
 from gi._gobject import _gobject
@@ -491,19 +491,27 @@ class TestPropertyBindings(unittest.TestCase):
         self.assertEqual(self.target.int_prop, 1)
 
     def test_transform_bidirectional(self):
+        test_data = object()
+
         def transform_to(binding, value, user_data=None):
-            self.assertEqual(user_data, 'test-data')
+            self.assertEqual(user_data, test_data)
             return value * 2
 
         def transform_from(binding, value, user_data=None):
-            self.assertEqual(user_data, 'test-data')
-            return value / 2
+            self.assertEqual(user_data, test_data)
+            return value // 2
+
+        test_data_ref_count = sys.getrefcount(test_data)
+        transform_to_ref_count = sys.getrefcount(transform_to)
+        transform_from_ref_count = sys.getrefcount(transform_from)
 
         # bidirectional bindings
         binding = self.source.bind_property('int_prop', self.target, 'int_prop',
                                             GObject.BindingFlags.BIDIRECTIONAL,
-                                            transform_to, transform_from, 'test-data')
+                                            transform_to, transform_from, test_data)
         binding = binding  # PyFlakes
+        binding_ref_count = sys.getrefcount(binding())
+        binding_gref_count = binding().__grefcount__
 
         self.source.int_prop = 1
         self.assertEqual(self.source.int_prop, 1)
@@ -513,6 +521,30 @@ class TestPropertyBindings(unittest.TestCase):
         self.assertEqual(self.source.int_prop, 2)
         self.assertEqual(self.target.int_prop, 4)
 
+        self.assertEqual(sys.getrefcount(binding()), binding_ref_count)
+        self.assertEqual(binding().__grefcount__, binding_gref_count)
+
+        # test_data ref count increases by 2, once for each callback.
+        self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2)
+        self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count + 1)
+        self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count + 1)
+
+        # Unbind should clear out the binding and its transforms
+        binding.unbind()
+        self.assertEqual(binding(), None)
+        del binding
+        gc.collect()
+
+        # Setting source or target should not change the other.
+        self.target.int_prop = 3
+        self.source.int_prop = 5
+        self.assertEqual(self.target.int_prop, 3)
+        self.assertEqual(self.source.int_prop, 5)
+
+        self.assertEqual(sys.getrefcount(test_data), test_data_ref_count)
+        self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count)
+        self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count)
+
     def test_explicit_unbind_clears_connection(self):
         self.assertEqual(self.source.int_prop, 0)
         self.assertEqual(self.target.int_prop, 0)
@@ -563,5 +595,68 @@ class TestPropertyBindings(unittest.TestCase):
         self.assertEqual(ref(), None)
         self.assertEqual(binding(), None)
 
+
+class TestGValue(unittest.TestCase):
+    def test_type_constant(self):
+        self.assertEqual(GObject.TYPE_VALUE, GObject.Value.__gtype__)
+        self.assertEqual(GObject.type_name(GObject.TYPE_VALUE), 'GValue')
+
+    def test_no_type(self):
+        value = GObject.Value()
+        self.assertEqual(value.g_type, GObject.TYPE_INVALID)
+        self.assertRaises(TypeError, value.set_value, 23)
+        self.assertEqual(value.get_value(), None)
+
+    def test_int(self):
+        value = GObject.Value(GObject.TYPE_UINT)
+        self.assertEqual(value.g_type, GObject.TYPE_UINT)
+        value.set_value(23)
+        self.assertEqual(value.get_value(), 23)
+        value.set_value(42.0)
+        self.assertEqual(value.get_value(), 42)
+
+    def test_string(self):
+        value = GObject.Value(str, 'foo_bar')
+        self.assertEqual(value.g_type, GObject.TYPE_STRING)
+        self.assertEqual(value.get_value(), 'foo_bar')
+
+    def test_float(self):
+        # python float is G_TYPE_DOUBLE
+        value = GObject.Value(float, 23.4)
+        self.assertEqual(value.g_type, GObject.TYPE_DOUBLE)
+        value.set_value(1e50)
+        self.assertAlmostEqual(value.get_value(), 1e50)
+
+        value = GObject.Value(GObject.TYPE_FLOAT, 23.4)
+        self.assertEqual(value.g_type, GObject.TYPE_FLOAT)
+        self.assertRaises(TypeError, value.set_value, 'string')
+        self.assertRaises(ValueError, value.set_value, 1e50)
+
+    def test_float_inf_nan(self):
+        nan = float('nan')
+        for type_ in [GObject.TYPE_FLOAT, GObject.TYPE_DOUBLE]:
+            for x in [float('inf'), float('-inf'), nan]:
+                value = GObject.Value(type_, x)
+                # assertEqual() is False for (nan, nan)
+                if x is nan:
+                    self.assertEqual(str(value.get_value()), 'nan')
+                else:
+                    self.assertEqual(value.get_value(), x)
+
+    def test_enum(self):
+        value = GObject.Value(GLib.FileError, GLib.FileError.FAILED)
+        self.assertEqual(value.get_value(), GLib.FileError.FAILED)
+
+    def test_flags(self):
+        value = GObject.Value(GLib.IOFlags, GLib.IOFlags.IS_READABLE)
+        self.assertEqual(value.get_value(), GLib.IOFlags.IS_READABLE)
+
+    def test_object(self):
+        class TestObject(GObject.Object):
+            pass
+        obj = TestObject()
+        value = GObject.Value(GObject.TYPE_OBJECT, obj)
+        self.assertEqual(value.get_value(), obj)
+
 if __name__ == '__main__':
     unittest.main()
index dec716e..8099101 100644 (file)
@@ -37,15 +37,13 @@ class TestTypeModuleLevelFunctions(unittest.TestCase):
         self.assertRaises(TypeError, GObject.type_is_a, 1, 2)
 
     def test_type_children(self):
-        self.assertSequenceEqual(GObject.type_children(CustomBase),
-                                 [CustomChild.__gtype__])
+        self.assertEqual(GObject.type_children(CustomBase), [CustomChild.__gtype__])
         self.assertEqual(len(GObject.type_children(CustomChild)), 0)
 
     def test_type_interfaces(self):
         self.assertEqual(len(GObject.type_interfaces(CustomBase)), 0)
         self.assertEqual(len(GObject.type_interfaces(CustomChild)), 1)
-        self.assertSequenceEqual(GObject.type_interfaces(CustomChild),
-                                 [GIMarshallingTests.Interface.__gtype__])
+        self.assertEqual(GObject.type_interfaces(CustomChild), [GIMarshallingTests.Interface.__gtype__])
 
     def test_type_parent(self):
         self.assertEqual(GObject.type_parent(CustomChild), CustomBase.__gtype__)
diff --git a/tests/test_object_marshaling.py b/tests/test_object_marshaling.py
new file mode 100644 (file)
index 0000000..2432b44
--- /dev/null
@@ -0,0 +1,617 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# vim: tabstop=4 shiftwidth=4 expandtab
+
+import unittest
+import weakref
+import gc
+import sys
+import warnings
+
+from gi.repository import GObject
+from gi.repository import GIMarshallingTests
+
+
+class StrongRef(object):
+    # A class that behaves like weakref.ref but holds a strong reference.
+    # This allows re-use of the VFuncsBase by swapping out the ObjectRef
+    # class var with either weakref.ref or StrongRef.
+
+    def __init__(self, obj):
+        self.obj = obj
+
+    def __call__(self):
+        return self.obj
+
+
+class VFuncsBase(GIMarshallingTests.Object):
+    # Class which generically implements the vfuncs used for reference counting tests
+    # in a way that can be easily sub-classed and modified.
+
+    #: Object type used by this class for testing
+    #: This can be GObject.Object or GObject.InitiallyUnowned
+    Object = GObject.Object
+
+    #: Reference type used by this class for holding refs to in/out objects.
+    #: This can be set to weakref.ref or StrongRef
+    ObjectRef = weakref.ref
+
+    def __init__(self):
+        super(VFuncsBase, self).__init__()
+
+        #: Hold ref of input or output python wrappers
+        self.object_ref = None
+
+        #: store grefcount of input object
+        self.in_object_grefcount = None
+        self.in_object_is_floating = None
+
+    def do_vfunc_return_object_transfer_none(self):
+        # Return an object but keep a python reference to it.
+        obj = self.Object()
+        self.object_ref = self.ObjectRef(obj)
+        return obj
+
+    def do_vfunc_return_object_transfer_full(self):
+        # Return an object and hand off the reference to the caller.
+        obj = self.Object()
+        self.object_ref = self.ObjectRef(obj)
+        return obj
+
+    def do_vfunc_out_object_transfer_none(self):
+        # Same as do_vfunc_return_object_transfer_none but the pygi
+        # internals convert the return here into an out arg.
+        obj = self.Object()
+        self.object_ref = self.ObjectRef(obj)
+        return obj
+
+    def do_vfunc_out_object_transfer_full(self):
+        # Same as do_vfunc_return_object_transfer_full but the pygi
+        # internals convert the return here into an out arg.
+        obj = self.Object()
+        self.object_ref = self.ObjectRef(obj)
+        return obj
+
+    def do_vfunc_in_object_transfer_none(self, obj):
+        # 'obj' will have a python wrapper as well as still held
+        # by the caller.
+        self.object_ref = self.ObjectRef(obj)
+        self.in_object_grefcount = obj.__grefcount__
+        self.in_object_is_floating = obj.is_floating()
+
+    def do_vfunc_in_object_transfer_full(self, obj):
+        # 'obj' will now be owned by the Python GObject wrapper.
+        # When obj goes out of scope and is collected, the GObject
+        # should also be fully released.
+        self.object_ref = self.ObjectRef(obj)
+        self.in_object_grefcount = obj.__grefcount__
+        self.in_object_is_floating = obj.is_floating()
+
+
+@unittest.skipUnless(hasattr(VFuncsBase, 'get_ref_info_for_vfunc_return_object_transfer_none') and
+                     hasattr(VFuncsBase, 'get_ref_info_for_vfunc_out_object_transfer_none'),
+                     'too old gobject-introspection')
+class TestVFuncsWithObjectArg(unittest.TestCase):
+    # Basic set of tests which work on non-floating objects which python does
+    # not keep an additional reference of.
+
+    class VFuncs(VFuncsBase):
+        # Object for testing non-floating objects without holding any refs.
+        Object = GObject.Object
+        ObjectRef = weakref.ref
+
+    def test_vfunc_self_arg_ref_count(self):
+        # Check to make sure vfunc "self" arguments don't leak.
+        vfuncs = self.VFuncs()
+        vfuncs_ref = weakref.ref(vfuncs)
+        vfuncs.get_ref_info_for_vfunc_return_object_transfer_full()  # Use any vfunc to test this.
+
+        gc.collect()
+        self.assertEqual(sys.getrefcount(vfuncs), 2)
+        self.assertEqual(vfuncs.__grefcount__, 1)
+
+        del vfuncs
+        gc.collect()
+        self.assertTrue(vfuncs_ref() is None)
+
+    def test_vfunc_return_object_transfer_none(self):
+        # This tests a problem case where the vfunc returns a GObject owned solely by Python
+        # but the argument is marked as transfer-none.
+        # In this case pygobject marshaling adds an additional ref and gives a warning
+        # of a potential leak. If this occures it is really a bug in the underlying library
+        # but pygobject tries to react to this in a reasonable way.
+        vfuncs = self.VFuncs()
+        with warnings.catch_warnings(record=True) as warn:
+            warnings.simplefilter('always')
+            ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_none()
+            self.assertTrue(issubclass(warn[0].category, RuntimeWarning))
+
+        # The ref count of the GObject returned to the caller (get_ref_info_for_vfunc_return_object_transfer_none)
+        # should be a single floating ref
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_out_object_transfer_none(self):
+        # Same as above except uses out arg instead of return
+        vfuncs = self.VFuncs()
+        with warnings.catch_warnings(record=True) as warn:
+            warnings.simplefilter('always')
+            ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_none()
+            self.assertTrue(issubclass(warn[0].category, RuntimeWarning))
+
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_return_object_transfer_full(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_return_object_transfer_full()
+
+        # The vfunc caller receives full ownership of a single ref which should not
+        # be floating.
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_out_object_transfer_full(self):
+        # Same as above except uses out arg instead of return
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_full()
+
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_in_object_transfer_none(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none(self.VFuncs.Object)
+
+        gc.collect()
+        self.assertEqual(vfuncs.in_object_grefcount, 2)  # initial + python wrapper
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        self.assertEqual(ref_count, 1)  # ensure python wrapper released
+        self.assertFalse(is_floating)
+
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_in_object_transfer_full(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full(self.VFuncs.Object)
+
+        gc.collect()
+
+        # python wrapper should take sole ownership of the gobject
+        self.assertEqual(vfuncs.in_object_grefcount, 1)
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        # ensure python wrapper took ownership and released, after vfunc was complete
+        self.assertEqual(ref_count, 0)
+        self.assertFalse(is_floating)
+
+        self.assertTrue(vfuncs.object_ref() is None)
+
+
+@unittest.skipUnless(hasattr(VFuncsBase, 'get_ref_info_for_vfunc_return_object_transfer_none') and
+                     hasattr(VFuncsBase, 'get_ref_info_for_vfunc_out_object_transfer_none'),
+                     'too old gobject-introspection')
+class TestVFuncsWithFloatingArg(unittest.TestCase):
+    # All tests here work with a floating object by using InitiallyUnowned as the argument
+
+    class VFuncs(VFuncsBase):
+        # Object for testing non-floating objects without holding any refs.
+        Object = GObject.InitiallyUnowned
+        ObjectRef = weakref.ref
+
+    def test_vfunc_return_object_transfer_none_with_floating(self):
+        # Python is expected to return a single floating reference without warning.
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_return_object_transfer_none()
+
+        # The ref count of the GObject returned to the caller (get_ref_info_for_vfunc_return_object_transfer_none)
+        # should be a single floating ref
+        self.assertEqual(ref_count, 1)
+        self.assertTrue(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_out_object_transfer_none_with_floating(self):
+        # Same as above except uses out arg instead of return
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_none()
+
+        self.assertEqual(ref_count, 1)
+        self.assertTrue(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_return_object_transfer_full_with_floating(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_return_object_transfer_full()
+
+        # The vfunc caller receives full ownership of a single ref.
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_out_object_transfer_full_with_floating(self):
+        # Same as above except uses out arg instead of return
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_full()
+
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        gc.collect()
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_in_object_transfer_none_with_floating(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none(self.VFuncs.Object)
+
+        gc.collect()
+
+        # python wrapper should maintain the object as floating and add an additional ref
+        self.assertEqual(vfuncs.in_object_grefcount, 2)
+        self.assertTrue(vfuncs.in_object_is_floating)
+
+        # vfunc caller should only have a single floating ref after the vfunc finishes
+        self.assertEqual(ref_count, 1)
+        self.assertTrue(is_floating)
+
+        self.assertTrue(vfuncs.object_ref() is None)
+
+    def test_vfunc_in_object_transfer_full_with_floating(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full(self.VFuncs.Object)
+
+        gc.collect()
+
+        # python wrapper sinks and owns the gobject
+        self.assertEqual(vfuncs.in_object_grefcount, 1)
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        # ensure python wrapper took ownership and released
+        self.assertEqual(ref_count, 0)
+        self.assertFalse(is_floating)
+
+        self.assertTrue(vfuncs.object_ref() is None)
+
+
+@unittest.skipUnless(hasattr(VFuncsBase, 'get_ref_info_for_vfunc_return_object_transfer_none') and
+                     hasattr(VFuncsBase, 'get_ref_info_for_vfunc_out_object_transfer_none'),
+                     'too old gobject-introspection')
+class TestVFuncsWithHeldObjectArg(unittest.TestCase):
+    # Same tests as TestVFuncsWithObjectArg except we hold
+    # onto the python object reference in all cases.
+
+    class VFuncs(VFuncsBase):
+        # Object for testing non-floating objects with a held ref.
+        Object = GObject.Object
+        ObjectRef = StrongRef
+
+    def test_vfunc_return_object_transfer_none_with_held_object(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_return_object_transfer_none()
+
+        # Python holds the single gobject ref in 'vfuncs.object_ref'
+        # Because of this, we do not expect a floating ref or a ref increase.
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        # The actual grefcount should stay at 1 even after the vfunc return.
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref)
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_out_object_transfer_none_with_held_object(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_none()
+
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref)
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_return_object_transfer_full_with_held_object(self):
+        # The vfunc caller receives full ownership which should not
+        # be floating. However, the held python wrapper also has a ref.
+
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_return_object_transfer_full()
+
+        # Ref count from the perspective of C after the vfunc is called
+        # The vfunc caller receives a new reference which should not
+        # be floating. However, the held python wrapper also has a ref.
+        self.assertEqual(ref_count, 2)
+        self.assertFalse(is_floating)
+
+        # Current ref count
+        # The vfunc caller should have decremented its reference.
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref)
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_out_object_transfer_full_with_held_object(self):
+        # Same test as above except uses out arg instead of return
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_full()
+
+        # Ref count from the perspective of C after the vfunc is called
+        # The vfunc caller receives a new reference which should not
+        # be floating. However, the held python wrapper also has a ref.
+        self.assertEqual(ref_count, 2)
+        self.assertFalse(is_floating)
+
+        # Current ref count
+        # The vfunc caller should have decremented its reference.
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref())
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_in_object_transfer_none_with_held_object(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none(self.VFuncs.Object)
+
+        gc.collect()
+
+        # Ref count inside vfunc from the perspective of Python
+        self.assertEqual(vfuncs.in_object_grefcount, 2)  # initial + python wrapper
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        # Ref count from the perspective of C after the vfunc is called
+        self.assertEqual(ref_count, 2)  # kept after vfunc + held python wrapper
+        self.assertFalse(is_floating)
+
+        # Current ref count after C cleans up its reference
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref())
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_in_object_transfer_full_with_held_object(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full(self.VFuncs.Object)
+
+        gc.collect()
+
+        # Ref count inside vfunc from the perspective of Python
+        self.assertEqual(vfuncs.in_object_grefcount, 1)  # python wrapper takes ownership of the gobject
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        # Ref count from the perspective of C after the vfunc is called
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        # Current ref count
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref())
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+
+@unittest.skipUnless(hasattr(VFuncsBase, 'get_ref_info_for_vfunc_return_object_transfer_none') and
+                     hasattr(VFuncsBase, 'get_ref_info_for_vfunc_out_object_transfer_none'),
+                     'too old gobject-introspection')
+class TestVFuncsWithHeldFloatingArg(unittest.TestCase):
+    # Tests for a floating object which we hold a reference to the python wrapper
+    # on the VFuncs test class.
+
+    class VFuncs(VFuncsBase):
+        # Object for testing floating objects with a held ref.
+        Object = GObject.InitiallyUnowned
+        ObjectRef = StrongRef
+
+    def test_vfunc_return_object_transfer_none_with_held_floating(self):
+        # Python holds onto the wrapper which basically means the floating ref
+        # should also be owned by python.
+
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_return_object_transfer_none()
+
+        # This is a borrowed ref from what is held in python.
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        # The actual grefcount should stay at 1 even after the vfunc return.
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref)
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_out_object_transfer_none_with_held_floating(self):
+        # Same as above
+
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_none()
+
+        self.assertEqual(ref_count, 1)
+        self.assertFalse(is_floating)
+
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref)
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_return_object_transfer_full_with_held_floating(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_return_object_transfer_full()
+
+        # Ref count from the perspective of C after the vfunc is called
+        self.assertEqual(ref_count, 2)
+        self.assertFalse(is_floating)
+
+        # Current ref count
+        # vfunc wrapper destroyes ref it was given
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref)
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_out_object_transfer_full_with_held_floating(self):
+        # Same test as above except uses out arg instead of return
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_out_object_transfer_full()
+
+        # Ref count from the perspective of C after the vfunc is called
+        self.assertEqual(ref_count, 2)
+        self.assertFalse(is_floating)
+
+        # Current ref count
+        # vfunc wrapper destroyes ref it was given
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref())
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_in_floating_transfer_none_with_held_floating(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_none(self.VFuncs.Object)
+        gc.collect()
+
+        # Ref count inside vfunc from the perspective of Python
+        self.assertTrue(vfuncs.in_object_is_floating)
+        self.assertEqual(vfuncs.in_object_grefcount, 2)  # python wrapper sinks and owns the gobject
+
+        # Ref count from the perspective of C after the vfunc is called
+        self.assertTrue(is_floating)
+        self.assertEqual(ref_count, 2)  # floating + held by wrapper
+
+        # Current ref count after C cleans up its reference
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref())
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+    def test_vfunc_in_floating_transfer_full_with_held_floating(self):
+        vfuncs = self.VFuncs()
+        ref_count, is_floating = vfuncs.get_ref_info_for_vfunc_in_object_transfer_full(self.VFuncs.Object)
+        gc.collect()
+
+        # Ref count from the perspective of C after the vfunc is called
+        self.assertEqual(vfuncs.in_object_grefcount, 1)  # python wrapper sinks and owns the gobject
+        self.assertFalse(vfuncs.in_object_is_floating)
+
+        # Ref count from the perspective of C after the vfunc is called
+        self.assertEqual(ref_count, 1)  # held by wrapper
+        self.assertFalse(is_floating)
+
+        # Current ref count
+        self.assertEqual(vfuncs.object_ref().__grefcount__, 1)
+
+        held_object_ref = weakref.ref(vfuncs.object_ref())
+        del vfuncs.object_ref
+        gc.collect()
+        self.assertTrue(held_object_ref() is None)
+
+
+@unittest.skipUnless(hasattr(GIMarshallingTests.PropertiesObject.props, 'some_object'),
+                     'too old gobject-introspection')
+class TestPropertyHoldingObject(unittest.TestCase):
+    def test_props_getter_holding_object_ref_count(self):
+        holder = GIMarshallingTests.PropertiesObject()
+        held = GObject.Object()
+
+        self.assertEqual(holder.__grefcount__, 1)
+        self.assertEqual(held.__grefcount__, 1)
+
+        holder.set_property('some-object', held)
+        self.assertEqual(holder.__grefcount__, 1)
+
+        initial_ref_count = held.__grefcount__
+        holder.props.some_object
+        gc.collect()
+        self.assertEqual(held.__grefcount__, initial_ref_count)
+
+    def test_get_property_holding_object_ref_count(self):
+        holder = GIMarshallingTests.PropertiesObject()
+        held = GObject.Object()
+
+        self.assertEqual(holder.__grefcount__, 1)
+        self.assertEqual(held.__grefcount__, 1)
+
+        holder.set_property('some-object', held)
+        self.assertEqual(holder.__grefcount__, 1)
+
+        initial_ref_count = held.__grefcount__
+        holder.get_property('some-object')
+        gc.collect()
+        self.assertEqual(held.__grefcount__, initial_ref_count)
+
+    def test_props_setter_holding_object_ref_count(self):
+        holder = GIMarshallingTests.PropertiesObject()
+        held = GObject.Object()
+
+        self.assertEqual(holder.__grefcount__, 1)
+        self.assertEqual(held.__grefcount__, 1)
+
+        # Setting property should only increase ref count by 1
+        holder.props.some_object = held
+        self.assertEqual(holder.__grefcount__, 1)
+        self.assertEqual(held.__grefcount__, 2)
+
+        # Clearing should pull it back down
+        holder.props.some_object = None
+        self.assertEqual(held.__grefcount__, 1)
+
+    def test_set_property_holding_object_ref_count(self):
+        holder = GIMarshallingTests.PropertiesObject()
+        held = GObject.Object()
+
+        self.assertEqual(holder.__grefcount__, 1)
+        self.assertEqual(held.__grefcount__, 1)
+
+        # Setting property should only increase ref count by 1
+        holder.set_property('some-object', held)
+        self.assertEqual(holder.__grefcount__, 1)
+        self.assertEqual(held.__grefcount__, 2)
+
+        # Clearing should pull it back down
+        holder.set_property('some-object', None)
+        self.assertEqual(held.__grefcount__, 1)
+
+    def test_set_object_property_to_invalid_type(self):
+        obj = GIMarshallingTests.PropertiesObject()
+        self.assertRaises(TypeError, obj.set_property, 'some-object', 'not_an_object')
index 070acb8..46f0a38 100644 (file)
@@ -117,3 +117,25 @@ class TestGdk(unittest.TestCase):
 
         self.assertNotEqual(c, None)
         self.assertRaises(ValueError, Gdk.Cursor, 1, 2, 3)
+
+    def test_flags(self):
+        self.assertEqual(Gdk.ModifierType.META_MASK | 0, 0x10000000)
+        self.assertEqual(hex(Gdk.ModifierType.META_MASK), '0x10000000')
+        self.assertEqual(str(Gdk.ModifierType.META_MASK),
+                         '<flags GDK_META_MASK of type GdkModifierType>')
+
+        self.assertEqual(Gdk.ModifierType.RELEASE_MASK | 0, 0x40000000)
+        self.assertEqual(hex(Gdk.ModifierType.RELEASE_MASK), '0x40000000')
+        self.assertEqual(str(Gdk.ModifierType.RELEASE_MASK),
+                         '<flags GDK_RELEASE_MASK of type GdkModifierType>')
+
+        self.assertEqual(Gdk.ModifierType.RELEASE_MASK | Gdk.ModifierType.META_MASK, 0x50000000)
+        self.assertEqual(str(Gdk.ModifierType.RELEASE_MASK | Gdk.ModifierType.META_MASK),
+                         '<flags GDK_META_MASK | GDK_RELEASE_MASK of type GdkModifierType>')
+
+    def test_color_parse(self):
+        c = Gdk.color_parse('#00FF80')
+        self.assertEqual(c.red, 0)
+        self.assertEqual(c.green, 65535)
+        self.assertEqual(c.blue, 32896)
+        self.assertEqual(Gdk.color_parse('bogus'), None)
index 3799454..4d7e63a 100644 (file)
@@ -272,6 +272,14 @@ class TestGVariant(unittest.TestCase):
         res = GLib.Variant('a{si}', {'key1': 1, 'key2': 2}).unpack()
         self.assertEqual(res, {'key1': 1, 'key2': 2})
 
+        # maybe
+        v = GLib.Variant.new_maybe(GLib.VariantType.new('i'), GLib.Variant('i', 1))
+        res = v.unpack()
+        self.assertEqual(res, 1)
+        v = GLib.Variant.new_maybe(GLib.VariantType.new('i'), None)
+        res = v.unpack()
+        self.assertEqual(res, None)
+
     def test_iteration(self):
         # array index access
         vb = GLib.VariantBuilder.new(gi._gi.variant_type_from_string('ai'))
@@ -463,6 +471,19 @@ class TestGVariant(unittest.TestCase):
         assert_equals_bool('v', GLib.Variant('i', 1))
 
     def test_repr(self):
+        # with C constructor
+        v = GLib.Variant.new_uint32(42)
+        self.assertEqual(repr(v), "GLib.Variant('u', 42)")
+
+        # with override constructor
         v = GLib.Variant('(is)', (1, 'somestring'))
-        self.assertEqual(str(v), "(1, 'somestring')")
         self.assertEqual(repr(v), "GLib.Variant('(is)', (1, 'somestring'))")
+
+    def test_str(self):
+        # with C constructor
+        v = GLib.Variant.new_uint32(42)
+        self.assertEqual(str(v), 'uint32 42')
+
+        # with override constructor
+        v = GLib.Variant('(is)', (1, 'somestring'))
+        self.assertEqual(str(v), "(1, 'somestring')")
index 7ed8344..fdb3ccb 100644 (file)
@@ -1,7 +1,11 @@
 # -*- Mode: Python; py-indent-offset: 4 -*-
+# coding: UTF-8
 # vim: tabstop=4 shiftwidth=4 expandtab
 
+import contextlib
 import unittest
+import time
+import sys
 
 from compathelper import _unicode, _bytes
 
@@ -16,6 +20,38 @@ except ImportError:
     Gtk = None
 
 
+@contextlib.contextmanager
+def realized(widget):
+    """Makes sure the widget is realized.
+
+    view = Gtk.TreeView()
+    with realized(view):
+        do_something(view)
+    """
+
+    if isinstance(widget, Gtk.Window):
+        toplevel = widget
+    else:
+        toplevel = widget.get_parent_window()
+
+    if toplevel is None:
+        window = Gtk.Window()
+        window.add(widget)
+
+    widget.realize()
+    while Gtk.events_pending():
+        Gtk.main_iteration()
+    assert widget.get_realized()
+    yield widget
+
+    if toplevel is None:
+        window.remove(widget)
+        window.destroy()
+
+    while Gtk.events_pending():
+        Gtk.main_iteration()
+
+
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestGtk(unittest.TestCase):
     def test_container(self):
@@ -114,6 +150,12 @@ class TestGtk(unittest.TestCase):
         self.assertEqual(ag, groups[-2])
         self.assertEqual(ag2, groups[-1])
 
+    def test_uimanager_nonascii(self):
+        ui = Gtk.UIManager()
+        ui.add_ui_from_string(b'<ui><menubar name="menub\xc3\xa6r1" /></ui>'.decode('UTF-8'))
+        mi = ui.get_widget("/menubær1")
+        self.assertEqual(type(mi), Gtk.MenuBar)
+
     def test_builder(self):
         self.assertEqual(Gtk.Builder, gi.overrides.Gtk.Builder)
 
@@ -512,6 +554,38 @@ class TestGtk(unittest.TestCase):
         self.assertTrue(hasattr(widget.drag_dest_set_proxy, '__call__'))
         self.assertTrue(hasattr(widget.drag_get_data, '__call__'))
 
+    def test_drag_target_list(self):
+        mixed_target_list = [Gtk.TargetEntry.new('test0', 0, 0),
+                             ('test1', 1, 1),
+                             Gtk.TargetEntry.new('test2', 2, 2),
+                             ('test3', 3, 3)]
+
+        def _test_target_list(targets):
+            for i, target in enumerate(targets):
+                self.assertTrue(isinstance(target, Gtk.TargetEntry))
+                self.assertEqual(target.target, 'test' + str(i))
+                self.assertEqual(target.flags, i)
+                self.assertEqual(target.info, i)
+
+        _test_target_list(Gtk._construct_target_list(mixed_target_list))
+
+        widget = Gtk.Button()
+        widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY)
+        widget.drag_dest_set_target_list(mixed_target_list)
+        widget.drag_dest_get_target_list()
+
+        widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE)
+        widget.drag_source_set_target_list(mixed_target_list)
+        widget.drag_source_get_target_list()
+
+        treeview = Gtk.TreeView()
+        treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
+                                          mixed_target_list,
+                                          Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
+
+        treeview.enable_model_drag_dest(mixed_target_list,
+                                        Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
+
     def test_scrollbar(self):
         # PyGTK compat
         adjustment = Gtk.Adjustment()
@@ -566,6 +640,21 @@ class TestGtk(unittest.TestCase):
         self.assertEqual(viewport.props.vadjustment, vadjustment)
         self.assertEqual(viewport.props.hadjustment, hadjustment)
 
+    def test_stock_lookup(self):
+        l = Gtk.stock_lookup('gtk-ok')
+        self.assertEqual(type(l), Gtk.StockItem)
+        self.assertEqual(l.stock_id, 'gtk-ok')
+        self.assertEqual(Gtk.stock_lookup('nosuchthing'), None)
+
+    def test_gtk_main(self):
+        # with no arguments
+        GLib.timeout_add(100, Gtk.main_quit)
+        Gtk.main()
+
+        # overridden function ignores its arguments
+        GLib.timeout_add(100, Gtk.main_quit, 'hello')
+        Gtk.main()
+
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestTreeModel(unittest.TestCase):
@@ -1300,7 +1389,65 @@ class TestTreeModel(unittest.TestCase):
         def set_row3():
             model[0][:2] = ("0", 0)
 
-        self.assertRaises(ValueError, set_row3)
+        self.assertRaises(TypeError, set_row3)
+
+    def test_tree_model_set_value_to_none(self):
+        # Tests allowing the usage of None to set an empty value on a model.
+        store = Gtk.ListStore(str)
+        row = store.append(['test'])
+        self.assertSequenceEqual(store[0][:], ['test'])
+        store.set_value(row, 0, None)
+        self.assertSequenceEqual(store[0][:], [None])
+
+    def test_signal_emission_tree_path_coerce(self):
+        class Model(GObject.Object, Gtk.TreeModel):
+            pass
+
+        model = Model()
+        tree_paths = []
+
+        def on_any_signal(model, path, *args):
+            tree_paths.append(path.to_string())
+
+        model.connect('row-changed', on_any_signal)
+        model.connect('row-deleted', on_any_signal)
+        model.connect('row-has-child-toggled', on_any_signal)
+        model.connect('row-inserted', on_any_signal)
+
+        model.row_changed('0', Gtk.TreeIter())
+        self.assertEqual(tree_paths[-1], '0')
+
+        model.row_deleted('1')
+        self.assertEqual(tree_paths[-1], '1')
+
+        model.row_has_child_toggled('2', Gtk.TreeIter())
+        self.assertEqual(tree_paths[-1], '2')
+
+        model.row_inserted('3', Gtk.TreeIter())
+        self.assertEqual(tree_paths[-1], '3')
+
+    def test_tree_model_filter(self):
+        model = Gtk.ListStore(int, str, float)
+        model.append([1, "one", -0.1])
+        model.append([2, "two", -0.2])
+
+        filtered = Gtk.TreeModelFilter(child_model=model)
+
+        self.assertEqual(filtered[0][1], 'one')
+        filtered[0][1] = 'ONE'
+        self.assertEqual(filtered[0][1], 'ONE')
+
+    def test_list_store_performance(self):
+        model = Gtk.ListStore(int, str)
+
+        iterations = 2000
+        start = time.clock()
+        i = iterations
+        while i > 0:
+            model.append([1, 'hello'])
+            i -= 1
+        end = time.clock()
+        sys.stderr.write('[%.0f µs/append] ' % ((end - start) * 1000000 / iterations))
 
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
@@ -1310,19 +1457,13 @@ class TestTreeView(unittest.TestCase):
         store.append((0, "foo"))
         store.append((1, "bar"))
         view = Gtk.TreeView()
-        # FIXME: We can't easily call get_cursor() to make sure this works as
-        # expected as we need to realize and focus the column; the following
-        # will raise a Gtk-CRITICAL which we ignore for now
-        old_mask = GLib.log_set_always_fatal(
-            GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_ERROR)
-        try:
+
+        with realized(view):
             view.set_cursor(store[1].path)
             view.set_cursor(str(store[1].path))
 
             view.get_cell_area(store[1].path)
             view.get_cell_area(str(store[1].path))
-        finally:
-            GLib.log_set_always_fatal(old_mask)
 
     def test_tree_view_column(self):
         cell = Gtk.CellRendererText()
@@ -1350,26 +1491,21 @@ class TestTreeView(unittest.TestCase):
         # unconnected
         tree.insert_column_with_attributes(-1, 'Head4', cell4)
 
-        # might cause a Pango warning, do not break on this
-        old_mask = GLib.log_set_always_fatal(
-            GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
-        try:
-            # causes the widget to get realized and cellN.props.text receive a
-            # value, otherwise it will be None.
-            tree.get_preferred_size()
-        finally:
-            GLib.log_set_always_fatal(old_mask)
+        with realized(tree):
+            tree.set_cursor(model[0].path)
+            while Gtk.events_pending():
+                Gtk.main_iteration()
 
-        self.assertEqual(tree.get_column(0).get_title(), 'Head1')
-        self.assertEqual(tree.get_column(1).get_title(), 'Head2')
-        self.assertEqual(tree.get_column(2).get_title(), 'Head3')
-        self.assertEqual(tree.get_column(3).get_title(), 'Head4')
+            self.assertEqual(tree.get_column(0).get_title(), 'Head1')
+            self.assertEqual(tree.get_column(1).get_title(), 'Head2')
+            self.assertEqual(tree.get_column(2).get_title(), 'Head3')
+            self.assertEqual(tree.get_column(3).get_title(), 'Head4')
 
-        # cursor should be at the first row
-        self.assertEqual(cell1.props.text, 'cell11')
-        self.assertEqual(cell2.props.text, 'cell12')
-        self.assertEqual(cell3.props.text, 'cell13')
-        self.assertEqual(cell4.props.text, None)
+            # cursor should be at the first row
+            self.assertEqual(cell1.props.text, 'cell11')
+            self.assertEqual(cell2.props.text, 'cell12')
+            self.assertEqual(cell3.props.text, 'cell13')
+            self.assertEqual(cell4.props.text, None)
 
     def test_tree_view_column_set_attributes(self):
         store = Gtk.ListStore(int, str)
@@ -1387,17 +1523,8 @@ class TestTreeView(unittest.TestCase):
         column.pack_start(cell, expand=True)
         column.set_attributes(cell, text=1)
 
-        # might cause a Pango warning, do not break on this
-        old_mask = GLib.log_set_always_fatal(
-            GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
-        try:
-            # This will make cell.props.text receive a value, otherwise it
-            # will be None.
-            treeview.get_preferred_size()
-        finally:
-            GLib.log_set_always_fatal(old_mask)
-
-        self.assertTrue(cell.props.text in directors)
+        with realized(treeview):
+            self.assertTrue(cell.props.text in directors)
 
     def test_tree_selection(self):
         store = Gtk.ListStore(int, str)
index fe286e2..4b128f3 100644 (file)
@@ -541,6 +541,24 @@ class TestProperty(unittest.TestCase):
         self.assertEqual(o.value, 'blah')
         self.assertEqual(o.props.value, 'blah')
 
+    def test_decorator_private_setter(self):
+        class C(GObject.GObject):
+            _value = 'value'
+
+            @GObject.Property
+            def value(self):
+                return self._value
+
+            @value.setter
+            def _set_value(self, value):
+                self._value = value
+
+        o = C()
+        self.assertEqual(o.value, 'value')
+        o.value = 'blah'
+        self.assertEqual(o.value, 'blah')
+        self.assertEqual(o.props.value, 'blah')
+
     def test_decorator_with_call(self):
         class C(GObject.GObject):
             _value = 1
@@ -571,7 +589,6 @@ class TestProperty(unittest.TestCase):
         self.assertRaises(TypeError, GObject.Property, type=bool)
         self.assertRaises(TypeError, GObject.Property, type=object, default=0)
         self.assertRaises(TypeError, GObject.Property, type=complex)
-        self.assertRaises(TypeError, GObject.Property, flags=-10)
 
     def test_defaults(self):
         GObject.Property(type=bool, default=True)
@@ -697,7 +714,7 @@ class TestProperty(unittest.TestCase):
         self.assertEqual(b.prop1, 20)
 
     def test_property_subclass_c(self):
-        class A(GIMarshallingTests.PropertiesObject):
+        class A(Regress.TestSubObj):
             prop1 = GObject.Property(type=int)
 
         a = A()
@@ -705,8 +722,15 @@ class TestProperty(unittest.TestCase):
         self.assertEqual(a.prop1, 10)
 
         # also has parent properties
-        a.props.some_int = 20
-        self.assertEqual(a.props.some_int, 20)
+        a.props.int = 20
+        self.assertEqual(a.props.int, 20)
+
+        # Some of which are unusable without introspection
+        a.props.list = ("str1", "str2")
+        self.assertEqual(a.props.list, ["str1", "str2"])
+
+        a.set_property("list", ("str3", "str4"))
+        self.assertEqual(a.props.list, ["str3", "str4"])
 
     def test_property_subclass_custom_setter(self):
         # test for #523352
index fc8c835..776ad7a 100644 (file)
@@ -120,7 +120,9 @@ class Foo(GObject.GObject):
         'my-acc-signal': (GObject.SignalFlags.RUN_LAST, GObject.TYPE_INT,
                           (), my_accumulator, "accum data"),
         'my-other-acc-signal': (GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN,
-                                (), GObject.signal_accumulator_true_handled)
+                                (), GObject.signal_accumulator_true_handled),
+        'my-acc-first-wins': (GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN,
+                              (), GObject.signal_accumulator_first_wins)
         }
 
 
@@ -148,6 +150,16 @@ class TestAccumulator(unittest.TestCase):
         inst.emit("my-other-acc-signal")
         self.assertEqual(self.__true_val, 2)
 
+    def test_accumulator_first_wins(self):
+        # First signal hit will always win
+        inst = Foo()
+        inst.connect("my-acc-first-wins", self._true_handler3)
+        inst.connect("my-acc-first-wins", self._true_handler1)
+        inst.connect("my-acc-first-wins", self._true_handler2)
+        self.__true_val = None
+        inst.emit("my-acc-first-wins")
+        self.assertEqual(self.__true_val, 3)
+
     def _true_handler1(self, obj):
         self.__true_val = 1
         return False
@@ -165,6 +177,9 @@ class E(GObject.GObject):
     __gsignals__ = {'signal': (GObject.SignalFlags.RUN_FIRST, None,
                                ())}
 
+    # Property used to test detailed signal
+    prop = GObject.Property(type=int, default=0)
+
     def __init__(self):
         GObject.GObject.__init__(self)
         self.status = 0
@@ -254,20 +269,146 @@ class TestEmissionHook(unittest.TestCase):
         self.assertEqual(obj.status, 3)
 
 
+class TestMatching(unittest.TestCase):
+    class Object(GObject.Object):
+        status = 0
+        prop = GObject.Property(type=int, default=0)
+
+        @GObject.Signal()
+        def my_signal(self):
+            pass
+
+    @unittest.expectedFailure  # https://bugzilla.gnome.org/show_bug.cgi?id=692918
+    def test_signal_handler_block_matching(self):
+        def dummy(*args):
+            "Hack to work around: "
+
+        def foo(obj):
+            obj.status += 1
+
+        obj = self.Object()
+        handler_id = GObject.signal_connect_closure(obj, 'my-signal', foo, after=False)
+        handler_id
+
+        self.assertEqual(obj.status, 0)
+        obj.emit('my-signal')
+        self.assertEqual(obj.status, 1)
+
+        # Blocking by match criteria disables the foo callback
+        signal_id, detail = GObject.signal_parse_name('my-signal', obj, True)
+        count = GObject.signal_handlers_block_matched(obj,
+                                                      GObject.SignalMatchType.ID | GObject.SignalMatchType.CLOSURE,
+                                                      signal_id=signal_id, detail=detail,
+                                                      closure=foo, func=dummy, data=dummy)
+        self.assertEqual(count, 1)
+        obj.emit('my-signal')
+        self.assertEqual(obj.status, 1)
+
+        # Unblocking by the same match criteria allows callback to work again
+        count = GObject.signal_handlers_unblock_matched(obj,
+                                                        GObject.SignalMatchType.ID | GObject.SignalMatchType.CLOSURE,
+                                                        signal_id=signal_id, detail=detail,
+                                                        closure=foo, func=dummy, data=dummy)
+        self.assertEqual(count, 1)
+        obj.emit('my-signal')
+        self.assertEqual(obj.status, 2)
+
+        # Disconnecting by match criteria completely removes the handler
+        count = GObject.signal_handlers_disconnect_matched(obj,
+                                                           GObject.SignalMatchType.ID | GObject.SignalMatchType.CLOSURE,
+                                                           signal_id=signal_id, detail=detail,
+                                                           closure=foo, func=dummy, data=dummy)
+        self.assertEqual(count, 1)
+        obj.emit('my-signal')
+        self.assertEqual(obj.status, 2)
+
+    def test_signal_handler_find(self):
+        def dummy(*args):
+            "Hack to work around: "
+
+        def foo(obj):
+            obj.status += 1
+
+        obj = self.Object()
+        handler_id = GObject.signal_connect_closure(obj, 'my-signal', foo, after=False)
+
+        signal_id, detail = GObject.signal_parse_name('my-signal', obj, True)
+        found_id = GObject.signal_handler_find(obj,
+                                               GObject.SignalMatchType.ID,
+                                               signal_id=signal_id, detail=detail,
+                                               closure=None, func=dummy, data=dummy)
+        self.assertEqual(handler_id, found_id)
+
+
 class TestClosures(unittest.TestCase):
     def setUp(self):
         self.count = 0
+        self.emission_stopped = False
+        self.emission_error = False
+        self.handler_pending = False
+
+    def _callback_handler_pending(self, e):
+        signal_id, detail = GObject.signal_parse_name('signal', e, True)
+        self.handler_pending = GObject.signal_has_handler_pending(e, signal_id, detail,
+                                                                  may_be_blocked=False)
 
     def _callback(self, e):
         self.count += 1
 
-    def test_disconnect(self):
+    def _callback_stop_emission(self, obj, prop, stop_it):
+        if stop_it:
+            obj.stop_emission_by_name('notify::prop')
+            self.emission_stopped = True
+        else:
+            self.count += 1
+
+    def _callback_invalid_stop_emission_name(self, obj, prop):
+        # We expect a GLib warning but there currently is no way to test that
+        # This can at least make sure we don't crash
+        old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_CRITICAL |
+                                             GLib.LogLevelFlags.LEVEL_ERROR)
+        try:
+            obj.stop_emission_by_name('notasignal::baddetail')
+        finally:
+            GLib.log_set_always_fatal(old_mask)
+            self.emission_error = True
+
+    def test_disconnect_by_func(self):
         e = E()
         e.connect('signal', self._callback)
         e.disconnect_by_func(self._callback)
         e.emit('signal')
         self.assertEqual(self.count, 0)
 
+    def test_disconnect(self):
+        e = E()
+        handler_id = e.connect('signal', self._callback)
+        self.assertTrue(e.handler_is_connected(handler_id))
+        e.disconnect(handler_id)
+        e.emit('signal')
+        self.assertEqual(self.count, 0)
+        self.assertFalse(e.handler_is_connected(handler_id))
+
+    def test_stop_emission_by_name(self):
+        e = E()
+
+        # Sandwich a callback that stops emission in between a callback that increments
+        e.connect('notify::prop', self._callback_stop_emission, False)
+        e.connect('notify::prop', self._callback_stop_emission, True)
+        e.connect('notify::prop', self._callback_stop_emission, False)
+
+        e.set_property('prop', 1234)
+        self.assertEqual(e.get_property('prop'), 1234)
+        self.assertEqual(self.count, 1)
+        self.assertTrue(self.emission_stopped)
+
+    def test_stop_emission_by_name_error(self):
+        e = E()
+
+        e.connect('notify::prop', self._callback_invalid_stop_emission_name)
+        e.set_property('prop', 1234)
+        self.assertTrue(self.emission_error)
+
     def test_handler_block(self):
         e = E()
         e.connect('signal', self._callback)
@@ -277,8 +418,8 @@ class TestClosures(unittest.TestCase):
 
     def test_handler_unblock(self):
         e = E()
-        signal_id = e.connect('signal', self._callback)
-        e.handler_block(signal_id)
+        handler_id = e.connect('signal', self._callback)
+        e.handler_block(handler_id)
         e.handler_unblock_by_func(self._callback)
         e.emit('signal')
         self.assertEqual(self.count, 1)
@@ -317,6 +458,32 @@ class TestClosures(unittest.TestCase):
         data = c.emit("my_signal", "\01\00\02")
         self.assertEqual(data, "\02\00\01")
 
+    def test_handler_pending(self):
+        obj = F()
+        obj.connect('signal', self._callback_handler_pending)
+        obj.connect('signal', self._callback)
+
+        self.assertEqual(self.count, 0)
+        self.assertEqual(self.handler_pending, False)
+
+        obj.emit('signal')
+        self.assertEqual(self.count, 1)
+        self.assertEqual(self.handler_pending, True)
+
+    def test_signal_handlers_destroy(self):
+        obj = F()
+        obj.connect('signal', self._callback)
+        obj.connect('signal', self._callback)
+        obj.connect('signal', self._callback)
+
+        obj.emit('signal')
+        self.assertEqual(self.count, 3)
+
+        # count should remain at 3 after all handlers are destroyed
+        GObject.signal_handlers_destroy(obj)
+        obj.emit('signal')
+        self.assertEqual(self.count, 3)
+
 
 class SigPropClass(GObject.GObject):
     __gsignals__ = {'my_signal': (GObject.SignalFlags.RUN_FIRST, None,
@@ -362,6 +529,7 @@ class CM(GObject.GObject):
         test_string=(GObject.SignalFlags.RUN_LAST, str, (str,)),
         test_object=(GObject.SignalFlags.RUN_LAST, object, (object,)),
         test_paramspec=(GObject.SignalFlags.RUN_LAST, GObject.ParamSpec, ()),
+        test_paramspec_in=(GObject.SignalFlags.RUN_LAST, GObject.ParamSpec, (GObject.ParamSpec, )),
         test_gvalue=(GObject.SignalFlags.RUN_LAST, GObject.Value, (GObject.Value,)),
         test_gvalue_ret=(GObject.SignalFlags.RUN_LAST, GObject.Value, (GObject.TYPE_GTYPE,)),
     )
@@ -418,6 +586,17 @@ class _TestCMarshaller:
         self.assertEqual(rv.name, "test-param")
         self.assertEqual(rv.nick, "test")
 
+    @unittest.skipUnless(hasattr(GObject, 'param_spec_boolean'),
+                         'too old gobject-introspection')
+    def test_paramspec_in(self):
+        rv = GObject.param_spec_boolean('mybool', 'test-bool', 'do something',
+                                        True, GObject.ParamFlags.READABLE)
+
+        rv2 = self.obj.emit("test-paramspec-in", rv)
+        self.assertEqual(type(rv), type(rv2))
+        self.assertEqual(rv2.name, "mybool")
+        self.assertEqual(rv2.nick, "test-bool")
+
     def test_C_paramspec(self):
         self.notify_called = False
 
@@ -436,9 +615,7 @@ class _TestCMarshaller:
         self.assertEqual(rv, 42)
 
         # explicit float
-        v = GObject.Value()
-        v.init(GObject.TYPE_FLOAT)
-        v.set_float(1.234)
+        v = GObject.Value(GObject.TYPE_FLOAT, 1.234)
         rv = self.obj.emit("test-gvalue", v)
         self.assertAlmostEqual(rv, 1.234, 4)
 
@@ -447,9 +624,7 @@ class _TestCMarshaller:
         self.assertAlmostEqual(rv, 1.234, 4)
 
         # explicit int64
-        v = GObject.Value()
-        v.init(GObject.TYPE_INT64)
-        v.set_int64(GObject.G_MAXINT64)
+        v = GObject.Value(GObject.TYPE_INT64, GObject.G_MAXINT64)
         rv = self.obj.emit("test-gvalue", v)
         self.assertEqual(rv, GObject.G_MAXINT64)
 
@@ -459,9 +634,7 @@ class _TestCMarshaller:
         #self.assertEqual(rv, GObject.G_MAXINT64)
 
         # explicit uint64
-        v = GObject.Value()
-        v.init(GObject.TYPE_UINT64)
-        v.set_uint64(GObject.G_MAXUINT64)
+        v = GObject.Value(GObject.TYPE_UINT64, GObject.G_MAXUINT64)
         rv = self.obj.emit("test-gvalue", v)
         self.assertEqual(rv, GObject.G_MAXUINT64)
 
@@ -794,11 +967,9 @@ class TestSignalModuleLevelFunctions(unittest.TestCase):
         my_signal_expected_query_result = [my_signal_id, 'my-signal', C.__gtype__,
                                            1, GObject.TYPE_NONE, (GObject.TYPE_INT,)]
         # signal_query(name, type)
-        self.assertSequenceEqual(GObject.signal_query('my-signal', C),
-                                 my_signal_expected_query_result)
+        self.assertEqual(list(GObject.signal_query('my-signal', C)), my_signal_expected_query_result)
         # signal_query(signal_id)
-        self.assertSequenceEqual(GObject.signal_query(my_signal_id),
-                                 my_signal_expected_query_result)
+        self.assertEqual(list(GObject.signal_query(my_signal_id)), my_signal_expected_query_result)
         # invalid query returns None instead of raising
         self.assertEqual(GObject.signal_query(0), None)
         self.assertEqual(GObject.signal_query('NOT_A_SIGNAL', C),
index dda492a..5b3b51b 100644 (file)
@@ -183,6 +183,37 @@ class TestSource(unittest.TestCase):
         GLib.Timeout(20)
         GLib.Idle()
 
+    def test_finalize(self):
+        self.dispatched = False
+        self.finalized = False
+
+        class S(GLib.Source):
+            def prepare(s):
+                return (True, 1)
+
+            def dispatch(s, callback, args):
+                self.dispatched = True
+                return False
+
+            def finalize(s):
+                self.finalized = True
+
+        source = S()
+        id = source.attach()
+        print('source id:', id)
+        self.assertFalse(self.finalized)
+        self.assertFalse(source.is_destroyed())
+
+        while source.get_context().iteration(False):
+            pass
+
+        source.destroy()
+        self.assertTrue(self.dispatched)
+        self.assertFalse(self.finalized)
+        self.assertTrue(source.is_destroyed())
+        del source
+        self.assertTrue(self.finalized)
+
 
 class TestUserData(unittest.TestCase):
     def test_idle_no_data(self):
index 16bb39e..516cb97 100644 (file)
@@ -7,9 +7,6 @@
 
 #include <pyglib-python-compat.h>
 
-static PyTypeObject *_PyGObject_Type;
-#define PyGObject_Type (*_PyGObject_Type)
-
 static PyObject * _wrap_TestInterface__do_iface_method(PyObject *cls,
                                                       PyObject *args,
                                                       PyObject *kwargs);
@@ -402,6 +399,15 @@ test_gvalue_ret_callback (GObject *object, GType type)
   return ret;
 }
 
+static GParamSpec *
+test_paramspec_in_callback (GObject *object, GParamSpec *p)
+{
+  g_return_val_if_fail (G_IS_OBJECT (object), NULL);
+  g_return_val_if_fail (G_IS_PARAM_SPEC (p), NULL);
+
+  return p;
+}
+
 static void
 connectcallbacks (GObject *object)
 {
@@ -460,6 +466,10 @@ connectcallbacks (GObject *object)
                     "test_gvalue_ret",
                     G_CALLBACK (test_gvalue_ret_callback), 
                     NULL);
+  g_signal_connect (G_OBJECT (object),
+                    "test_paramspec_in",
+                    G_CALLBACK (test_paramspec_in_callback), 
+                    NULL);
 }
 
 static PyObject *
@@ -530,7 +540,6 @@ _wrap_test_gerror_exception(PyObject *self, PyObject *args)
         return NULL;
     }      
 
-    Py_DECREF(py_method);
     Py_DECREF(py_args);
     Py_DECREF(py_ret);
 
@@ -606,16 +615,7 @@ PYGLIB_MODULE_START(testhelper, "testhelper")
 
   d = PyModule_GetDict(module);
 
-  if ((m = PyImport_ImportModule("gi._gobject._gobject")) != NULL) {
-    PyObject *moddict = PyModule_GetDict(m);
-    
-    _PyGObject_Type = (PyTypeObject *)PyDict_GetItemString(moddict, "GObject");
-    if (_PyGObject_Type == NULL) {
-      PyErr_SetString(PyExc_ImportError,
-                     "cannot import name GObject from gobject");
-      return PYGLIB_MODULE_ERROR_RETURN;
-    }
-  } else {
+  if ((m = PyImport_ImportModule("gi._gobject._gobject")) == NULL) {
     PyErr_SetString(PyExc_ImportError,
                    "could not import gobject");
     return PYGLIB_MODULE_ERROR_RETURN;