Imported Upstream version 3.11.1 53/138253/1
authorDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 11 Jul 2017 23:39:41 +0000 (08:39 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Tue, 11 Jul 2017 23:39:45 +0000 (08:39 +0900)
Change-Id: I6f6a69c5dd77017d0c62c4fbefa44a2e57514c47
Signed-off-by: DongHun Kwak <dh0128.kwak@samsung.com>
47 files changed:
ChangeLog
Makefile.am
Makefile.in
NEWS
PKG-INFO
README
aclocal.m4
config.h.in
configure
configure.ac
examples/Makefile.in
gi/Makefile.in
gi/_glib/Makefile.in
gi/_glib/pyglib-python-compat.h
gi/_gobject/Makefile.in
gi/_gobject/pygobject.c
gi/docstring.py
gi/gimodule.c
gi/overrides/GLib.py
gi/overrides/GObject.py
gi/overrides/Makefile.in
gi/pygi-argument.c
gi/pygi-cache.c
gi/pygi-cache.h
gi/pygi-closure.c
gi/pygi-info.c
gi/pygi-invoke-state-struct.h
gi/pygi-invoke.c
gi/pygi-marshal-cleanup.c
gi/pygi-marshal-cleanup.h
gi/pygi-marshal-from-py.c
gi/pygi-marshal-from-py.h
gi/pygi-marshal-to-py.c
gi/pygi.h
gi/repository/Makefile.in
pygtkcompat/Makefile.in
tests/Makefile.am
tests/Makefile.in
tests/test_docstring.py
tests/test_everything.py
tests/test_gi.py
tests/test_glib.py
tests/test_gobject.py
tests/test_repository.py [new file with mode: 0644]
tests/test_signal.py
tests/test_source.py
tests/test_subprocess.py

index 7c4d231..0f4c934 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,13 +1,13 @@
-commit 7b037393e640711f54837794c942003b3a8df0af
+commit 5bcdb56433d0ba2976f05946c6c5b6ffe3e84901
 Author: Martin Pitt <martinpitt@gnome.org>
-Date:   Mon Nov 11 14:58:19 2013 +0100
+Date:   Mon Oct 28 15:59:51 2013 +0100
 
-    release 3.10.2
+    release 3.11.1
 
- NEWS | ++++
- 1 file changed, 4 insertions(+)
+ NEWS | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
 
-commit 9c44080f95c4c73688a34cf8033605c049fed77d
+commit 65b8f7bd77474e361c80905ec23de6dbde27970c
 Author: Simon Feltman <sfeltman@src.gnome.org>
 Date:   Sun Oct 27 22:09:27 2013 -0700
 
@@ -24,62 +24,78 @@ Date:   Sun Oct 27 22:09:27 2013 -0700
 
     https://bugzilla.gnome.org/show_bug.cgi?id=709223
 
+ gi/__init__.py       |  2 --
  gi/gimodule.c        | 18 +++++++-----------
- gi/overrides/GLib.py |  8 +++++++-
2 files changed, 14 insertions(+), 12 deletions(-)
+ gi/overrides/GLib.py |  8 ++------
3 files changed, 9 insertions(+), 19 deletions(-)
 
-commit 9f913abdfa46af3c6ddf2fd35f1fb0e08d7791d4
-Author: Martin Pitt <martinpitt@gnome.org>
-Date:   Mon Nov 11 14:34:12 2013 +0100
+commit 57195c9c864bc25521bb3cb98286e6d6f0645652
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Oct 27 16:02:13 2013 -0700
 
-    Revert "Add type checking to positional Gtk.Box and Gtk.Window
-    ctor arguments"
+    Add consistent GLib.MainLoop SIGINT cleanup
 
-    While this enforces correctness, this can cause new crashes in
-    software which
-    incorrectly uses the GObject constructor and needs
-    fixing. E. g. Ubuntu's
-    current sofware-center (wrongly) does
+    Remove auto cleanup of SIGINT source handling by returning True
+    from the
+    signal callback. This gives the __del__ method consistent cleanup
+    semantics
+    regardless of whether or not a SIGINT occurred.
 
-      Gtk.Box(Gtk.Orientation.HORIZONTAL)
+    https://bugzilla.gnome.org/show_bug.cgi?id=710978
 
-    which now causes a crash with this new check.
+ gi/overrides/GLib.py | 4 ++++
+ 1 file changed, 4 insertions(+)
 
-    This reverts commit 2cc4dfaf877f202977de4a7ede24aa3bad7d91c8.
+commit 1c03ebba9598e7b6d5293889f46b015bfac3611c
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Oct 27 15:16:09 2013 -0700
 
- gi/overrides/Gtk.py         |  7 -------
- tests/test_overrides_gtk.py | 18 ------------------
- tests/test_properties.py    |  9 ---------
- 3 files changed, 34 deletions(-)
+    tests: Fix source testing to handle critical with non-existing sources
 
-commit 2cc4dfaf877f202977de4a7ede24aa3bad7d91c8
-Author: Martin Pitt <martinpitt@gnome.org>
-Date:   Tue Nov 5 15:28:12 2013 +0100
+    Silence new critical coming from g_source_remove on non-existing
+    sources.
+    This function still returns False, but we need to silence the new
+    critical
+    so the test suite doesn't fail. See bug 710724.
 
-    Add type checking to positional Gtk.Box and Gtk.Window ctor arguments
+    https://bugzilla.gnome.org/show_bug.cgi?id=710978
 
-    Gtk.Box and Gtk.Window are base classes of a lot of widgets. Avoid
-    confusion
-    when trying to create a subclass of them through the GObject
-    constructor with
-    positional arguments by at least verifying that their type is
-    right. Otherwise
-    you can do things like
+ tests/test_source.py | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+commit ac776da7e56b78a2fa422487f0ef0d8771bcb78f
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Jul 28 00:01:35 2013 -0700
 
-      chooser = Gtk.FileChooserWidget(Gtk.FileChooserAction.SELECT_FOLDER)
+    docs: Add a keyword value of None for allow-none annotations
 
-    which succeeds, but does not have the desired effect (it sets the
-    "homogenous"
-    property of the Gtk.Box superclass instead).
+    Update documentation generator for allow-none arguments and
+    user_data arguments to show a keyword value of None.
+    Add skip for GDestroyNotify closure arguments.
 
-    https://bugzilla.gnome.org/show_bug.cgi?id=711487
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
 
- gi/overrides/Gtk.py         |  7 +++++++
- tests/test_overrides_gtk.py | 18 ++++++++++++++++++
- tests/test_properties.py    |  9 +++++++++
- 3 files changed, 34 insertions(+)
+ gi/docstring.py         | 20 +++++++++++++++++---
+ tests/test_docstring.py | 10 ++++++++++
+ 2 files changed, 27 insertions(+), 3 deletions(-)
 
-commit 7036e9d79ed49fe153758ec0507d6af62f067f2f
+commit e1bf9c069644ea0bff0c6a7efa72a285e122a414
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sat Oct 19 19:03:12 2013 -0700
+
+    Remove overrides for supporting pre-3.10 GObject signal functions
+
+    Remove GObject override code for supporting pre-3.10 signal functions
+    which
+    annotate the object argument as "gpointer". With PyGObject 3.11
+    having a
+    dependency on GObject 3.10, clear the special case overrides out.
+
+ gi/overrides/GObject.py | 76
+ ++++++-------------------------------------------
+ 1 file changed, 9 insertions(+), 67 deletions(-)
+
+commit 0c308de528c402f67808b13760ca30d55d4c99d7
 Author: Simon Feltman <sfeltman@src.gnome.org>
 Date:   Fri Oct 18 17:15:06 2013 -0700
 
@@ -96,29 +112,157 @@ Date:   Fri Oct 18 17:15:06 2013 -0700
 
     https://bugzilla.gnome.org/show_bug.cgi?id=710447
 
+ gi/__init__.py       |  2 ++
  gi/gimodule.c        | 10 ++++++++++
- gi/overrides/GLib.py |  9 +--------
2 files changed, 11 insertions(+), 8 deletions(-)
+ gi/overrides/GLib.py | 11 +++++++----
3 files changed, 19 insertions(+), 4 deletions(-)
 
-commit 26c34534f8771e0ee31cf37eb8df3be8cb1cb2f6
-Author: Martin Pitt <martinpitt@gnome.org>
-Date:   Mon Oct 14 12:54:36 2013 +0200
+commit a2fa531b4dee73c193cac92fa3e870808688b5d7
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Oct 14 20:38:13 2013 -0700
 
-    configure.ac: Post-release bump to 3.10.2
+    Add dir method to GObject props accessor
 
- configure.ac | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
+    Remove special case __members__ attribute from the props accessor
+    objects getattr method. This has been deprecated since Python 2.3 and
+    removed in Python 3. Replace this with a __dir__ method making use
+    of the
+    old members list building code. Additionally fix error where the
+    GObjectClass was being unref'd too many times when using
+    dir(Object.props),
+    causing a GLib critical.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=705754
+
+ gi/_gobject/pygobject.c | 29 +++++++++++++++++++++--------
+ tests/test_gi.py        | 14 ++++++++++++++
+ 2 files changed, 35 insertions(+), 8 deletions(-)
+
+commit 799989ada2f6b1d729f078f204445651c808a2c7
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri May 3 04:37:13 2013 -0700
+
+    Remove PyGObjectWeakRef now that g_binding_unbind exists
+
+    Remove the static code for managing GBinding weak references now
+    that GLib
+    has a method (unbind) for clearing out bindings.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=699571
+
+ gi/_gobject/pygobject.c | 59
+ +------------------------------------------------
+ gi/overrides/GObject.py | 19 ++++++++++++++++
+ tests/test_gobject.py   | 41 ++++++++++++++++++++--------------
+ 3 files changed, 44 insertions(+), 75 deletions(-)
 
-commit 863124b6268d1ea2c649d27771813c27cc9faa06
+commit fe217e0afbd63f05285e59628533f351896377d9
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Oct 9 00:34:37 2013 -0700
+
+    Fix GArray, GList, GSList, and GHashTable marshaling leaks
+
+    Remove calling of cleanup code for transfer-everything modes by
+    ensuring
+    cleanup_data is set to NULL in from_py marshalers. Use array and hash
+    table ref/unref functions for container transfer mode to ensure we
+    have a
+    valid container ref after invoke and during from_py cleanup of
+    contents.
+    Rework restrictions with to_py marshaling cleanup so we always
+    unref the
+    container for transfer-everything and transfer-container modes.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693402
+
+ gi/pygi-marshal-cleanup.c | 54 +++++++++++----------------------
+ gi/pygi-marshal-from-py.c | 77
+ ++++++++++++++++++++++++++++++++++++++++-------
+ 2 files changed, 84 insertions(+), 47 deletions(-)
+
+commit 7407367f424595c2780a2d6a47d936ad0bd91735
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Oct 7 14:11:39 2013 -0700
+
+    Add cleanup_data argument used for Python to C marshaler cleanup
+
+    Add a new output argument to all from_py marshalers which is used for
+    keeping track of marshaling data that later needs cleanup. Previously
+    most
+    marshalers would rely on the GIArgument->v_pointer as the means
+    for data
+    cleanup. However, this pointer would get clobbered in the case of
+    bi-directional arguments (inout) and the memory lost.
+    Use the new cleanup_data for storing temporarily wrapped C arrays
+    so we
+    don't need to re-calculate the length argument during cleanup.
+
+    Additionally delay the from_py marshaling cleanup function until after
+    _invoke_marshal_out_args is called. This gives inout arguments
+    which don't
+    modify the pointer sufficient time to exist until they marshaled
+    back to
+    Python (gi_marshalling_tests_gvalue_inout).
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693402
+
+ gi/pygi-argument.c            |   4 +-
+ gi/pygi-cache.h               |   3 +-
+ gi/pygi-invoke-state-struct.h |   7 +-
+ gi/pygi-invoke.c              |  20 +++---
+ gi/pygi-marshal-cleanup.c     |  43 +++++-------
+ gi/pygi-marshal-from-py.c     | 160
+ ++++++++++++++++++++++++++++--------------
+ gi/pygi-marshal-from-py.h     |  45 ++++++++----
+ 7 files changed, 177 insertions(+), 105 deletions(-)
+
+commit 9456e83233a927f1f01c6ffcb1f07c62b491a1df
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Aug 7 12:08:15 2013 -0700
+
+    Add support for variable user data arguments
+
+    Support a variable number of user data arguments for all callback
+    connection function where the user data is the last explicit argument.
+    This adds convience as well as consistency with the rest of PyGObject.
+    Cleanup overrides for GLib.idle_add, timeout_add, timeout_add_seconds,
+    io_add_watch, and child_watch_add which manually implemented this
+    feature.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/overrides/GLib.py      | 75
+ +++++++++++++++--------------------------------
+ gi/pygi-cache.c           | 14 +++++++++
+ gi/pygi-cache.h           |  3 ++
+ gi/pygi-closure.c         | 37 +++++++++++++++--------
+ gi/pygi-invoke.c          | 71
+ +++++++++++++++++++++++++++++++-------------
+ gi/pygi-marshal-from-py.c |  5 ++++
+ tests/test_everything.py  | 32 ++++++++++++++++++++
+ tests/test_glib.py        | 21 +++++++++++++
+ tests/test_subprocess.py  |  8 ++---
+ 9 files changed, 177 insertions(+), 89 deletions(-)
+
+commit ba4a0a65bf9ec44c3b9449f63d63035bff75d8df
 Author: Martin Pitt <martinpitt@gnome.org>
-Date:   Mon Oct 14 12:51:44 2013 +0200
+Date:   Mon Oct 14 12:57:04 2013 +0200
 
-    release 3.10.1
+    Bump glib and g-i dependencies to latest stable.
 
- NEWS | 8 ++++++++
- 1 file changed, 8 insertions(+)
+    glib 2.38 and g-i 1.38 are from stable GNOME 3.10 which we now
+    assume as
+    minimal version.
+
+    Drop @unittest.skipUnless tags from tests which didn't work with
+    g-i 1.36.
 
-commit 43ac1f9fd4b1f5132b7fa996da7e307371d11bb1
+ README           | 3 ++-
+ configure.ac     | 6 +++---
+ tests/test_gi.py | 2 --
+ 3 files changed, 5 insertions(+), 6 deletions(-)
+
+commit 2a5ad2af6bc91b187a2f07fc8d001ec7ad618adf
 Author: Nuno Araujo <nuno.araujo@russo79.com>
 Date:   Fri Oct 11 18:41:48 2013 +0200
 
@@ -147,7 +291,7 @@ Date:   Fri Oct 11 18:41:48 2013 +0200
  tests/test_overrides_gtk.py | 2 ++
  2 files changed, 4 insertions(+), 2 deletions(-)
 
-commit 90beeee7600bf39768c38bcfc47582c0e592eec9
+commit 27e9f6ede021fc58e952491b67d69c2a5cdd6acb
 Author: Simon Feltman <sfeltman@src.gnome.org>
 Date:   Tue Oct 1 17:09:39 2013 -0700
 
@@ -172,7 +316,374 @@ Date:   Tue Oct 1 17:09:39 2013 -0700
  gi/_gobject/pygobject.c | 21 ++++++++++++++-------
  1 file changed, 14 insertions(+), 7 deletions(-)
 
-commit 073f3870f2671a387d99529bab386f2218f44e2e
+commit 55d925d5f0fb87464b1f391c325c1e70da10d33d
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Oct 10 16:10:16 2013 -0700
+
+    Add expected failure to deal with fixes in gimarshallingtests.c
+
+    Fix test_object_full_inout based on newer gimarshallingtests.c >
+    1.38.0.
+    Add expectedFailure to deal with previous versions of
+    gimarshallingtests.c.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709796
+
+ tests/test_gi.py | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+commit d866d422cc39b229f443dd08a3ea50cb3f7df8e6
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Mon Oct 7 01:17:08 2013 -0700
+
+    Fix memory leaks for inout array arguments
+
+    Add tracking for array allocations to from_py marashalers in the
+    argument states extra data (arg_data). This is then used later
+    for inout
+    marshaling cleanup to call the array cleanup function.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693402
+
+ gi/pygi-invoke.c          |  1 +
+ gi/pygi-marshal-cleanup.c |  1 +
+ gi/pygi-marshal-from-py.c | 13 +++++++++----
+ 3 files changed, 11 insertions(+), 4 deletions(-)
+
+commit 31263ac117027446c8e2fd1b56d7e348384aabef
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Oct 6 21:54:15 2013 -0700
+
+    Fix to Python marshaling leaks for arrays holding GVariants
+
+    Add early check for array items holding pointers and simply assign the
+    pointer to GIArgument.v_pointer prior giving it to the per-item
+    marshaler.
+    This simplifies marshaling and fixes leaks regarding arrays of
+    GVariants by
+    removing the unneeded g_variant_ref_sink (variants are always
+    pointers).
+    Conditionalize the use of g_variant_ref_sink based on transfer mode
+    in the
+    per-item marshaler. This fixes a reference leak where we are given
+    ownership
+    of the variant (transfer full) but added a new ref anyway.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693402
+
+ gi/pygi-marshal-to-py.c | 34 ++++++++++++++++++----------------
+ 1 file changed, 18 insertions(+), 16 deletions(-)
+
+commit c9580ce1156789221aa19b00c7aab404db5431b5
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Oct 6 04:26:18 2013 -0700
+
+    Cleanup per-item array marshaling code for flat arrays
+
+    Add an early per-item check which tests if the item being marshaled
+    is a
+    pointer and simply copies the pointer into the array. This takes
+    care of the
+    GdkAtom and GVariant special cases because these items are always
+    reported
+    as pointers.
+    Fix error condition cleanup code when an item fails marshaling in
+    the middle
+    of an array.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693402
+
+ gi/pygi-marshal-from-py.c | 87
+ +++++++++++++++++++++--------------------------
+ tests/test_gi.py          | 32 +++++++++++++++++
+ 2 files changed, 71 insertions(+), 48 deletions(-)
+
+commit 4623caa71c54958ab821db27a9eff2790acb3975
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sat Oct 5 17:00:54 2013 -0700
+
+    Fix GValue array marshaling leaks and crash fallout
+
+    * Decrement references for results of PySequence_GetItem. There were
+    a few
+    places we were not decrementing the Python reference, leaking
+    the value.
+    * Add tracking of Python arguments with recursive marshaling
+    cleanup. This
+    allows arrays of GValues which have been coerced from Python types
+    to be
+    properly free'd (also fixes bug 703662).
+    * Use g_variant_ref for variant arguments marked as transfer
+    everything.
+    This fixes double free's caused by the decrementing of
+    PySequence_GetItem
+    results.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=693402
+
+ gi/pygi-cache.h           |  1 +
+ gi/pygi-invoke.c          |  1 +
+ gi/pygi-marshal-cleanup.c | 50
+ +++++++++++++++++++++++++++++++++++++++++------
+ gi/pygi-marshal-cleanup.h | 14 +++++++++++++
+ gi/pygi-marshal-from-py.c | 20 ++++++++++++++++---
+ gi/pygi-marshal-to-py.c   |  1 +
+ 6 files changed, 78 insertions(+), 9 deletions(-)
+
+commit 549f849ef8854352483657df3d7558688a4b0007
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sat Sep 28 00:26:28 2013 -0700
+
+    Refactor GLib.io_add_watch to make it more testable
+
+    Break the argument munging code into a separate function which
+    can be tested in isolation of adding an io watch.
+    Add additional failing test which specifies all args as keywords
+    which we eventually need to support for consistency with the
+    rest of PyGObject.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/overrides/GLib.py | 23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+commit bc780ed17bc4cc62959c63c3f0142161a924679f
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Sep 27 20:59:45 2013 -0700
+
+    Refactor GLib.child_watch_add to make it more testable
+
+    Break the argument munging code into a separate function which
+    can be tested in isolation of adding a child watch. Update tests
+    to reflect this. Add additional failing test which specify
+    all args as keywords which we eventually need to support for
+    consistency with the rest of PyGObject.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/overrides/GLib.py     | 25 +++++++++-----
+ tests/test_subprocess.py | 88
+ +++++++++++++++++++++---------------------------
+ 2 files changed, 56 insertions(+), 57 deletions(-)
+
+commit 73c6213e8b47fa7c4c2c7a517fe7b56126145888
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Sep 26 19:05:20 2013 -0700
+
+    Don't pass None to callbacks when user data is not specified
+
+    For APIs which support a callback and optional user data,
+    don't pass the user data to the callback if it was not explicitly
+    specified when the callback was connected.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-closure.c         | 17 ++++++++++++++---
+ gi/pygi-marshal-from-py.c |  5 -----
+ tests/test_everything.py  |  7 ++-----
+ 3 files changed, 16 insertions(+), 13 deletions(-)
+
+commit a76b06179cdca43f1c7d1feb8e2563e3d884a8ff
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 17:27:47 2013 -0700
+
+    Add missing methods on PyGIBaseInfo and sub-classes
+
+    Expose all methods of GIBaseBase info and its sub-classes.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/_glib/pyglib-python-compat.h |   1 +
+ gi/pygi-info.c                  | 550
+ +++++++++++++++++++++++++++++++++++++++-
+ tests/test_repository.py        | 134 ++++++++++
+ 3 files changed, 677 insertions(+), 8 deletions(-)
+
+commit e190eb75093e8bf36190dc1beb18d1c1b95b9582
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 13:46:36 2013 -0700
+
+    Expose all GI enum and flags types
+
+    Add new types for GIDirection, GITransfer, GIArrayType, GIScopeType,
+    GIVFuncInfoFlags, GIFieldInfoFlags, GIFuncitonInfoFlags, GITypeTag,
+    and
+    GInfoType. These types are found in the gi._gi module exposed
+    without the
+    "GI" prefix and contain all of their values as class attributes. e.g.
+    gi._gi.Transfer.EVERYTHING.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/docstring.py          |  10 ++--
+ gi/pygi-info.c           | 150
+ ++++++++++++++++++++++++++++++++++++++++++++---
+ tests/test_repository.py |  13 +++-
+ 3 files changed, 158 insertions(+), 15 deletions(-)
+
+commit 0120af6c418d0f67f39c02a4e8327813645b97f4
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 13:42:34 2013 -0700
+
+    Avoid calling g_base_info_get_name on GI_INFO_TYPE_TYPE
+
+    Calling g_base_info_get_name on infos tagged with GI_INFO_TYPE_TYPE
+    will
+    cause a crash. Avoid this by adding _safe_base_info_get_name and
+    using that
+    throughout the bindings.
+    Logged GI bug as: https://bugzilla.gnome.org/show_bug.cgi?id=709456
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/pygi-info.c | 35 +++++++++++++++++++++++++----------
+ 1 file changed, 25 insertions(+), 10 deletions(-)
+
+commit c86b2fe8d01070f06c45fffd910d890afba1313a
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 13:41:08 2013 -0700
+
+    Add GIBaseInfo.equal method
+
+    Break PyGIBaseInfo rich compare into two methods: equal and
+    richcompare.
+    Equal is a direct exposure of the GI method and richcompare makes
+    use of
+    this with additional support for Pyton "==" and "!=" operators.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/pygi-info.c           | 32 ++++++++++++++++++++++++--------
+ tests/test_repository.py |  1 +
+ 2 files changed, 25 insertions(+), 8 deletions(-)
+
+commit e7b758badd0ab0b147117859f7871c39fb5399c1
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 13:36:11 2013 -0700
+
+    Move info string retrieval into generic function
+
+    Add get_info_string for sharing binding of simple string retrieval on
+    GIBaseInfo objects.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/pygi-info.c | 15 +++++++++++++--
+ 1 file changed, 13 insertions(+), 2 deletions(-)
+
+commit d2aef364de778da966bc1cfffe184d649f9ebb21
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Tue Sep 24 06:26:17 2013 -0700
+
+    Move child info retrieval into generic function
+
+    Add a generic function for bindings which return a single child info.
+    This trivializes binding methods like PyGIObjectInfo.get_parent and
+    fixes leaks in PyGIObjectInfo.get_class_struct and
+    PyGIVFuncInfo.get_invoker.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/pygi-info.c | 56
+ +++++++++++++++++++++++---------------------------------
+ 1 file changed, 23 insertions(+), 33 deletions(-)
+
+commit cdd03a2b0baef19797a5b55c2880e5b7acf1dd93
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Tue Sep 24 02:52:22 2013 -0700
+
+    Move info tuple retrieval into generic function
+
+    Create new generic function for retrieving a tuple of child infos.
+    This greatly simplifies all the bindings which return tuples from
+    a common pattern of functions on GIBaseInfo based instances.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/pygi-info.c | 469
+ ++++++++-------------------------------------------------
+ 1 file changed, 59 insertions(+), 410 deletions(-)
+
+commit 62f185bef20b42f18290a3cf1d3b19dddc957f8a
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Oct 6 16:41:37 2013 -0700
+
+    tests: Update check.valgrind with always-malloc and add logging
+    options
+
+    Based on notes in https://wiki.gnome.org/Valgrind we need to use
+    always-malloc for valgrind runs.
+    Add check.valgrindlog and check.valgrindxml which output valgrind
+    logs into
+    an ignored local tmp. Output logs are named <head-sha>-$TEST_NAMES.log
+    so we
+    can track commits and use diff tools on the logs.
+
+ .gitignore        |  1 +
+ Makefile.am       |  6 ++++++
+ tests/Makefile.am | 10 +++++++++-
+ 3 files changed, 16 insertions(+), 1 deletion(-)
+
+commit 314c933626c4dc5fc585d0e5b6c45ddb17c2e52f
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 20:43:02 2013 -0700
+
+    Move existing repository tests into test_repository
+
+    Move flags and enum double registration tests into test_repository.py.
+    Remove duplicate ObjectInfo tests from test_gi.py.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ tests/test_gi.py         | 38 --------------------------------------
+ tests/test_repository.py | 28 ++++++++++++++++++++++++++++
+ 2 files changed, 28 insertions(+), 38 deletions(-)
+
+commit 31840888c8948aab78041da93c329572f3aabb64
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 17:31:21 2013 -0700
+
+    Add unittests for GIRepository
+
+    Add basic unittests for the existing classes and methods exposed for
+    the GIRepository module (gi._gi).
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ tests/Makefile.am        |   1 +
+ tests/test_repository.py | 170
+ +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 171 insertions(+)
+
+commit 4408f83be70e92c5e3943f5ce85c551e7f2c87d0
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 15:50:05 2013 -0700
+
+    Derive SignalInfo info from CallableInfo
+
+    Change Python class derivation of PyGISignalInfo to use
+    PyGICallableInfo as
+    the base class. This accurately reflects the GI class layout and
+    provides
+    the callable information for signals.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/pygi-info.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+commit b01daba04ff001b9e63d343938e879d339d9a98c
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Oct 4 15:48:05 2013 -0700
+
+    Use PYGLIB_PyLong_FromLong for GIDirection return
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=709008
+
+ gi/pygi-info.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit d644cbd0c0ad85142286754838db848c4eb1707f
 Author: Simon Feltman <sfeltman@src.gnome.org>
 Date:   Thu Oct 3 19:25:34 2013 -0700
 
@@ -193,6 +704,207 @@ Date:   Thu Oct 3 19:25:34 2013 -0700
  gi/pygi-marshal-cleanup.c | 11 ++++++-----
  1 file changed, 6 insertions(+), 5 deletions(-)
 
+commit 510789d52e9e2fd863d26613f3282364eb175601
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Jul 28 14:44:51 2013 -0700
+
+    Add support for default arguments annotated with allow-none
+
+    Support default value of NULL for tail end arguments which are
+    marked with allow-none.
+    The implementation uses a place holder object for un-supplied
+    arguments
+    which are annotated with allow-none. This is then used later during
+    marshaling to supply NULL as the default.
+    Additionally support an implicit default for callback user_data
+    using the same technique.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/gimodule.c             |   6 +++
+ gi/pygi-cache.c           | 103
+ ++++++++++++++++++++++++++++++----------------
+ gi/pygi-cache.h           |   8 ++++
+ gi/pygi-invoke.c          |  42 +++++++++++++------
+ gi/pygi-marshal-from-py.c |   5 +++
+ gi/pygi.h                 |   1 +
+ tests/test_everything.py  |  16 +++++++
+ tests/test_gi.py          |  30 ++++++++++++++
+ 8 files changed, 162 insertions(+), 49 deletions(-)
+
+commit 03f531ffb1adde0c48e98f92bd92f79416654fbe
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Aug 2 22:27:10 2013 -0700
+
+    cache refactoring: Move arg cache field assignments into
+    _arg_cache_new
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.c | 23 +++++++++++------------
+ 1 file changed, 11 insertions(+), 12 deletions(-)
+
+commit cb7e7311bff57eb4c79c7772b6db4d00084656bb
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Aug 2 20:27:02 2013 -0700
+
+    cache refactoring: Cleanup array length argument marshaling
+
+    Add shared function: _arg_cache_array_len_arg_setup for use
+    with both to and from array marshaling setup. This function
+    consolidates all of the edge cases regarding array length setup
+    and removes the need for flagging arguments with
+    PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.c | 145
+ +++++++++++++++++++++++++++-----------------------------
+ gi/pygi-cache.h |   5 --
+ 2 files changed, 71 insertions(+), 79 deletions(-)
+
+commit c9d8639401ae82977e960de44d80b94a501a2184
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sat Aug 3 00:26:11 2013 -0700
+
+    cache refactoring: Move variable declarations to blocks where they
+    are used
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.c | 25 ++++++++++++++-----------
+ 1 file changed, 14 insertions(+), 11 deletions(-)
+
+commit dbc2cf5f1fa0f9cc046170efa6afb086b90253cb
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Thu Aug 1 19:33:27 2013 -0700
+
+    cache refactoring: Remove continue statements from
+    _args_cache_generate
+
+    Remove continue and goto statements from the large loop within
+    _args_cache_generate. This simplifies the sharing of parts of
+    the loop for future refactoring.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.c | 126
+ +++++++++++++++++++++++++++-----------------------------
+ 1 file changed, 61 insertions(+), 65 deletions(-)
+
+commit 87ae14b8b4a0ed9beb22f48314247e988a2e017f
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Jul 31 18:10:05 2013 -0700
+
+    cache refactoring: Use bit field for PyGIDirection instead of enum
+
+    This supports cleaner logic when testing the direction of
+    arguments due to the majority of these tests being along the
+    lines of: (direction == FROM_PYTHON || direction == BIDIRECTIONAL)
+    Which is replaced with: (direction & FROM_PYTHON)
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.c | 64
+ ++++++++++++++++++++++++++++-----------------------------
+ gi/pygi-cache.h |  6 +++---
+ 2 files changed, 35 insertions(+), 35 deletions(-)
+
+commit d5925b76afa3a429092cbafd82aed40bb0cf0b18
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Jul 28 20:45:05 2013 -0700
+
+    cache refactoring: Remove special case marshaling for instance
+    arguments
+
+    Remove duplicate code for marshaling struct and objects for
+    instance arguments. Re-use individual cache marshalers for
+    structs and objects with the instance argument. This required
+    removal of passing GITypeInfo to the marshaler because it is
+    not available for instance arguments. Instead always assume
+    "is_pointer" for the instance argument by using the cache.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-argument.c        |  4 +--
+ gi/pygi-cache.c           | 16 ++++-----
+ gi/pygi-marshal-from-py.c | 87
+ +++--------------------------------------------
+ gi/pygi-marshal-from-py.h | 16 ++-------
+ 4 files changed, 16 insertions(+), 107 deletions(-)
+
+commit c19bed69c669160737e12d92cc29f3e6d1b008cc
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Jul 28 16:44:01 2013 -0700
+
+    cache refactoring: Use GPtrArray for callable arg cache
+
+    Replace manual management of the C array holding individual
+    argument caches with usage of GPtrArray. This provides storage
+    of the array length along with item memory management.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.c           | 62
+ +++++++++++++++++++++++------------------------
+ gi/pygi-cache.h           | 16 +++++++++---
+ gi/pygi-invoke.c          | 16 ++++++------
+ gi/pygi-marshal-cleanup.c |  8 +++---
+ gi/pygi-marshal-from-py.c |  6 ++---
+ gi/pygi-marshal-to-py.c   |  6 ++---
+ 6 files changed, 62 insertions(+), 52 deletions(-)
+
+commit 52ea3afb0a6494423eca36a54af928d4ae5d9954
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Sun Jul 28 15:02:51 2013 -0700
+
+    cache refactoring: Move PyGI direction code into new function
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.c | 42 +++++++++++++++++++++---------------------
+ 1 file changed, 21 insertions(+), 21 deletions(-)
+
+commit 83208bf495b152e93a28a231d445f43ea827d2eb
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Fri Aug 2 15:59:25 2013 -0700
+
+    cache refactoring: Add comments to callable cache structure
+
+    Add comments to count fields on _PyGICallableCache.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=640812
+
+ gi/pygi-cache.h | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+commit 0a8d5695972601eaa9f7f463bac173d02b0380a0
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Jul 24 01:14:29 2013 -0700
+
+    Remove support for allowing PyObjects as void pointers
+
+    Final removal of marshaling Python object addresses as
+    void pointers. This ensures we can successfully pass
+    integer values as the pointer without the Python object
+    leaking or crashing due to invalid memory.
+
+    https://bugzilla.gnome.org/show_bug.cgi?id=688081
+
+ gi/pygi-marshal-from-py.c | 20 ++++++--------------
+ gi/pygi-marshal-to-py.c   | 14 ++------------
+ tests/test_signal.py      |  5 +----
+ 3 files changed, 9 insertions(+), 30 deletions(-)
+
+commit 1469403ee2faa699430055384b338f0cd8e672d7
+Author: Simon Feltman <sfeltman@src.gnome.org>
+Date:   Wed Sep 25 18:21:22 2013 -0700
+
+    configure.ac: bump trunk to 3.11.1
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
 commit 8e774e61d62c82efa3d907c1201359121878b4b5
 Author: Simon Feltman <sfeltman@src.gnome.org>
 Date:   Mon Sep 23 03:57:03 2013 -0700
index 5e91024..5051b54 100644 (file)
@@ -148,4 +148,10 @@ check.nemiver:
 check.valgrind:
        cd tests && $(MAKE) check.valgrind
 
+check.valgrindlog:
+       cd tests && $(MAKE) check.valgrindlog
+
+check.valgrindxml:
+       cd tests && $(MAKE) check.valgrindxml
+
 @GNOME_CODE_COVERAGE_RULES@
index 71694fb..b4528f1 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -493,8 +493,8 @@ $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
 $(am__aclocal_m4_deps):
 
 config.h: stamp-h1
-       @test -f $@ || rm -f stamp-h1
-       @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+       @if test ! -f $@; then rm -f stamp-h1; else :; fi
+       @if test ! -f $@; then $(MAKE) $(AM_MAKEFLAGS) stamp-h1; else :; fi
 
 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
        @rm -f stamp-h1
@@ -767,16 +767,10 @@ dist-xz: distdir
        $(am__post_remove_distdir)
 
 dist-tarZ: distdir
-       @echo WARNING: "Support for shar distribution archives is" \
-                      "deprecated." >&2
-       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
        tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
        $(am__post_remove_distdir)
 
 dist-shar: distdir
-       @echo WARNING: "Support for distribution archives compressed with" \
-                      "legacy program 'compress' is deprecated." >&2
-       @echo WARNING: "It will be removed altogether in Automake 2.0" >&2
        shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
        $(am__post_remove_distdir)
 
@@ -1095,6 +1089,12 @@ check.nemiver:
 check.valgrind:
        cd tests && $(MAKE) check.valgrind
 
+check.valgrindlog:
+       cd tests && $(MAKE) check.valgrindlog
+
+check.valgrindxml:
+       cd tests && $(MAKE) check.valgrindxml
+
 @GNOME_CODE_COVERAGE_RULES@
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/NEWS b/NEWS
index 5d9b042..f0a4503 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,14 +1,29 @@
-3.10.2  11-Nov-2013
-        - Fix thread safety problems by always enabling the GIL
-         (Simon Feltman) (#709223, #710447)
-
-3.10.1  14-Oct-2013
+3.11.1  28-Oct-2013
+        - Fix toggleref safety problems by always enabling the GIL
+         (Simon Feltman) (#709223)
+       - Add consistent GLib.MainLoop SIGINT cleanup (Simon Feltman) (#710978)
+        - docs: Add a keyword value of None for allow-none annotations
+         (Simon Feltman) (#640812)
+       - Remove overrides for supporting pre-3.10 GObject signal functions
+         (Simon Feltman)
+       - Add threads_init back as a requirement for non-Python threaded repos
+         (Simon Feltman) (#710447)
+       - Add dir method to GObject props accessor (Simon Feltman) (#705754)
+        - Remove PyGObjectWeakRef now that g_binding_unbind exists
+         (Simon Feltman) (#699571)
+        - Fix lots of memory leaks leaks (Simon Feltman) (#693402, #709397)
+        - Add support for variable user data arguments (Simon Feltman) (#640812)
+        - Bump glib and g-i dependencies to latest stable. (Martin Pitt)
        - Fix TypeError when setting drag target_list to None (Nuno Araujo)
          (#709926)
        - Use qdata for wrapper retrieval in toggle reference notifications
          (Simon Feltman) (#709223)
-        - Fix memory leak for caller allocated GValue out arguments
-         (Simon Feltman) (#709397)
+        - Expose all GI enum and flags types (Simon Feltman) (#709008)
+        - Add support for default arguments annotated with allow-none
+         (Simon Feltman) (#640812)
+       - Refactor argument cache handling (Simon Feltman) (#640812)
+        - Remove support for allowing PyObjects as void pointers
+         (Simon Feltman) (#688081)
 
 3.10.0  23-Sep-2013
         - Fix test_gi.TestProjectVersion.test_version_str() (Martin Pitt)
index 86a104e..5751559 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.0
 Name: PyGObject
-Version: 3.10.2
+Version: 3.11.1
 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.10/pygobject-3.10.2.tar.gz
+Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.11/pygobject-3.11.1.tar.gz
 Description: Python bindings for GLib and GObject
 Platform: POSIX, Windows
 Classifier: Development Status :: 5 - Production/Stable
diff --git a/README b/README
index 7530c61..d38e974 100644 (file)
--- a/README
+++ b/README
@@ -46,7 +46,8 @@ Requirements
 ============
   * C compiler (GCC and MSVC supported)
   * Python 2.7 or higher
-  * Glib/Gio 2.35.9 or higher
+  * Glib/Gio 2.38.0 or higher
+  * gobject-introspection 1.38.0 or higher
   * libffi (optional)
 
 Copyright Information
index aa08057..43d9348 100644 (file)
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.14 -*- Autoconf -*-
+# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
 
 # Copyright (C) 1996-2013 Free Software Foundation, Inc.
 
@@ -753,10 +753,10 @@ fi[]dnl
 # generated from the m4 files accompanying Automake X.Y.
 # (This private macro should not be called outside this file.)
 AC_DEFUN([AM_AUTOMAKE_VERSION],
-[am__api_version='1.14'
+[am__api_version='1.13'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.14], [],
+m4_if([$1], [1.13.3], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -772,7 +772,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.14])dnl
+[AM_AUTOMAKE_VERSION([1.13.3])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
@@ -1139,12 +1139,6 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
 # This macro actually does too much.  Some checks are only needed if
 # your package does certain things.  But this isn't really a big deal.
 
-dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
-m4_define([AC_PROG_CC],
-m4_defn([AC_PROG_CC])
-[_AM_PROG_CC_C_O
-])
-
 # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
 # AM_INIT_AUTOMAKE([OPTIONS])
 # -----------------------------------------------
@@ -1253,48 +1247,7 @@ dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
 AC_CONFIG_COMMANDS_PRE(dnl
 [m4_provide_if([_AM_COMPILER_EXEEXT],
   [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
-
-# POSIX will say in a future version that running "rm -f" with no argument
-# is OK; and we want to be able to make that assumption in our Makefile
-# recipes.  So use an aggressive probe to check that the usage we want is
-# actually supported "in the wild" to an acceptable degree.
-# See automake bug#10828.
-# To make any issue more visible, cause the running configure to be aborted
-# by default if the 'rm' program in use doesn't match our expectations; the
-# user can still override this though.
-if rm -f && rm -fr && rm -rf; then : OK; else
-  cat >&2 <<'END'
-Oops!
-
-Your 'rm' program seems unable to run without file operands specified
-on the command line, even when the '-f' option is present.  This is contrary
-to the behaviour of most rm programs out there, and not conforming with
-the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
-
-Please tell bug-automake@gnu.org about your system, including the value
-of your $PATH and any error possibly output before this message.  This
-can help us improve future automake versions.
-
-END
-  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
-    echo 'Configuration will proceed anyway, since you have set the' >&2
-    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
-    echo >&2
-  else
-    cat >&2 <<'END'
-Aborting the configuration process, to ensure you take notice of the issue.
-
-You can download and install GNU coreutils to get an 'rm' implementation
-that behaves properly: <http://www.gnu.org/software/coreutils/>.
-
-If you want to complete the configuration process using your problematic
-'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
-to "yes", and re-run configure.
-
-END
-    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
-  fi
-fi])
+])
 
 dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
 dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
@@ -1302,6 +1255,7 @@ dnl mangled by Autoconf and run in a shell conditional statement.
 m4_define([_AC_COMPILER_EXEEXT],
 m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
 
+
 # When config.status generates a header, we must update the stamp-h file.
 # This file resides in the same directory as the config header
 # that is generated.  The stamp files are numbered to have different names.
@@ -1413,6 +1367,38 @@ AC_MSG_RESULT([$_am_result])
 rm -f confinc confmf
 ])
 
+# Copyright (C) 1999-2013 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.
+
+# AM_PROG_CC_C_O
+# --------------
+# Like AC_PROG_CC_C_O, but changed for automake.
+AC_DEFUN([AM_PROG_CC_C_O],
+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([compile])dnl
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+if test "$am_t" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+dnl Make sure AC_PROG_CC is never called again, or it will override our
+dnl setting of CC.
+m4_define([AC_PROG_CC],
+          [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
+])
+
 # Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
 
 # Copyright (C) 1997-2013 Free Software Foundation, Inc.
@@ -1489,53 +1475,6 @@ AC_DEFUN([_AM_IF_OPTION],
 # gives unlimited permission to copy and/or distribute it,
 # with or without modifications, as long as this notice is preserved.
 
-# _AM_PROG_CC_C_O
-# ---------------
-# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
-# to automatically call this.
-AC_DEFUN([_AM_PROG_CC_C_O],
-[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
-AC_REQUIRE_AUX_FILE([compile])dnl
-AC_LANG_PUSH([C])dnl
-AC_CACHE_CHECK(
-  [whether $CC understands -c and -o together],
-  [am_cv_prog_cc_c_o],
-  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
-  # Make sure it works both with $CC and with simple cc.
-  # Following AC_PROG_CC_C_O, we do the test twice because some
-  # compilers refuse to overwrite an existing .o file with -o,
-  # though they will create one.
-  am_cv_prog_cc_c_o=yes
-  for am_i in 1 2; do
-    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
-         && test -f conftest2.$ac_objext; then
-      : OK
-    else
-      am_cv_prog_cc_c_o=no
-      break
-    fi
-  done
-  rm -f core conftest*
-  unset am_i])
-if test "$am_cv_prog_cc_c_o" != yes; then
-   # Losing compiler, so override with the script.
-   # FIXME: It is wrong to rewrite CC.
-   # But if we don't then we get into trouble of one sort or another.
-   # A longer-term fix would be to have automake use am__CC in this case,
-   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
-   CC="$am_aux_dir/compile $CC"
-fi
-AC_LANG_POP([C])])
-
-# For backward compatibility.
-AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
-
-# Copyright (C) 1999-2013 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.
-
 
 # AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
 # ---------------------------------------------------------------------------
index f93b29e..fa098f6 100644 (file)
@@ -37,6 +37,9 @@
    */
 #undef LT_OBJDIR
 
+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
+#undef NO_MINUS_C_MINUS_O
+
 /* Name of package */
 #undef PACKAGE
 
index 7e8e0fd..791a090 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.10.2.
+# Generated by GNU Autoconf 2.69 for pygobject 3.11.1.
 #
 # 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.10.2'
-PACKAGE_STRING='pygobject 3.10.2'
+PACKAGE_VERSION='3.11.1'
+PACKAGE_STRING='pygobject 3.11.1'
 PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject'
 PACKAGE_URL='https://live.gnome.org/PyGObject/'
 
@@ -1395,7 +1395,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.10.2 to adapt to many kinds of systems.
+\`configure' configures pygobject 3.11.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1465,7 +1465,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of pygobject 3.10.2:";;
+     short | recursive ) echo "Configuration of pygobject 3.11.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1602,7 +1602,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-pygobject configure 3.10.2
+pygobject configure 3.11.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1880,7 +1880,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.10.2, which was
+It was created by pygobject $as_me 3.11.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2239,14 +2239,14 @@ $as_echo "#define PYGOBJECT_MAJOR_VERSION 3" >>confdefs.h
 PYGOBJECT_MAJOR_VERSION=3
 
 
-$as_echo "#define PYGOBJECT_MINOR_VERSION 10" >>confdefs.h
+$as_echo "#define PYGOBJECT_MINOR_VERSION 11" >>confdefs.h
 
-PYGOBJECT_MINOR_VERSION=10
+PYGOBJECT_MINOR_VERSION=11
 
 
-$as_echo "#define PYGOBJECT_MICRO_VERSION 2" >>confdefs.h
+$as_echo "#define PYGOBJECT_MICRO_VERSION 1" >>confdefs.h
 
-PYGOBJECT_MICRO_VERSION=2
+PYGOBJECT_MICRO_VERSION=1
 
 
 ac_config_headers="$ac_config_headers config.h"
@@ -2290,7 +2290,7 @@ else
 fi
 AM_BACKSLASH='\'
 
-am__api_version='1.14'
+am__api_version='1.13'
 
 ac_aux_dir=
 for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
@@ -2766,7 +2766,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='pygobject'
- VERSION='3.10.2'
+ VERSION='3.11.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2817,47 +2817,6 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
 
 
 
-# POSIX will say in a future version that running "rm -f" with no argument
-# is OK; and we want to be able to make that assumption in our Makefile
-# recipes.  So use an aggressive probe to check that the usage we want is
-# actually supported "in the wild" to an acceptable degree.
-# See automake bug#10828.
-# To make any issue more visible, cause the running configure to be aborted
-# by default if the 'rm' program in use doesn't match our expectations; the
-# user can still override this though.
-if rm -f && rm -fr && rm -rf; then : OK; else
-  cat >&2 <<'END'
-Oops!
-
-Your 'rm' program seems unable to run without file operands specified
-on the command line, even when the '-f' option is present.  This is contrary
-to the behaviour of most rm programs out there, and not conforming with
-the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
-
-Please tell bug-automake@gnu.org about your system, including the value
-of your $PATH and any error possibly output before this message.  This
-can help us improve future automake versions.
-
-END
-  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
-    echo 'Configuration will proceed anyway, since you have set the' >&2
-    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
-    echo >&2
-  else
-    cat >&2 <<'END'
-Aborting the configuration process, to ensure you take notice of the issue.
-
-You can download and install GNU coreutils to get an 'rm' implementation
-that behaves properly: <http://www.gnu.org/software/coreutils/>.
-
-If you want to complete the configuration process using your problematic
-'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
-to "yes", and re-run configure.
-
-END
-    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
-  fi
-fi
 
 ACLOCAL="$ACLOCAL $ACLOCAL_FLAGS"
 
@@ -3921,65 +3880,6 @@ 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
 
-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
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
-$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
-if ${am_cv_prog_cc_c_o+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-  # Make sure it works both with $CC and with simple cc.
-  # Following AC_PROG_CC_C_O, we do the test twice because some
-  # compilers refuse to overwrite an existing .o file with -o,
-  # though they will create one.
-  am_cv_prog_cc_c_o=yes
-  for am_i in 1 2; do
-    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
-   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
-   ac_status=$?
-   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-   (exit $ac_status); } \
-         && test -f conftest2.$ac_objext; then
-      : OK
-    else
-      am_cv_prog_cc_c_o=no
-      break
-    fi
-  done
-  rm -f core conftest*
-  unset am_i
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
-$as_echo "$am_cv_prog_cc_c_o" >&6; }
-if test "$am_cv_prog_cc_c_o" != yes; then
-   # Losing compiler, so override with the script.
-   # FIXME: It is wrong to rewrite CC.
-   # But if we don't then we get into trouble of one sort or another.
-   # A longer-term fix would be to have automake use am__CC in this case,
-   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
-   CC="$am_aux_dir/compile $CC"
-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
@@ -12420,65 +12320,6 @@ 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
 
-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
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
-$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
-if ${am_cv_prog_cc_c_o+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-int
-main ()
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-  # Make sure it works both with $CC and with simple cc.
-  # Following AC_PROG_CC_C_O, we do the test twice because some
-  # compilers refuse to overwrite an existing .o file with -o,
-  # though they will create one.
-  am_cv_prog_cc_c_o=yes
-  for am_i in 1 2; do
-    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
-   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
-   ac_status=$?
-   echo "$as_me:$LINENO: \$? = $ac_status" >&5
-   (exit $ac_status); } \
-         && test -f conftest2.$ac_objext; then
-      : OK
-    else
-      am_cv_prog_cc_c_o=no
-      break
-    fi
-  done
-  rm -f core conftest*
-  unset am_i
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
-$as_echo "$am_cv_prog_cc_c_o" >&6; }
-if test "$am_cv_prog_cc_c_o" != yes; then
-   # Losing compiler, so override with the script.
-   # FIXME: It is wrong to rewrite CC.
-   # But if we don't then we get into trouble of one sort or another.
-   # A longer-term fix would be to have automake use am__CC in this case,
-   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
-   CC="$am_aux_dir/compile $CC"
-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
@@ -12607,6 +12448,131 @@ else
 fi
 
 
+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; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5
+$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
+fi
+set dummy $CC; ac_cc=`$as_echo "$2" |
+                     sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+# Make sure it works both with $CC and with simple cc.
+# We do the test twice because some compilers refuse to overwrite an
+# existing .o file with -o, though they will create one.
+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+rm -f conftest2.*
+if { { 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_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } &&
+   test -f conftest2.$ac_objext && { { 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_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; };
+then
+  eval ac_cv_prog_cc_${ac_cc}_c_o=yes
+  if test "x$CC" != xcc; then
+    # Test first that cc exists at all.
+    if { ac_try='cc -c conftest.$ac_ext >&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_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+      ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
+      rm -f conftest2.*
+      if { { 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_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } &&
+        test -f conftest2.$ac_objext && { { 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_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; };
+      then
+       # cc works too.
+       :
+      else
+       # cc exists but doesn't like -o.
+       eval ac_cv_prog_cc_${ac_cc}_c_o=no
+      fi
+    fi
+  fi
+else
+  eval ac_cv_prog_cc_${ac_cc}_c_o=no
+fi
+rm -f core conftest*
+
+fi
+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
+
+fi
+
+# FIXME: we rely on the cache variable name because
+# there is no other way.
+set dummy $CC
+am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
+if test "$am_t" != yes; then
+   # Losing compiler, so override with the script.
+   # FIXME: It is wrong to rewrite CC.
+   # But if we don't then we get into trouble of one sort or another.
+   # A longer-term fix would be to have automake use am__CC in this case,
+   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
+   CC="$am_aux_dir/compile $CC"
+fi
+
 
 
 # option to specify python interpreter to use; this just sets $PYTHON, so that
@@ -13439,7 +13405,7 @@ fi
     PKG_CONFIG=no
   fi
 
-  min_glib_version=2.35.9
+  min_glib_version=2.38.0
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GLIB - version >= $min_glib_version" >&5
 $as_echo_n "checking for GLIB - version >= $min_glib_version... " >&6; }
 
@@ -13784,12 +13750,12 @@ if test -n "$GIO_CFLAGS"; then
     pkg_cv_GIO_CFLAGS="$GIO_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.35.9\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.35.9") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.38.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.38.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GIO_CFLAGS=`$PKG_CONFIG --cflags "gio-2.0 >= 2.35.9" 2>/dev/null`
+  pkg_cv_GIO_CFLAGS=`$PKG_CONFIG --cflags "gio-2.0 >= 2.38.0" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -13801,12 +13767,12 @@ if test -n "$GIO_LIBS"; then
     pkg_cv_GIO_LIBS="$GIO_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.35.9\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.35.9") 2>&5
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.38.0\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.38.0") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GIO_LIBS=`$PKG_CONFIG --libs "gio-2.0 >= 2.35.9" 2>/dev/null`
+  pkg_cv_GIO_LIBS=`$PKG_CONFIG --libs "gio-2.0 >= 2.38.0" 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
   pkg_failed=yes
@@ -13827,14 +13793,14 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gio-2.0 >= 2.35.9" 2>&1`
+               GIO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gio-2.0 >= 2.38.0" 2>&1`
         else
-               GIO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gio-2.0 >= 2.35.9" 2>&1`
+               GIO_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gio-2.0 >= 2.38.0" 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GIO_PKG_ERRORS" >&5
 
-       as_fn_error $? "Package requirements (gio-2.0 >= 2.35.9) were not met:
+       as_fn_error $? "Package requirements (gio-2.0 >= 2.38.0) were not met:
 
 $GIO_PKG_ERRORS
 
@@ -13884,17 +13850,17 @@ if test -n "$GI_CFLAGS"; then
     pkg_cv_GI_CFLAGS="$GI_CFLAGS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 \""; } >&5
-  ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+  ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 ") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GI_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+  pkg_cv_GI_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 " 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
@@ -13907,17 +13873,17 @@ if test -n "$GI_LIBS"; then
     pkg_cv_GI_LIBS="$GI_LIBS"
  elif test -n "$PKG_CONFIG"; then
     if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 \""; } >&5
-  ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+  ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 ") 2>&5
   ac_status=$?
   $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
   test $ac_status = 0; }; then
-  pkg_cv_GI_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+  pkg_cv_GI_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 " 2>/dev/null`
                      test "x$?" != "x0" && pkg_failed=yes
 else
@@ -13939,19 +13905,19 @@ else
         _pkg_short_errors_supported=no
 fi
         if test $_pkg_short_errors_supported = yes; then
-               GI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+               GI_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 " 2>&1`
         else
-               GI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+               GI_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 " 2>&1`
         fi
        # Put the nasty error message in config.log where it belongs
        echo "$GI_PKG_ERRORS" >&5
 
-       as_fn_error $? "Package requirements (glib-2.0 >= 2.35.9
-    gobject-introspection-1.0 >= 1.35.9
+       as_fn_error $? "Package requirements (glib-2.0 >= 2.38.0
+    gobject-introspection-1.0 >= 1.38.0
 ) were not met:
 
 $GI_PKG_ERRORS
@@ -15368,7 +15334,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.10.2, which was
+This file was extended by pygobject $as_me 3.11.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -15435,7 +15401,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.10.2
+pygobject config.status 3.11.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index 002681a..05f54ba 100644 (file)
@@ -17,16 +17,16 @@ m4_define(python3_min_ver, 3.1)
 
 dnl the pygobject version number
 m4_define(pygobject_major_version, 3)
-m4_define(pygobject_minor_version, 10)
-m4_define(pygobject_micro_version, 2)
+m4_define(pygobject_minor_version, 11)
+m4_define(pygobject_micro_version, 1)
 m4_define(pygobject_version, pygobject_major_version.pygobject_minor_version.pygobject_micro_version)
 
 dnl versions of packages we require ...
-m4_define(introspection_required_version, 1.35.9)
+m4_define(introspection_required_version, 1.38.0)
 m4_define(py2cairo_required_version, 1.2.0)
 m4_define(py3cairo_required_version, 1.10.0)
-m4_define(glib_required_version, 2.35.9)
-m4_define(gio_required_version, 2.35.9)
+m4_define(glib_required_version, 2.38.0)
+m4_define(gio_required_version, 2.38.0)
 
 AC_INIT([pygobject],[pygobject_version],
        [http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject],
index 69875b8..0c05343 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
index 20c203c..abc8c4e 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -642,14 +642,14 @@ distclean-compile:
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
 
 .c.obj:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
 
 .c.lo:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
index 6d56bb5..b08e8f1 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -578,14 +578,14 @@ distclean-compile:
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
 
 .c.obj:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
 
 .c.lo:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
index 7b4c595..844bc55 100644 (file)
@@ -198,6 +198,7 @@ PyTypeObject symbol = {                                 \
 
 #define PYGLIB_PyLong_Check PyLong_Check
 #define PYGLIB_PyLong_FromLong PyLong_FromLong
+#define PYGLIB_PyLong_FromSize_t PyLong_FromSize_t
 #define PYGLIB_PyLong_AsLong PyLong_AsLong
 #define PYGLIB_PyLong_AS_LONG(o) PyLong_AS_LONG((PyObject*)(o))
 #define PYGLIB_PyLongObject PyLongObject
index 81b9f3f..b057108 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -535,14 +535,14 @@ distclean-compile:
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
 
 .c.obj:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
 
 .c.lo:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
index 65d5de9..f78b7f5 100644 (file)
@@ -38,7 +38,6 @@ static int  pygobject_clear(PyGObject *self);
 static PyObject * pyg_type_get_bases(GType gtype);
 static inline int pygobject_clear(PyGObject *self);
 static PyObject * pygobject_weak_ref_new(GObject *obj, PyObject *callback, PyObject *user_data);
-static PyObject * pygbinding_weak_ref_new(GObject *obj);
 static inline PyGObjectData * pyg_object_peek_inst_data(GObject *obj);
 static void pygobject_inherit_slots(PyTypeObject *type, PyObject *bases,
                                    gboolean check_for_present);
@@ -242,14 +241,13 @@ build_parameter_list(GObjectClass *class)
        g_free(name);
     }
 
-    g_type_class_unref(class);
-
     if (props)
         g_free(props);
     
     return props_list;
 }
 
+
 static PyObject*
 PyGProps_getattro(PyGProps *self, PyObject *attr)
 {
@@ -266,12 +264,6 @@ PyGProps_getattro(PyGProps *self, PyObject *attr)
     }
 
     class = g_type_class_ref(self->gtype);
-    
-    if (!strcmp(attr_name, "__members__")) {
-        ret = build_parameter_list(class);
-        g_type_class_unref(class);
-       return ret;
-    }
 
     /* g_object_class_find_property recurses through the class hierarchy,
      * so the resulting pspec tells us the owner_type that owns the property
@@ -441,6 +433,25 @@ pygobject_props_get_iter(PyGProps *self)
     return (PyObject *) iter;
 }
 
+static PyObject*
+pygobject_props_dir(PyGProps *self)
+{
+    PyObject *ret;
+    GObjectClass *class;
+
+    class = g_type_class_ref (self->gtype);
+    ret = build_parameter_list (class);
+    g_type_class_unref (class);
+
+    return ret;
+}
+
+static PyMethodDef pygobject_props_methods[] = {
+    { "__dir__", (PyCFunction)pygobject_props_dir, METH_NOARGS},
+    { NULL, NULL, 0}
+};
+
+
 static Py_ssize_t
 PyGProps_length(PyGProps *self)
 {
@@ -1637,7 +1648,7 @@ pygobject_bind_property(PyGObject *self, PyObject *args)
                return NULL;
        }
 
-       return pygbinding_weak_ref_new(G_OBJECT (binding));
+       return pygobject_new (G_OBJECT (binding));
 }
 
 static PyObject *
@@ -2341,54 +2352,6 @@ pygobject_weak_ref_call(PyGObjectWeakRef *self, PyObject *args, PyObject *kw)
     }
 }
 
-
-/* -------------- GBinding Weak Reference ----------------- */
-
-/**
- * BindingWeakRef
- *
- * The BindingWeakRef object is used to manage GBinding objects within python
- * created through GObject.bind_property. It is a sub-class PyGObjectWeakRef so
- * that we can maintain the same reference counting semantics between Python
- * and GObject Binding objects. This gives explicit direct control of the
- * binding lifetime by using the "unbind" method on the BindingWeakRef object
- * along with implicit management based on the lifetime of the source or
- * target objects.
- */
-
-PYGLIB_DEFINE_TYPE("gi._gobject.GBindingWeakRef", PyGBindingWeakRef_Type, PyGObjectWeakRef);
-
-static PyObject *
-pygbinding_weak_ref_new(GObject *obj)
-{
-       PyGObjectWeakRef *self;
-
-       self = PyObject_GC_New(PyGObjectWeakRef, &PyGBindingWeakRef_Type);
-       self->callback = NULL;
-       self->user_data = NULL;
-       self->obj = obj;
-       g_object_weak_ref(self->obj, (GWeakNotify) pygobject_weak_ref_notify, self);
-       return (PyObject *) self;
-}
-
-static PyObject *
-pygbinding_weak_ref_unbind(PyGObjectWeakRef *self, PyObject *args)
-{
-    if (!self->obj) {
-        PyErr_SetString(PyExc_ValueError, "weak binding ref already unreffed");
-        return NULL;
-    }
-    g_object_unref(self->obj);
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyMethodDef pygbinding_weak_ref_methods[] = {
-    { "unbind", (PyCFunction)pygbinding_weak_ref_unbind, METH_NOARGS},
-    { NULL, NULL, 0}
-};
-
-
 static gpointer
 pyobject_copy(gpointer boxed)
 {
@@ -2462,6 +2425,7 @@ pygobject_object_register_types(PyObject *d)
        "Python attributes.";
     PyGProps_Type.tp_traverse = (traverseproc)pygobject_props_traverse;
     PyGProps_Type.tp_iter = (getiterfunc)pygobject_props_get_iter;
+    PyGProps_Type.tp_methods = pygobject_props_methods;
     if (PyType_Ready(&PyGProps_Type) < 0)
         return;
 
@@ -2494,12 +2458,4 @@ pygobject_object_register_types(PyObject *d)
     if (PyType_Ready(&PyGObjectWeakRef_Type) < 0)
         return;
     PyDict_SetItemString(d, "GObjectWeakRef", (PyObject *) &PyGObjectWeakRef_Type);
-
-    PyGBindingWeakRef_Type.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC;
-    PyGBindingWeakRef_Type.tp_doc = "A GBinding weak reference";
-    PyGBindingWeakRef_Type.tp_methods = pygbinding_weak_ref_methods;
-    PyGBindingWeakRef_Type.tp_base = &PyGObjectWeakRef_Type;
-    if (PyType_Ready(&PyGBindingWeakRef_Type) < 0)
-        return;
-    PyDict_SetItemString(d, "GBindingWeakRef", (PyObject *) &PyGBindingWeakRef_Type);
 }
index 713bb6e..2aa2629 100644 (file)
@@ -23,9 +23,7 @@
 from ._gi import \
     VFuncInfo, \
     FunctionInfo, \
-    DIRECTION_IN, \
-    DIRECTION_OUT, \
-    DIRECTION_INOUT
+    Direction
 
 
 #: Module storage for currently registered doc string generator function.
@@ -60,7 +58,7 @@ def generate_doc_string(info):
 def split_function_info_args(info):
     """Split a functions args into a tuple of two lists.
 
-    Note that args marked as DIRECTION_INOUT will be in both lists.
+    Note that args marked as Direction.INOUT will be in both lists.
 
     :Returns:
         Tuple of (in_args, out_args)
@@ -69,9 +67,9 @@ def split_function_info_args(info):
     out_args = []
     for arg in info.get_arguments():
         direction = arg.get_direction()
-        if direction in (DIRECTION_IN, DIRECTION_INOUT):
+        if direction in (Direction.IN, Direction.INOUT):
             in_args.append(arg)
-        if direction in (DIRECTION_OUT, DIRECTION_INOUT):
+        if direction in (Direction.OUT, Direction.INOUT):
             out_args.append(arg)
     return (in_args, out_args)
 
@@ -88,9 +86,23 @@ def _generate_callable_info_function_signature(info):
         elif info.is_constructor():
             in_args_strs = ['cls']
 
-    for arg in in_args:
-        argstr = arg.get_name() + ':' + arg.get_pytype_hint()
-        if arg.is_optional():
+    # Build a lists of indices prior to adding the docs because
+    # because it is possible the index retrieved comes before in
+    # argument being used.
+    ignore_indices = set([arg.get_destroy() for arg in in_args])
+    user_data_indices = set([arg.get_closure() for arg in in_args])
+
+    for i, arg in enumerate(in_args):
+        if i in ignore_indices:
+            continue
+        argstr = arg.get_name()
+        hint = arg.get_pytype_hint()
+        if hint not in ('void',):
+            argstr += ':' + hint
+        if arg.may_be_null() or i in user_data_indices:
+            # allow-none or user_data from a closure
+            argstr += '=None'
+        elif arg.is_optional():
             argstr += '=<optional>'
         in_args_strs.append(argstr)
     in_args_str = ', '.join(in_args_strs)
index 0d30b67..12addbc 100644 (file)
@@ -29,6 +29,7 @@
 #include <pyglib-python-compat.h>
 
 PyObject *PyGIDeprecationWarning;
+PyObject *_PyGIDefaultArgPlaceholder;
 
 static PyObject *
 _wrap_pyg_enum_add (PyObject *self,
@@ -662,6 +663,11 @@ PYGLIB_MODULE_START(_gi, "_gi")
                                                 PyExc_DeprecationWarning, NULL);
 #endif
 
+    /* Place holder object used to fill in "from Python" argument lists
+     * for values not supplied by the caller but support a GI default.
+     */
+    _PyGIDefaultArgPlaceholder = PyObject_New(PyObject, &PyType_Type);
+
     Py_INCREF(PyGIDeprecationWarning);
     PyModule_AddObject(module, "PyGIDeprecationWarning", PyGIDeprecationWarning);
 
index c80a727..fc38f69 100644 (file)
@@ -48,7 +48,7 @@ spawn_async = _glib.spawn_async
 
 
 def threads_init():
-    warnings.warn('Since version 3.10, calling threads_init is no longer needed. '
+    warnings.warn('Since version 3.11, calling threads_init is no longer needed. '
                   'See: https://wiki.gnome.org/PyGObject/Threading',
                   PyGIDeprecationWarning, stacklevel=2)
 
@@ -503,6 +503,10 @@ class MainLoop(GLib.MainLoop):
         def _handler(loop):
             loop.quit()
             loop._quit_by_sigint = True
+            # We handle signal deletion in __del__, return True so GLib
+            # doesn't do the deletion for us.
+            return True
+
         if sys.platform != 'win32':
             # compatibility shim, keep around until we depend on glib 2.36
             if hasattr(GLib, 'unix_signal_add'):
@@ -616,60 +620,41 @@ class Timeout(Source):
 __all__.append('Timeout')
 
 
-def user_data_varargs_shim(callback, user_data, cb_num_args=0):
-    '''Adjust callback and user_data varargs for PyGTK backwards compatibility
-
-    GLib only accepts exactly one user_data argument, but older pygtk
-    traditionally accepted zero or more for some specific functions. For "one
-    argument", use the actual user-supplied callback for efficiency; for all
-    others, rewire it to accept zero or more than one.
-
-    Return the adjusted callback and the real user data to pass to GLib.
-    '''
-    if len(user_data) == 1:
-        return (callback, user_data[0])
-
-    if cb_num_args == 0:
-        return (lambda data: callback(*data), user_data)
-    if cb_num_args == 2:
-        return (lambda a1, a2, data: callback(a1, a2, *data), user_data)
-    raise NotImplementedError('%i number of callback arguments not supported' % cb_num_args)
-
-
 # backwards compatible API
 def idle_add(function, *user_data, **kwargs):
-    (fn, data) = user_data_varargs_shim(function, user_data)
     priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT_IDLE)
-    return GLib.idle_add(priority, fn, data)
+    return GLib.idle_add(priority, function, *user_data)
 
 __all__.append('idle_add')
 
 
 def timeout_add(interval, function, *user_data, **kwargs):
-    (fn, data) = user_data_varargs_shim(function, user_data)
     priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
-    return GLib.timeout_add(priority, interval, fn, data)
+    return GLib.timeout_add(priority, interval, function, *user_data)
 
 __all__.append('timeout_add')
 
 
 def timeout_add_seconds(interval, function, *user_data, **kwargs):
-    (fn, data) = user_data_varargs_shim(function, user_data)
     priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
-    return GLib.timeout_add_seconds(priority, interval, fn, data)
+    return GLib.timeout_add_seconds(priority, interval, function, *user_data)
 
 __all__.append('timeout_add_seconds')
 
 
-# The real GLib API is io_add_watch(IOChannel, priority, condition, callback,
-# user_data). This needs to take into account several historical APIs:
+# The GI GLib API uses g_io_add_watch_full renamed to g_io_add_watch with
+# a signature of (channel, priority, condition, func, user_data).
+# Prior to PyGObject 3.8, this function was statically bound with an API closer to the
+# non-full version with a signature of: (fd, condition, func, *user_data)
+# We need to support this until we are okay with breaking API in a way which is
+# not backwards compatible.
+#
+# This needs to take into account several historical APIs:
 # - calling with an fd as first argument
 # - calling with a Python file object as first argument (we keep this one as
 #   it's really convenient and does not change the number of arguments)
 # - calling without a priority as second argument
-# and the usual "call without or multiple user_data", in which case the
-# callback gets the same user data arguments.
-def io_add_watch(channel, priority_, condition, *cb_and_user_data, **kwargs):
+def _io_add_watch_get_args(channel, priority_, condition, *cb_and_user_data, **kwargs):
     if not isinstance(priority_, int) or isinstance(priority_, GLib.IOCondition):
         warnings.warn('Calling io_add_watch without priority as second argument is deprecated',
                       PyGIDeprecationWarning)
@@ -693,23 +678,28 @@ def io_add_watch(channel, priority_, condition, *cb_and_user_data, **kwargs):
         callback = cb_and_user_data[0]
         user_data = cb_and_user_data[1:]
 
-    (func, user_data) = user_data_varargs_shim(callback, user_data, 2)
-
     # backwards compatibility: Allow calling with fd
     if isinstance(channel, int):
-        func_fdtransform = lambda _, cond, data: func(channel, cond, data)
+        func_fdtransform = lambda _, cond, *data: callback(channel, cond, *data)
         real_channel = GLib.IOChannel.unix_new(channel)
     elif hasattr(channel, 'fileno'):
         # backwards compatibility: Allow calling with Python file
-        func_fdtransform = lambda _, cond, data: func(channel, cond, data)
+        func_fdtransform = lambda _, cond, *data: callback(channel, cond, *data)
         real_channel = GLib.IOChannel.unix_new(channel.fileno())
     else:
         assert isinstance(channel, GLib.IOChannel)
-        func_fdtransform = func
+        func_fdtransform = callback
         real_channel = channel
 
-    return GLib.io_add_watch(real_channel, priority_, condition,
-                             func_fdtransform, user_data)
+    return real_channel, priority_, condition, func_fdtransform, user_data
+
+__all__.append('_io_add_watch_get_args')
+
+
+def io_add_watch(*args, **kwargs):
+    """io_add_watch(channel, priority, condition, func, *user_data) -> event_source_id"""
+    channel, priority, condition, func, user_data = _io_add_watch_get_args(*args, **kwargs)
+    return GLib.io_add_watch(channel, priority, condition, func, *user_data)
 
 __all__.append('io_add_watch')
 
@@ -807,14 +797,14 @@ PollFD = override(PollFD)
 __all__.append('PollFD')
 
 
-# The real GLib API is child_watch_add(priority, pid, callback, data).
-# The old static bindings had the following API which we still need to support
-# for a while:
-#   child_watch_add(pid, callback, data=None, priority=GLib.PRIORITY_DEFAULT)
-# and the usual "call without user_data", in which case the callback does not
-# get an user_data either.
-def child_watch_add(priority_or_pid, pid_or_callback, *args, **kwargs):
-    _unspecified = object()
+# The GI GLib API uses g_child_watch_add_full renamed to g_child_watch_add with
+# a signature of (priority, pid, callback, data).
+# Prior to PyGObject 3.8, this function was statically bound with an API closer to the
+# non-full version with a signature of: (pid, callback, data=None, priority=GLib.PRIORITY_DEFAULT)
+# We need to support this until we are okay with breaking API in a way which is
+# not backwards compatible.
+def _child_watch_add_get_args(priority_or_pid, pid_or_callback, *args, **kwargs):
+    user_data = []
 
     if callable(pid_or_callback):
         warnings.warn('Calling child_watch_add without priority as first argument is deprecated',
@@ -822,35 +812,42 @@ def child_watch_add(priority_or_pid, pid_or_callback, *args, **kwargs):
         pid = priority_or_pid
         callback = pid_or_callback
         if len(args) == 0:
-            user_data = kwargs.get('data', _unspecified)
             priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
         elif len(args) == 1:
-            user_data = args[0]
+            user_data = args
             priority = kwargs.get('priority', GLib.PRIORITY_DEFAULT)
         elif len(args) == 2:
-            user_data = args[0]
+            user_data = [args[0]]
             priority = args[1]
         else:
             raise TypeError('expected at most 4 positional arguments')
     else:
         priority = priority_or_pid
         pid = pid_or_callback
-        if len(args) == 0 or not callable(args[0]):
-            raise TypeError('expected callback as third argument')
-        callback = args[0]
-        if len(args) == 1:
-            user_data = kwargs.get('data', _unspecified)
+        if 'function' in kwargs:
+            callback = kwargs['function']
+            user_data = args
+        elif len(args) > 0 and callable(args[0]):
+            callback = args[0]
+            user_data = args[1:]
         else:
-            user_data = args[1]
+            raise TypeError('expected callback as third argument')
+
+    if 'data' in kwargs:
+        if user_data:
+            raise TypeError('got multiple values for "data" argument')
+        user_data = [kwargs['data']]
+
+    return priority, pid, callback, user_data
+
+# we need this to be accessible for unit testing
+__all__.append('_child_watch_add_get_args')
 
-    if user_data is _unspecified:
-        # we have to call the callback without the user_data argument
-        func = lambda pid, status, data: callback(pid, status)
-        user_data = None
-    else:
-        func = callback
 
-    return GLib.child_watch_add(priority, pid, func, user_data)
+def child_watch_add(*args, **kwargs):
+    """child_watch_add(priority, pid, function, *data)"""
+    priority, pid, function, data = _child_watch_add_get_args(*args, **kwargs)
+    return GLib.child_watch_add(priority, pid, function, *data)
 
 __all__.append('child_watch_add')
 
index b3aad47..83f1481 100644 (file)
@@ -425,21 +425,6 @@ def signal_query(id_or_name, type_=None):
 __all__.append('signal_query')
 
 
-# Check needed for glib versions which annotate signal related methods
-# with a void pointer instead of GObject.Object.
-# See: https://bugzilla.gnome.org/show_bug.cgi?id=685387
-_is_first_signal_arg_void = GObjectModule.signal_stop_emission.get_arguments()[0].get_pytype_hint() == 'void'
-
-
-def _get_instance_for_signal(obj):
-    if not _is_first_signal_arg_void:
-        return obj
-    elif isinstance(obj, GObjectModule.Object):
-        return obj.__gpointer__
-    else:
-        raise TypeError('Unsupported object "%s" for signal function' % obj)
-
-
 class _HandlerBlockManager(object):
     def __init__(self, obj, handler_id):
         self.obj = obj
@@ -449,7 +434,7 @@ class _HandlerBlockManager(object):
         pass
 
     def __exit__(self, exc_type, exc_value, traceback):
-        signal_handler_unblock(self.obj, self.handler_id)
+        GObjectModule.signal_handler_unblock(self.obj, self.handler_id)
 
 
 def signal_handler_block(obj, handler_id):
@@ -461,55 +446,12 @@ def signal_handler_block(obj, handler_id):
       with GObject.signal_handler_block(obj, id):
          pass
     """
-    GObjectModule.signal_handler_block(_get_instance_for_signal(obj), handler_id)
+    GObjectModule.signal_handler_block(obj, handler_id)
     return _HandlerBlockManager(obj, handler_id)
 
 __all__.append('signal_handler_block')
 
 
-if _is_first_signal_arg_void:
-    # The following functions wrap GI functions but coerce the first arg into
-    # something compatible with gpointer
-
-    def _wrap_signal_func(func):
-        @functools.wraps(func)
-        def wrapper(obj, *args, **kwargs):
-            return func(_get_instance_for_signal(obj), *args, **kwargs)
-        return wrapper
-
-    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']
-else:
-    # First signal arg is GObject.Object but we need these as globals for
-    # our GObject.Object class override below
-    signal_handler_disconnect = GObjectModule.signal_handler_disconnect
-    signal_handler_unblock = GObjectModule.signal_handler_unblock
-    signal_handler_disconnect = GObjectModule.signal_handler_disconnect
-    signal_handler_is_connected = GObjectModule.signal_handler_is_connected
-    signal_stop_emission_by_name = GObjectModule.signal_stop_emission_by_name
-
-
 def signal_parse_name(detailed_signal, itype, force_detail_quark):
     """Parse a detailed signal name into (signal_id, detail).
 
@@ -661,12 +603,12 @@ class Object(GObjectModule.Object):
     # Aliases
     #
 
-    disconnect = _signalmethod(signal_handler_disconnect)
-    handler_block = _signalmethod(signal_handler_block)
-    handler_unblock = _signalmethod(signal_handler_unblock)
-    handler_disconnect = _signalmethod(signal_handler_disconnect)
-    handler_is_connected = _signalmethod(signal_handler_is_connected)
-    stop_emission_by_name = _signalmethod(signal_stop_emission_by_name)
+    handler_block = signal_handler_block
+    handler_unblock = _signalmethod(GObjectModule.signal_handler_unblock)
+    disconnect = _signalmethod(GObjectModule.signal_handler_disconnect)
+    handler_disconnect = _signalmethod(GObjectModule.signal_handler_disconnect)
+    handler_is_connected = _signalmethod(GObjectModule.signal_handler_is_connected)
+    stop_emission_by_name = _signalmethod(GObjectModule.signal_stop_emission_by_name)
 
     #
     # Deprecated Methods
@@ -675,7 +617,7 @@ class Object(GObjectModule.Object):
     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)
+        return self.stop_emission_by_name(detailed_signal)
 
     emit_stop_by_name = stop_emission
 
@@ -685,6 +627,25 @@ GObject = Object
 __all__ += ['Object', 'GObject']
 
 
+class Binding(GObjectModule.Binding):
+    def __call__(self):
+        warnings.warn('Using parentheses (binding()) to retrieve the Binding object is no '
+                      'longer needed because the binding is returned directly from "bind_property.',
+                      PyGIDeprecationWarning, stacklevel=2)
+        return self
+
+    def unbind(self):
+        if hasattr(self, '_unbound'):
+            raise ValueError('binding has already been cleared out')
+        else:
+            setattr(self, '_unbound', True)
+            super(Binding, self).unbind()
+
+
+Binding = override(Binding)
+__all__.append('Binding')
+
+
 Property = propertyhelper.Property
 Signal = signalhelper.Signal
 SignalOverride = signalhelper.SignalOverride
index e8a5bf3..7b2d5ab 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
index 7d8a837..6378892 100644 (file)
@@ -894,11 +894,13 @@ _pygi_argument_from_object (PyObject   *object,
 {
     GIArgument arg;
     GITypeTag type_tag;
+    gpointer cleanup_data = NULL;
 
     memset(&arg, 0, sizeof(GIArgument));
     type_tag = g_type_info_get_tag (type_info);
 
-    if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer) ||
+    /* Ignores cleanup data for now. */
+    if (_pygi_marshal_from_py_basic_type (object, &arg, type_tag, transfer, &cleanup_data) ||
             PyErr_Occurred()) {
         return arg;
     }
@@ -1031,12 +1033,12 @@ array_success:
                                                             &arg,
                                                             NULL, /*arg_name*/
                                                             info, /*interface_info*/
-                                                            type_info,
                                                             g_type,
                                                             py_type,
                                                             transfer,
                                                             FALSE, /*copy_reference*/
-                                                            g_struct_info_is_foreign (info));
+                                                            g_struct_info_is_foreign (info),
+                                                            g_type_info_is_pointer (type_info));
 
                     Py_DECREF (py_type);
                     break;
index 2f807f8..14d69b1 100644 (file)
@@ -42,6 +42,7 @@ PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                                              PyGIDirection direction,
                                              gssize c_arg_index,
                                              gssize py_arg_index);
+
 /* cleanup */
 static void
 _pygi_arg_cache_free (PyGIArgCache *cache)
@@ -103,23 +104,17 @@ _callback_cache_free_func (PyGICallbackCache *cache)
 void
 _pygi_callable_cache_free (PyGICallableCache *cache)
 {
-    gssize i;
-
     if (cache == NULL)
         return;
 
     g_slist_free (cache->to_py_args);
     g_slist_free (cache->arg_name_list);
     g_hash_table_destroy (cache->arg_name_hash);
+    g_ptr_array_unref (cache->args_cache);
 
-    for (i = 0; i < cache->n_args; i++) {
-        PyGIArgCache *tmp = cache->args_cache[i];
-        _pygi_arg_cache_free (tmp);
-    }
     if (cache->return_cache != NULL)
         _pygi_arg_cache_free (cache->return_cache);
 
-    g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
     g_slice_free (PyGICallableCache, cache);
 }
 
@@ -299,45 +294,90 @@ _arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
     arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
 }
 
-static gboolean
-_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
+static PyGIArgCache*
+_arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
                                 PyGICallableCache *callable_cache,
-                                GITypeInfo *type_info,
-                                GITransfer transfer,
                                 PyGIDirection direction,
-                                gssize arg_index)
+                                gssize arg_index,
+                                gssize *py_arg_index)
 {
     PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
-    seq_cache->array_type = g_type_info_get_array_type (type_info);
-
-    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
-
     if (seq_cache->len_arg_index >= 0) {
-        PyGIArgCache *child_cache = 
-            callable_cache->args_cache[seq_cache->len_arg_index];
+        PyGIArgCache *child_cache = NULL;
 
+        child_cache = _pygi_callable_cache_get_arg (callable_cache,
+                                                    seq_cache->len_arg_index);
         if (child_cache == NULL) {
             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;
+        } else {
+            /* If the "length" arg cache already exists (the length comes before
+             * the array in the argument list), remove it from the to_py_args list
+             * because it does not belong in "to python" return tuple. The length
+             * will implicitly be a part of the returned Python list.
+             */
+            if (direction & PYGI_DIRECTION_TO_PYTHON) {
+                callable_cache->to_py_args =
+                    g_slist_remove (callable_cache->to_py_args, child_cache);
+            }
+
+            /* This is a case where the arg cache already exists and has been
+             * setup by another array argument sharing the same length argument.
+             * See: gi_marshalling_tests_multi_array_key_value_in
+             */
+            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
+                return child_cache;
         }
 
-        if (seq_cache->len_arg_index < arg_index)
-            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE;
-        else
-            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+        /* There is a length argument for this array, so increment the number
+         * of "to python" child arguments when applicable.
+         */
+        if (direction & PYGI_DIRECTION_TO_PYTHON)
+             callable_cache->n_to_py_child_args++;
 
+        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
         child_cache->direction = direction;
         child_cache->to_py_marshaller = NULL;
         child_cache->from_py_marshaller = NULL;
 
-        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
+        /* ugly edge case code:
+         *
+         * When the length comes before the array parameter we need to update
+         * indexes of arguments after the index argument.
+         */
+        if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
+            gssize i;
+            (*py_arg_index) -= 1;
+            callable_cache->n_py_args -= 1;
+
+            for (i = seq_cache->len_arg_index + 1;
+                   i < _pygi_callable_cache_args_len (callable_cache); i++) {
+                PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
+                if (update_cache == NULL)
+                    break;
+
+                update_cache->py_arg_index -= 1;
+            }
+        }
+
+        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
+        return child_cache;
     }
 
-    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
+    return NULL;
+}
 
+static gboolean
+_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
+                                PyGICallableCache *callable_cache,
+                                GITypeInfo *type_info,
+                                GITransfer transfer,
+                                PyGIDirection direction,
+                                gssize arg_index)
+{
+    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+    seq_cache->array_type = g_type_info_get_array_type (type_info);
+    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
+    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
     return TRUE;
 }
 
@@ -350,35 +390,9 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                               gssize arg_index)
 {
     PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+    seq_cache->array_type = g_type_info_get_array_type (type_info);
     arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
     arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
-
-    seq_cache->array_type = g_type_info_get_array_type (type_info);
-
-    if (seq_cache->len_arg_index >= 0) {
-        PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
-        if (seq_cache->len_arg_index < arg_index)
-             callable_cache->n_to_py_child_args++;
-
-        if (child_cache != NULL) {
-            callable_cache->to_py_args =
-                g_slist_remove (callable_cache->to_py_args, child_cache);
-
-            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
-                child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE)
-                return TRUE;
-        } else {
-            child_cache = _arg_cache_alloc ();
-        }
-
-        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
-        child_cache->direction = direction;
-        child_cache->to_py_marshaller = NULL;
-        child_cache->from_py_marshaller = NULL;
-
-        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
-    }
-
     return TRUE;
 }
 
@@ -509,14 +523,17 @@ _arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
         PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
         user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
         user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
-        callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
+        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
+        _pygi_callable_cache_set_arg (callable_cache, callback_cache->user_data_index,
+                                      user_data_arg_cache);
     }
 
     if (callback_cache->destroy_notify_index >= 0) {
         PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
         destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
         destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
-        callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
+        _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
+                                      destroy_arg_cache);
     }
     arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
     arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
@@ -589,31 +606,31 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
 
     switch (info_type) {
         case GI_INFO_TYPE_UNION:
-            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
 
-            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
 
             break;
         case GI_INFO_TYPE_BOXED:
         case GI_INFO_TYPE_STRUCT:
-            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                           iface_info,
                                                           transfer);
 
-            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                         iface_info,
                                                         transfer);
             break;
         case GI_INFO_TYPE_OBJECT:
         case GI_INFO_TYPE_INTERFACE:
-            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
 
-            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
 
             break;
@@ -621,7 +638,7 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
             {
                 PyGICallbackCache *callback_cache;
 
-                if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+                if (direction & PYGI_DIRECTION_TO_PYTHON) {
                     _arg_cache_to_py_interface_callback_setup ();
                     return NULL;
                 }
@@ -635,24 +652,24 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                 if (arg_cache == NULL)
                     return NULL;
 
-                if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+                if (direction & PYGI_DIRECTION_FROM_PYTHON)
                     _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);
 
                 break;
             }
         case GI_INFO_TYPE_ENUM:
-            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
 
-            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
 
             break;
         case GI_INFO_TYPE_FLAGS:
-            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
 
-            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+            if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
 
             break;
@@ -676,10 +693,30 @@ _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
     return arg_cache;
 }
 
+/* _arg_info_default_value
+ * info:
+ * arg: (out): GIArgument to fill in with default value.
+ *
+ * This is currently a place holder API which only supports "allow-none" pointer args.
+ * Once defaults are part of the GI API, we can replace this with: g_arg_info_default_value
+ * https://bugzilla.gnome.org/show_bug.cgi?id=558620
+ *
+ * Returns: TRUE if the given argument supports a default value and was filled in.
+ */
+static gboolean
+_arg_info_default_value (GIArgInfo *info, GIArgument *arg)
+{
+    if (g_arg_info_may_be_null (info)) {
+        arg->v_pointer = NULL;
+        return TRUE;
+    }
+    return FALSE;
+}
+
 PyGIArgCache *
 _arg_cache_new (GITypeInfo *type_info,
                 PyGICallableCache *callable_cache,
-                GIArgInfo *arg_info,
+                GIArgInfo *arg_info,     /* may be null */
                 GITransfer transfer,
                 PyGIDirection direction,
                 gssize c_arg_index,
@@ -702,10 +739,10 @@ _arg_cache_new (GITypeInfo *type_info,
            if (arg_cache == NULL)
                break;
 
-           if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_void_setup (arg_cache);
 
-           if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_void_setup (arg_cache);
 
            break;
@@ -726,10 +763,10 @@ _arg_cache_new (GITypeInfo *type_info,
            if (arg_cache == NULL)
                break;
 
-           if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_basic_type_setup (arg_cache);
 
-           if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_basic_type_setup (arg_cache);
 
            break;
@@ -739,10 +776,10 @@ _arg_cache_new (GITypeInfo *type_info,
            if (arg_cache == NULL)
                break;
 
-           if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_utf8_setup (arg_cache, transfer);
 
-           if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_utf8_setup (arg_cache, transfer);
 
            break;
@@ -758,7 +795,7 @@ _arg_cache_new (GITypeInfo *type_info,
                if (arg_cache == NULL)
                    break;
 
-               if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+               if (direction & PYGI_DIRECTION_FROM_PYTHON)
                    _arg_cache_from_py_array_setup (arg_cache,
                                                    callable_cache,
                                                    type_info,
@@ -766,7 +803,7 @@ _arg_cache_new (GITypeInfo *type_info,
                                                    direction,
                                                    c_arg_index);
 
-               if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+               if (direction & PYGI_DIRECTION_TO_PYTHON)
                    _arg_cache_to_py_array_setup (arg_cache,
                                                  callable_cache,
                                                  type_info,
@@ -774,31 +811,11 @@ _arg_cache_new (GITypeInfo *type_info,
                                                  direction,
                                                  c_arg_index);
 
-               /* ugly edge case code:
-                *  
-                * length can come before the array parameter which means we
-                * need to update indexes if this happens
-                */ 
-               if (seq_cache->len_arg_index > -1 &&
-                   callable_cache->args_cache[seq_cache->len_arg_index]->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
-                   gssize i;
-                   PyGIArgCache *child_cache =
-                       callable_cache->args_cache[seq_cache->len_arg_index];
-
-                   child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
-                   py_arg_index -= 1;
-                   callable_cache->n_py_args -= 1;
-
-                   for (i = seq_cache->len_arg_index + 1; 
-                          i < callable_cache->n_args; 
-                            i++) {
-                       PyGIArgCache *update_cache = callable_cache->args_cache[i];
-                       if (update_cache == NULL)
-                           break;
-
-                       update_cache->py_arg_index -= 1;
-                   }
-               }
+               _arg_cache_array_len_arg_setup (arg_cache,
+                                               callable_cache,
+                                               direction,
+                                               c_arg_index,
+                                               &py_arg_index);
 
                break;
            }
@@ -814,10 +831,10 @@ _arg_cache_new (GITypeInfo *type_info,
                if (arg_cache == NULL)
                    break;
 
-               if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+               if (direction & PYGI_DIRECTION_FROM_PYTHON)
                    _arg_cache_from_py_glist_setup (arg_cache, transfer);
 
-               if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+               if (direction & PYGI_DIRECTION_TO_PYTHON)
                    _arg_cache_to_py_glist_setup (arg_cache, transfer);
 
 
@@ -835,10 +852,10 @@ _arg_cache_new (GITypeInfo *type_info,
                if (arg_cache == NULL)
                    break;
 
-               if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+               if (direction & PYGI_DIRECTION_FROM_PYTHON)
                    _arg_cache_from_py_gslist_setup (arg_cache, transfer);
 
-               if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+               if (direction & PYGI_DIRECTION_TO_PYTHON)
                    _arg_cache_to_py_gslist_setup (arg_cache, transfer);
 
                break;
@@ -852,10 +869,10 @@ _arg_cache_new (GITypeInfo *type_info,
            if (arg_cache == NULL)
                    break;
 
-           if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_ghash_setup (arg_cache);
 
-           if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
+           if (direction & PYGI_DIRECTION_TO_PYTHON) {
                _arg_cache_to_py_ghash_setup (arg_cache);
            }
 
@@ -879,10 +896,10 @@ _arg_cache_new (GITypeInfo *type_info,
            if (arg_cache == NULL)
                break;
 
-           if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_FROM_PYTHON)
                _arg_cache_from_py_gerror_setup (arg_cache);
 
-           if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
+           if (direction & PYGI_DIRECTION_TO_PYTHON)
                _arg_cache_to_py_gerror_setup (arg_cache);
 
            break;
@@ -897,43 +914,41 @@ _arg_cache_new (GITypeInfo *type_info,
         arg_cache->is_pointer = g_type_info_is_pointer (type_info);
         g_base_info_ref ( (GIBaseInfo *) type_info);
         arg_cache->type_info = type_info;
+
+        if (arg_info != NULL) {
+            if (!arg_cache->has_default) {
+                /* It is possible has_default was set somewhere else */
+                arg_cache->has_default = _arg_info_default_value (arg_info,
+                                                                  &arg_cache->default_value);
+            }
+            arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
+            arg_cache->allow_none = g_arg_info_may_be_null (arg_info);
+
+            if (type_tag == GI_TYPE_TAG_INTERFACE || type_tag == GI_TYPE_TAG_ARRAY)
+                arg_cache->is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
+            else
+                arg_cache->is_caller_allocates = FALSE;
+        }
     }
 
     return arg_cache;
 }
 
-static void
-_arg_name_list_generate (PyGICallableCache *callable_cache)
+static PyGIDirection
+_pygi_get_direction (PyGICallableCache *callable_cache, GIDirection gi_direction)
 {
-    GSList * arg_name_list = NULL;
-    int i;
-
-    if (callable_cache->arg_name_hash == NULL) {
-        callable_cache->arg_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
+    /* For vfuncs and callbacks our marshalling directions are reversed */
+    if (gi_direction == GI_DIRECTION_INOUT) {
+        return PYGI_DIRECTION_BIDIRECTIONAL;
+    } else if (gi_direction == GI_DIRECTION_IN) {
+        if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
+            return PYGI_DIRECTION_TO_PYTHON;
+        return PYGI_DIRECTION_FROM_PYTHON;
     } else {
-        g_hash_table_remove_all (callable_cache->arg_name_hash);
-    }
-
-    for (i=0; i < callable_cache->n_args; i++) {
-        PyGIArgCache *arg_cache = NULL;
-
-        arg_cache = callable_cache->args_cache[i];
-
-        if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
-            arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
-                (arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON ||
-                 arg_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL)) {
-
-            gpointer arg_name = (gpointer)arg_cache->arg_name;
-
-            arg_name_list = g_slist_prepend (arg_name_list, arg_name);
-            if (arg_name != NULL) {
-                g_hash_table_insert (callable_cache->arg_name_hash, arg_name, arg_name);
-            }
-        }
+        if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
+            return PYGI_DIRECTION_FROM_PYTHON;
+        return PYGI_DIRECTION_TO_PYTHON;
     }
-
-    callable_cache->arg_name_list = g_slist_reverse (arg_name_list);
 }
 
 /* Generate the cache for the callable's arguments */
@@ -948,11 +963,8 @@ _args_cache_generate (GICallableInfo *callable_info,
     PyGIArgCache *return_cache;
     PyGIDirection return_direction;
 
-    /* determine if we are marshalling the return to or from python */
-    if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
-        return_direction = PYGI_DIRECTION_FROM_PYTHON;
-    else
-        return_direction = PYGI_DIRECTION_TO_PYTHON;
+    /* Return arguments are always considered out */
+    return_direction = _pygi_get_direction (callable_cache, GI_DIRECTION_OUT);
 
     /* cache the return arg */
     return_info =
@@ -979,10 +991,6 @@ _args_cache_generate (GICallableInfo *callable_info,
             callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) {
         GIInterfaceInfo *interface_info;
         PyGIArgCache *instance_cache;
-        PyGIDirection instance_direction;
-
-        instance_direction = PYGI_DIRECTION_FROM_PYTHON;
-
 
         interface_info = g_base_info_get_container ( (GIBaseInfo *)callable_info);
 
@@ -991,18 +999,20 @@ _args_cache_generate (GICallableInfo *callable_info,
                                           callable_cache,
                                           NULL,
                                           GI_TRANSFER_NOTHING,
-                                          instance_direction,
+                                          PYGI_DIRECTION_FROM_PYTHON,
                                           arg_index,
                                           0);
 
-        /* FIXME: marshal interfaces from_py */
-        instance_cache->from_py_marshaller = _pygi_marshal_from_py_interface_instance;
         g_base_info_unref ( (GIBaseInfo *)interface_info);
 
         if (instance_cache == NULL)
             return FALSE;
 
-        callable_cache->args_cache[arg_index] = instance_cache;
+        /* Because we are not supplied a GITypeInfo for instance arguments,
+         * assume some defaults. */
+        instance_cache->is_pointer = TRUE;
+
+        _pygi_callable_cache_set_arg (callable_cache, arg_index, instance_cache);
 
         arg_index++;
         callable_cache->n_from_py_args++;
@@ -1010,130 +1020,153 @@ _args_cache_generate (GICallableInfo *callable_info,
     }
 
 
-    for (i=0; arg_index < callable_cache->n_args; arg_index++, i++) {
+    for (i=0; arg_index < _pygi_callable_cache_args_len (callable_cache); arg_index++, i++) {
         PyGIArgCache *arg_cache = NULL;
         GIArgInfo *arg_info;
-        GITypeInfo *type_info;
-        GIDirection gi_direction;
         PyGIDirection direction;
-        GITransfer transfer;
-        GITypeTag type_tag;
-        gboolean is_caller_allocates = FALSE;
-        gssize py_arg_index = -1;
 
         arg_info = g_callable_info_get_arg (callable_info, i);
 
         if (g_arg_info_get_closure (arg_info) == i) {
 
             arg_cache = _arg_cache_alloc ();
-            callable_cache->args_cache[arg_index] = arg_cache;
+            _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
 
-            arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
-            arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
+            direction = PYGI_DIRECTION_FROM_PYTHON;
+            arg_cache->direction = direction;
             arg_cache->meta_type = PYGI_META_ARG_TYPE_CLOSURE;
             arg_cache->c_arg_index = i;
 
             callable_cache->n_from_py_args++;
 
-            g_base_info_unref ( (GIBaseInfo *)arg_info);
+        } else {
+            GITypeInfo *type_info;
+
+            direction = _pygi_get_direction (callable_cache,
+                                             g_arg_info_get_direction (arg_info));
+            type_info = g_arg_info_get_type (arg_info);
+
+            /* must be an child arg filled in by its owner
+             * and continue
+             * fill in it's c_arg_index, add to the in count
+             */
+            arg_cache = _pygi_callable_cache_get_arg (callable_cache, arg_index);
+            if (arg_cache != NULL) {
+                if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
+                    arg_cache->py_arg_index = callable_cache->n_py_args;
+                    callable_cache->n_py_args++;
+                }
 
-            continue;
-        }
+                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+                    arg_cache->c_arg_index = callable_cache->n_from_py_args;
+                    callable_cache->n_from_py_args++;
+                }
 
-        /* For vfuncs and callbacks our marshalling directions
-           are reversed */
-        gi_direction = g_arg_info_get_direction (arg_info);
-        if (gi_direction == GI_DIRECTION_INOUT) {
-            direction = PYGI_DIRECTION_BIDIRECTIONAL;
-        } else if (gi_direction == GI_DIRECTION_IN) {
-            direction = PYGI_DIRECTION_FROM_PYTHON;
-            if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
-                direction = PYGI_DIRECTION_TO_PYTHON;
-        } else {
-            direction = PYGI_DIRECTION_TO_PYTHON;
-            if (callable_cache->function_type == PYGI_FUNCTION_TYPE_CALLBACK)
-                direction = PYGI_DIRECTION_FROM_PYTHON;
-        }
+                if (direction & PYGI_DIRECTION_TO_PYTHON) {
+                    callable_cache->n_to_py_args++;
+                }
 
-        transfer = g_arg_info_get_ownership_transfer (arg_info);
-        type_info = g_arg_info_get_type (arg_info);
-        type_tag = g_type_info_get_tag (type_info);
+                arg_cache->type_tag = g_type_info_get_tag (type_info);
 
-        if (type_tag == GI_TYPE_TAG_INTERFACE || type_tag == GI_TYPE_TAG_ARRAY)
-            is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
+            } else {
+                GITransfer transfer;
+                gssize py_arg_index = -1;
+                transfer = g_arg_info_get_ownership_transfer (arg_info);
 
-        /* must be an child arg filled in by its owner
-         * and continue
-         * fill in it's c_arg_index, add to the in count
-         */
-        if (callable_cache->args_cache[arg_index] != NULL) {
-            arg_cache = callable_cache->args_cache[arg_index];
-            if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) {
-                arg_cache->py_arg_index = callable_cache->n_py_args;
-                callable_cache->n_py_args++;
-            }
+                if (direction & PYGI_DIRECTION_FROM_PYTHON) {
+                    py_arg_index = callable_cache->n_py_args;
+                    callable_cache->n_from_py_args++;
+                    callable_cache->n_py_args++;
+                }
 
-            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
-                arg_cache->c_arg_index = callable_cache->n_from_py_args;
-                callable_cache->n_from_py_args++;
-            }
+                arg_cache =
+                    _arg_cache_new (type_info,
+                                    callable_cache,
+                                    arg_info,
+                                    transfer,
+                                    direction,
+                                    arg_index,
+                                    py_arg_index);
 
-            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
-                callable_cache->n_to_py_args++;
-                callable_cache->n_to_py_child_args++;
-            }
+                if (arg_cache == NULL) {
+                    g_base_info_unref( (GIBaseInfo *)type_info);
+                    g_base_info_unref( (GIBaseInfo *)arg_info);
+                    return FALSE;
+                }
 
-            arg_cache->type_tag = g_type_info_get_tag (type_info);
+
+                if (direction & PYGI_DIRECTION_TO_PYTHON) {
+                    callable_cache->n_to_py_args++;
+
+                    callable_cache->to_py_args =
+                        g_slist_append (callable_cache->to_py_args, arg_cache);
+                }
+
+                _pygi_callable_cache_set_arg (callable_cache, arg_index, arg_cache);
+            }
 
             g_base_info_unref (type_info);
-            g_base_info_unref ( (GIBaseInfo *)arg_info);
-            continue;
         }
 
-        if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
-            py_arg_index = callable_cache->n_py_args;
-            callable_cache->n_from_py_args++;
-            callable_cache->n_py_args++;
-        }
+        /* Ensure arguments always have a name when available */
+        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
 
-        arg_cache =
-            _arg_cache_new (type_info,
-                            callable_cache,
-                            arg_info,
-                            transfer,
-                            direction,
-                            arg_index,
-                            py_arg_index);
+        g_base_info_unref ( (GIBaseInfo *)arg_info);
 
-        if (arg_cache == NULL)
-            goto arg_err;
+    }
 
-        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
-        arg_cache->allow_none = g_arg_info_may_be_null(arg_info);
-        arg_cache->is_caller_allocates = is_caller_allocates;
+    if (callable_cache->arg_name_hash == NULL) {
+        callable_cache->arg_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
+    } else {
+        g_hash_table_remove_all (callable_cache->arg_name_hash);
+    }
+    callable_cache->n_py_required_args = 0;
+    callable_cache->user_data_varargs_index = -1;
 
-        if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
-            callable_cache->n_to_py_args++;
+    gssize last_explicit_arg_index = -1;
 
-            if (arg_cache == NULL)
-                goto arg_err;
+    /* Reverse loop through all the arguments to setup arg_name_list/hash
+     * and find the number of required arguments */
+    for (i=((gssize)_pygi_callable_cache_args_len (callable_cache))-1; i >= 0; i--) {
+        PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache, i);
 
-            callable_cache->to_py_args =
-                g_slist_append (callable_cache->to_py_args, arg_cache);
-        }
+        if (arg_cache->meta_type != PYGI_META_ARG_TYPE_CHILD &&
+                arg_cache->meta_type != PYGI_META_ARG_TYPE_CLOSURE &&
+                arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
 
-        callable_cache->args_cache[arg_index] = arg_cache;
-        g_base_info_unref( (GIBaseInfo *)type_info);
-        g_base_info_unref( (GIBaseInfo *)arg_info);
+            /* Setup arg_name_list and arg_name_hash */
+            gpointer arg_name = (gpointer)arg_cache->arg_name;
+            callable_cache->arg_name_list = g_slist_prepend (callable_cache->arg_name_list,
+                                                             arg_name);
+            if (arg_name != NULL) {
+                g_hash_table_insert (callable_cache->arg_name_hash,
+                                     arg_name,
+                                     GINT_TO_POINTER(i));
+            }
 
-        continue;
-arg_err:
-        g_base_info_unref( (GIBaseInfo *)type_info);
-        g_base_info_unref( (GIBaseInfo *)arg_info);
-        return FALSE;
-    }
+            /* The first tail argument without a default will force all the preceding
+             * argument defaults off. This limits support of default args to the
+             * tail of an args list.
+             */
+            if (callable_cache->n_py_required_args > 0) {
+                arg_cache->has_default = FALSE;
+                callable_cache->n_py_required_args += 1;
+            } else if (!arg_cache->has_default) {
+                callable_cache->n_py_required_args += 1;
+            }
+
+            if (last_explicit_arg_index == -1) {
+                last_explicit_arg_index = i;
 
-    _arg_name_list_generate (callable_cache);
+                /* If the last "from python" argument in the args list is a child
+                 * with pyarg (currently only callback user_data). Set it to eat
+                 * variable args in the callable cache.
+                 */
+                if (arg_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_WITH_PYARG)
+                    callable_cache->user_data_varargs_index = i;
+            }
+        }
+    }
 
     return TRUE;
 }
@@ -1141,6 +1174,7 @@ arg_err:
 PyGICallableCache *
 _pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
 {
+    gint n_args;
     PyGICallableCache *cache;
     GIInfoType type = g_base_info_get_type ( (GIBaseInfo *)callable_info);
 
@@ -1185,15 +1219,17 @@ _pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback)
         cache->function_type = PYGI_FUNCTION_TYPE_METHOD;
     }
 
-    cache->n_args = g_callable_info_get_n_args (callable_info);
+    n_args = g_callable_info_get_n_args (callable_info);
 
     /* if we are a method or vfunc make sure the instance parameter is counted */
     if (cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
             cache->function_type == PYGI_FUNCTION_TYPE_VFUNC)
-        cache->n_args++;
+        n_args++;
 
-    if (cache->n_args > 0)
-        cache->args_cache = g_slice_alloc0 (cache->n_args * sizeof (PyGIArgCache *));
+    if (n_args >= 0) {
+        cache->args_cache = g_ptr_array_new_full (n_args, (GDestroyNotify) _pygi_arg_cache_free);
+        g_ptr_array_set_size (cache->args_cache, n_args);
+    }
 
     if (!_args_cache_generate (callable_info, cache))
         goto err;
index 6e5e0ab..745d0a1 100644 (file)
@@ -36,7 +36,8 @@ typedef gboolean (*PyGIMarshalFromPyFunc) (PyGIInvokeState   *state,
                                            PyGICallableCache *callable_cache,
                                            PyGIArgCache      *arg_cache,
                                            PyObject          *py_arg,
-                                           GIArgument        *arg);
+                                           GIArgument        *arg,
+                                           gpointer          *cleanup_data);
 
 typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState   *state,
                                           PyGICallableCache *callable_cache,
@@ -45,6 +46,7 @@ typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState   *state,
 
 typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
                                         PyGIArgCache    *arg_cache,
+                                        PyObject        *py_arg, /* always NULL for to_py cleanup */
                                         gpointer         data,
                                         gboolean         was_processed);
 
@@ -56,10 +58,6 @@ typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
  *  - PYGI_META_ARG_TYPE_CHILD - Children without python argument are
  *    ignored by the marshallers and handled directly by their parents
  *    marshaller.
- *  - PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE -Sometimes children arguments
- *    come before the parent.  In these cases they need to be flagged
- *    so that the argument list counts must be updated for the cache to
- *    be valid
  *  - Children with pyargs (PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) are processed
  *    the same as other child args but also have an index into the 
  *    python parameters passed to the invoker
@@ -67,7 +65,6 @@ typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
 typedef enum {
     PYGI_META_ARG_TYPE_PARENT,
     PYGI_META_ARG_TYPE_CHILD,
-    PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE,
     PYGI_META_ARG_TYPE_CHILD_WITH_PYARG,
     PYGI_META_ARG_TYPE_CLOSURE,
 } PyGIMetaArgType;
@@ -95,9 +92,9 @@ typedef enum {
  * marshalled into Python or from Python.
  */
 typedef enum {
-    PYGI_DIRECTION_TO_PYTHON,
-    PYGI_DIRECTION_FROM_PYTHON,
-    PYGI_DIRECTION_BIDIRECTIONAL
+    PYGI_DIRECTION_TO_PYTHON     = 1 << 0,
+    PYGI_DIRECTION_FROM_PYTHON   = 1 << 1,
+    PYGI_DIRECTION_BIDIRECTIONAL = PYGI_DIRECTION_TO_PYTHON | PYGI_DIRECTION_FROM_PYTHON
  } PyGIDirection;
 
 
@@ -110,6 +107,7 @@ struct _PyGIArgCache
     gboolean is_caller_allocates;
     gboolean is_skipped;
     gboolean allow_none;
+    gboolean has_default;
 
     PyGIDirection direction;
     GITransfer transfer;
@@ -126,6 +124,9 @@ struct _PyGIArgCache
 
     gssize c_arg_index;
     gssize py_arg_index;
+
+    /* Set when has_default is true. */
+    GIArgument default_value;
 };
 
 typedef struct _PyGISequenceCache
@@ -172,18 +173,34 @@ struct _PyGICallableCache
     PyGIFunctionType function_type;
 
     PyGIArgCache *return_cache;
-    PyGIArgCache **args_cache;
+    GPtrArray *args_cache;
     GSList *to_py_args;
     GSList *arg_name_list; /* for keyword arg matching */
     GHashTable *arg_name_hash;
 
-    /* counts */
+    /* Index of user_data arg that can eat variable args passed to a callable. */
+    gssize user_data_varargs_index;
+
+    /* Number of in args passed to g_function_info_invoke.
+     * This is used for the length of PyGIInvokeState.in_args */
     gssize n_from_py_args;
+
+    /* Number of out args passed to g_function_info_invoke.
+     * This is used for the length of PyGIInvokeState.out_values */
     gssize n_to_py_args;
+
+    /* Number of out args for g_function_info_invoke that will be skipped
+     * when marshaling to Python due to them being implicitly available
+     * (list/array length).
+     */
     gssize n_to_py_child_args;
 
-    gssize n_args;
+    /* Number of Python arguments expected for invoking the gi function. */
     gssize n_py_args;
+
+    /* Minimum number of args required to call the callable from Python.
+     * This count does not include args with defaults. */
+    gssize n_py_required_args;
 };
 
 void _pygi_arg_cache_clear     (PyGIArgCache *cache);
@@ -192,6 +209,18 @@ void _pygi_callable_cache_free     (PyGICallableCache *cache);
 PyGICallableCache *_pygi_callable_cache_new (GICallableInfo *callable_info,
                                              gboolean is_ccallback);
 
+#define _pygi_callable_cache_args_len(cache) ((cache)->args_cache)->len
+
+inline static PyGIArgCache *
+_pygi_callable_cache_get_arg (PyGICallableCache *cache, guint index) {
+    return (PyGIArgCache *) g_ptr_array_index (cache->args_cache, index);
+}
+
+inline static void
+_pygi_callable_cache_set_arg (PyGICallableCache *cache, guint index, PyGIArgCache *arg_cache) {
+    cache->args_cache->pdata[index] = arg_cache;
+}
+
 G_END_DECLS
 
 #endif /* __PYGI_CACHE_H__ */
index 2f5548a..5df4713 100644 (file)
@@ -369,11 +369,33 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args,
                     g_type_info_is_pointer (&arg_type)) {
 
                 if (user_data == NULL) {
+                    /* user_data can be NULL for connect functions which don't accept
+                     * user_data or as the default for user_data in the middle of function
+                     * arguments.
+                     */
                     Py_INCREF (Py_None);
                     value = Py_None;
                 } else {
-                    value = user_data;
-                    Py_INCREF (value);
+                    /* Extend the callbacks args with user_data as variable args. */
+                    int j, user_data_len;
+                    PyObject *py_user_data = user_data;
+
+                    if (!PyTuple_Check (py_user_data)) {
+                        PyErr_SetString (PyExc_TypeError, "expected tuple for callback user_data");
+                        goto error;
+                    }
+
+                    user_data_len = PyTuple_Size (py_user_data);
+                    _PyTuple_Resize (py_args, n_args + user_data_len - 1);
+                    for (j = 0; j < user_data_len; j++, n_in_args++) {
+                        value = PyTuple_GetItem (py_user_data, j);
+                        Py_INCREF (value);
+                        PyTuple_SET_ITEM (*py_args, n_in_args, value);
+                    }
+                    /* We can assume user_data args are never going to be inout,
+                     * so just continue here.
+                     */
+                    continue;
                 }
             } else if (direction == GI_DIRECTION_IN &&
                        arg_tag == GI_TYPE_TAG_INTERFACE) {
@@ -631,10 +653,10 @@ _pygi_make_native_closure (GICallableInfo* info,
     closure = g_slice_new0 (PyGICClosure);
     closure->info = (GICallableInfo *) g_base_info_ref ( (GIBaseInfo *) info);
     closure->function = py_function;
-    closure->user_data = py_user_data ? py_user_data : Py_None;
+    closure->user_data = py_user_data;
 
     Py_INCREF (py_function);
-    Py_INCREF (closure->user_data);
+    Py_XINCREF (closure->user_data);
 
     fficlosure =
         g_callable_info_prepare_closure (info, &closure->cif, _pygi_closure_handle,
index 7164ff9..0dd67b7 100644 (file)
@@ -2,6 +2,7 @@
  * vim: tabstop=4 shiftwidth=4 expandtab
  *
  * Copyright (C) 2005-2009 Johan Dahlin <johan@gnome.org>
+ * Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
  *
  *   pygi-info.c: GI.*Info wrappers.
  *
@@ -53,9 +54,121 @@ _generate_doc_string(PyGIBaseInfo *self)
     return PyObject_CallFunctionObjArgs (_py_generate_doc_string, self, NULL);
 }
 
+static PyObject *
+_get_info_string (PyGIBaseInfo *self,
+                  const gchar* (*get_info_string)(GIBaseInfo*))
+{
+    const gchar *value = get_info_string ((GIBaseInfo*)self->info);
+    if (value == NULL) {
+        Py_RETURN_NONE;
+    }
+    return PYGLIB_PyUnicode_FromString (value);
+}
+
+static PyObject *
+_get_child_info (PyGIBaseInfo *self,
+                 GIBaseInfo* (*get_child_info)(GIBaseInfo*))
+{
+    GIBaseInfo *info;
+    PyObject *py_info;
+
+    info = get_child_info ((GIBaseInfo*)self->info);
+    if (info == NULL) {
+        Py_RETURN_NONE;
+    }
+
+    py_info = _pygi_info_new (info);
+    g_base_info_unref (info);
+    return py_info;
+}
+
+
+static PyObject *
+_get_child_info_by_name (PyGIBaseInfo *self, PyObject *py_name,
+                         GIBaseInfo* (*get_child_info_by_name)(GIBaseInfo*, const gchar*))
+{
+    GIBaseInfo *info;
+    PyObject *py_info;
+    char *name;
+
+    if (!PYGLIB_PyUnicode_Check (py_name)) {
+        PyErr_SetString (PyExc_TypeError, "expected string name");
+        return NULL;
+    }
+
+    name = PYGLIB_PyUnicode_AsString (py_name);
+    info = get_child_info_by_name ((GIObjectInfo*)self->info, name);
+    if (info == NULL) {
+        Py_RETURN_NONE;
+    }
+
+    py_info = _pygi_info_new (info);
+    g_base_info_unref (info);
+    return py_info;
+}
+
+
+/* _make_infos_tuple
+ *
+ * Build a tuple from the common API pattern in GI of having a
+ * function which returns a count and an indexed GIBaseInfo
+ * in the range of 0 to count;
+ */
+static PyObject *
+_make_infos_tuple (PyGIBaseInfo *self,
+                   gint (*get_n_infos)(GIBaseInfo*),
+                   GIBaseInfo* (*get_info)(GIBaseInfo*, gint))
+{
+    gint n_infos;
+    PyObject *infos;
+    gint i;
+
+    n_infos = get_n_infos ( (GIBaseInfo *) self->info);
+
+    infos = PyTuple_New (n_infos);
+    if (infos == NULL) {
+        return NULL;
+    }
+
+    for (i = 0; i < n_infos; i++) {
+        GIBaseInfo *info;
+        PyObject *py_info;
+
+        info = (GIBaseInfo *) get_info (self->info, i);
+        g_assert (info != NULL);
+
+        py_info = _pygi_info_new (info);
+
+        g_base_info_unref (info);
+
+        if (py_info == NULL) {
+            Py_CLEAR (infos);
+            break;
+        }
+
+        PyTuple_SET_ITEM (infos, i, py_info);
+    }
+
+    return infos;
+}
+
 
 /* BaseInfo */
 
+/* We need to be careful about calling g_base_info_get_name because
+ * calling it with a GI_INFO_TYPE_TYPE will crash.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=709456
+ */
+static const char *
+_safe_base_info_get_name (GIBaseInfo *info)
+{
+    if (g_base_info_get_type (info) == GI_INFO_TYPE_TYPE) {
+        return "type_type_instance";
+    } else {
+        return g_base_info_get_name (info);
+    }
+}
+
 static void
 _base_info_dealloc (PyGIBaseInfo *self)
 {
@@ -72,32 +185,48 @@ _base_info_dealloc (PyGIBaseInfo *self)
 static PyObject *
 _base_info_repr (PyGIBaseInfo *self)
 {
+
     return PYGLIB_PyUnicode_FromFormat ("<%s object (%s) at 0x%p>",
-                                        Py_TYPE( (PyObject *) self)->tp_name, 
-                                        g_base_info_get_name (self->info), 
+                                        Py_TYPE( (PyObject *) self)->tp_name,
+                                        _safe_base_info_get_name (self->info),
                                         (void *) self);
 }
 
 static PyObject *
-_base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op)
+_wrap_g_base_info_equal (PyGIBaseInfo *self, PyObject *other)
 {
-    PyObject *res;
     GIBaseInfo *other_info;
 
-    if (!PyObject_TypeCheck(other, &PyGIBaseInfo_Type)) {
-        Py_INCREF(Py_NotImplemented);
+    if (!PyObject_TypeCheck (other, &PyGIBaseInfo_Type)) {
+        Py_INCREF (Py_NotImplemented);
         return Py_NotImplemented;
     }
 
     other_info = ((PyGIBaseInfo *)other)->info;
+    if (g_base_info_equal (self->info, other_info)) {
+        Py_RETURN_TRUE;
+    } else {
+        Py_RETURN_FALSE;
+    }
+}
+
+static PyObject *
+_base_info_richcompare (PyGIBaseInfo *self, PyObject *other, int op)
+{
+    PyObject *res;
 
     switch (op) {
         case Py_EQ:
-            res = g_base_info_equal (self->info, other_info) ? Py_True : Py_False;
-            break;
+            return _wrap_g_base_info_equal (self, other);
         case Py_NE:
-            res = g_base_info_equal (self->info, other_info) ? Py_False : Py_True;
-            break;
+            res = _wrap_g_base_info_equal (self, other);
+            if (res == Py_True) {
+                Py_DECREF (res);
+                Py_RETURN_FALSE;
+            } else {
+                Py_DECREF (res);
+                Py_RETURN_TRUE;
+            }
         default:
             res = Py_NotImplemented;
             break;
@@ -145,11 +274,17 @@ _pygi_is_python_keyword (const gchar *name)
 }
 
 static PyObject *
+_wrap_g_base_info_get_type (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_base_info_get_type (self->info));
+}
+
+static PyObject *
 _wrap_g_base_info_get_name (PyGIBaseInfo *self)
 {
     const gchar *name;
 
-    name = g_base_info_get_name (self->info);
+    name = _safe_base_info_get_name (self->info);
 
     /* escape keywords */
     if (_pygi_is_python_keyword (name)) {
@@ -165,18 +300,49 @@ _wrap_g_base_info_get_name (PyGIBaseInfo *self)
 static PyObject *
 _wrap_g_base_info_get_name_unescaped (PyGIBaseInfo *self)
 {
-    return PYGLIB_PyUnicode_FromString (g_base_info_get_name (self->info));
+    return _get_info_string (self, _safe_base_info_get_name);
 }
 
 static PyObject *
 _wrap_g_base_info_get_namespace (PyGIBaseInfo *self)
 {
-    return PYGLIB_PyUnicode_FromString (g_base_info_get_namespace (self->info));
+    return _get_info_string (self, g_base_info_get_namespace);
+}
+
+static PyObject *
+_wrap_g_base_info_is_deprecated (PyGIBaseInfo *self)
+{
+    if (g_base_info_is_deprecated (self->info))
+        Py_RETURN_TRUE;
+    else
+        Py_RETURN_FALSE;
+}
+
+static PyObject *
+_wrap_g_base_info_get_attribute (PyGIBaseInfo *self, PyObject *arg)
+{
+    char *name;
+    const char *value;
+
+    if (!PYGLIB_PyUnicode_Check (arg)) {
+        PyErr_SetString (PyExc_TypeError, "expected string name");
+        return NULL;
+    }
+
+    name = PYGLIB_PyUnicode_AsString (arg);
+    value = g_base_info_get_attribute (self->info, name);
+    if (value == NULL) {
+        Py_RETURN_NONE;
+    }
+    return PYGLIB_PyUnicode_FromString (value);
 }
 
 static PyObject *
 _wrap_g_base_info_get_container (PyGIBaseInfo *self)
 {
+    /* Note: don't use _get_child_info because g_base_info_get_container
+     * is marked as [transfer none] and therefore returns a borrowed ref.
+     */
     GIBaseInfo *info;
 
     info = g_base_info_get_container (self->info);
@@ -190,10 +356,14 @@ _wrap_g_base_info_get_container (PyGIBaseInfo *self)
 
 
 static PyMethodDef _PyGIBaseInfo_methods[] = {
+    { "get_type", (PyCFunction) _wrap_g_base_info_get_type, METH_NOARGS },
     { "get_name", (PyCFunction) _wrap_g_base_info_get_name, METH_NOARGS },
     { "get_name_unescaped", (PyCFunction) _wrap_g_base_info_get_name_unescaped, METH_NOARGS },
     { "get_namespace", (PyCFunction) _wrap_g_base_info_get_namespace, METH_NOARGS },
+    { "is_deprecated", (PyCFunction) _wrap_g_base_info_is_deprecated, METH_NOARGS },
+    { "get_attribute", (PyCFunction) _wrap_g_base_info_get_attribute, METH_O },
     { "get_container", (PyCFunction) _wrap_g_base_info_get_container, METH_NOARGS },
+    { "equal", (PyCFunction) _wrap_g_base_info_equal, METH_O },
     { NULL, NULL, 0 }
 };
 
@@ -359,43 +529,6 @@ out:
 /* CallableInfo */
 PYGLIB_DEFINE_TYPE ("gi.CallableInfo", PyGICallableInfo_Type, PyGICallableInfo);
 
-static PyObject *
-_wrap_g_callable_info_get_arguments (PyGIBaseInfo *self)
-{
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    n_infos = g_callable_info_get_n_args ( (GICallableInfo *) self->info);
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        info = (GIBaseInfo *) g_callable_info_get_arg ( (GICallableInfo *) self->info, i);
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
-
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
-
-    return infos;
-}
-
-
 /* _callable_info_call:
  *
  * Shared wrapper for invoke which can be bound (instance method or class constructor)
@@ -478,11 +611,11 @@ _function_info_call (PyGICallableInfo *self, PyObject *args, PyObject *kwargs)
             str_name = PyBytes_AsString (py_str_name);
 #endif
 
-            if (strcmp (str_name, g_base_info_get_name (container_info))) {
+            if (strcmp (str_name, _safe_base_info_get_name (container_info))) {
                 PyErr_Format (PyExc_TypeError,
                               "%s constructor cannot be used to create instances of "
                               "a subclass %s",
-                              g_base_info_get_name (container_info),
+                              _safe_base_info_get_name (container_info),
                               str_name);
                 Py_DECREF (py_str_name);
                 return NULL;
@@ -572,9 +705,61 @@ _callable_info_dealloc (PyGICallableInfo *self)
     PyGIBaseInfo_Type.tp_dealloc ((PyObject *) self);
 }
 
+static PyObject *
+_wrap_g_callable_info_get_arguments (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_callable_info_get_n_args, g_callable_info_get_arg);
+}
+
+static PyObject *
+_wrap_g_callable_info_get_return_type (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_callable_info_get_return_type);
+}
+
+static PyObject *
+_wrap_g_callable_info_get_caller_owns (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_callable_info_get_caller_owns (self->info) );
+}
+
+static PyObject *
+_wrap_g_callable_info_may_return_null (PyGIBaseInfo *self)
+{
+    return PyBool_FromLong (
+            g_callable_info_may_return_null (self->info) );
+}
+
+static PyObject *
+_wrap_g_callable_info_get_return_attribute (PyGIBaseInfo *self, PyObject *py_name)
+{
+    gchar *name;
+    const gchar *attr;
+
+    if (!PYGLIB_PyUnicode_Check (py_name)) {
+        PyErr_SetString (PyExc_TypeError, "expected string name");
+        return NULL;
+    }
+
+    name = PYGLIB_PyUnicode_AsString (py_name);
+    attr = g_callable_info_get_return_attribute (self->info, name);
+    if (attr) {
+        return PYGLIB_PyUnicode_FromString (
+                g_callable_info_get_return_attribute (self->info, name));
+    } else {
+        PyErr_Format(PyExc_AttributeError, "return attribute %s not found", name);
+        return NULL;
+    }
+}
+
 static PyMethodDef _PyGICallableInfo_methods[] = {
     { "invoke", (PyCFunction) _wrap_g_callable_info_invoke, METH_VARARGS | METH_KEYWORDS },
     { "get_arguments", (PyCFunction) _wrap_g_callable_info_get_arguments, METH_NOARGS },
+    { "get_return_type", (PyCFunction) _wrap_g_callable_info_get_return_type, METH_NOARGS },
+    { "get_caller_owns", (PyCFunction) _wrap_g_callable_info_get_caller_owns, METH_NOARGS },
+    { "may_return_null", (PyCFunction) _wrap_g_callable_info_may_return_null, METH_NOARGS },
+    { "get_return_attribute", (PyCFunction) _wrap_g_callable_info_get_return_attribute, METH_O },
     { NULL, NULL, 0 }
 };
 
@@ -600,16 +785,62 @@ static PyMethodDef _PyGIErrorDomainInfo_methods[] = {
 };
 
 /* SignalInfo */
-PYGLIB_DEFINE_TYPE ("gi.SignalInfo", PyGISignalInfo_Type, PyGIBaseInfo);
+PYGLIB_DEFINE_TYPE ("gi.SignalInfo", PyGISignalInfo_Type, PyGICallableInfo);
+
+static PyObject *
+_wrap_g_signal_info_get_flags (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_signal_info_get_flags ((GISignalInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_signal_info_get_class_closure (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_signal_info_get_class_closure);
+}
+
+static PyObject *
+_wrap_g_signal_info_true_stops_emit (PyGIBaseInfo *self)
+{
+    return PyBool_FromLong (
+            g_signal_info_true_stops_emit ((GISignalInfo *)self->info) );
+}
 
 static PyMethodDef _PyGISignalInfo_methods[] = {
+    { "get_flags", (PyCFunction) _wrap_g_signal_info_get_flags, METH_NOARGS },
+    { "get_class_closure", (PyCFunction) _wrap_g_signal_info_get_class_closure, METH_NOARGS },
+    { "true_stops_emit", (PyCFunction) _wrap_g_signal_info_true_stops_emit, METH_NOARGS },
     { NULL, NULL, 0 }
 };
 
 /* PropertyInfo */
 PYGLIB_DEFINE_TYPE ("gi.PropertyInfo", PyGIPropertyInfo_Type, PyGIBaseInfo);
 
+static PyObject *
+_wrap_g_property_info_get_flags (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_property_info_get_flags ((GIPropertyInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_property_info_get_type (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_property_info_get_type);
+}
+
+static PyObject *
+_wrap_g_property_info_get_ownership_transfer (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_property_info_get_ownership_transfer ((GIPropertyInfo *)self->info) );
+}
+
 static PyMethodDef _PyGIPropertyInfo_methods[] = {
+    { "get_flags", (PyCFunction) _wrap_g_property_info_get_flags, METH_NOARGS },
+    { "get_type", (PyCFunction) _wrap_g_property_info_get_type, METH_NOARGS },
+    { "get_ownership_transfer", (PyCFunction) _wrap_g_property_info_get_ownership_transfer, METH_NOARGS },
     { NULL, NULL, 0 }
 };
 
@@ -620,7 +851,7 @@ PYGLIB_DEFINE_TYPE ("gi.ArgInfo", PyGIArgInfo_Type, PyGIBaseInfo);
 static PyObject *
 _wrap_g_arg_info_get_direction (PyGIBaseInfo *self)
 {
-    return PyLong_FromLong (
+    return PYGLIB_PyLong_FromLong (
            g_arg_info_get_direction ((GIArgInfo*)self->info) );
 }
 
@@ -652,6 +883,40 @@ _wrap_g_arg_info_may_be_null (PyGIBaseInfo *self)
            g_arg_info_may_be_null ((GIArgInfo*)self->info) );
 }
 
+static PyObject *
+_wrap_g_arg_info_get_ownership_transfer (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_arg_info_get_ownership_transfer ((GIArgInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_arg_info_get_scope (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_arg_info_get_scope ((GIArgInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_arg_info_get_closure (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_arg_info_get_closure ((GIArgInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_arg_info_get_destroy (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (
+            g_arg_info_get_destroy ((GIArgInfo *)self->info) );
+}
+
+static PyObject *
+_wrap_g_arg_info_get_type (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_arg_info_get_type);
+}
+
 /* _g_arg_get_pytype_hint
  *
  * Returns new value reference to a string hinting at the python type
@@ -682,7 +947,7 @@ _g_arg_get_pytype_hint (PyGIBaseInfo *self)
            GIBaseInfo *iface = g_type_info_get_interface(&type_info);
            gchar *name;
 
-           info_name = g_base_info_get_name (iface);
+           info_name = _safe_base_info_get_name (iface);
            if (info_name == NULL) {
                g_base_info_unref (iface);
                return PYGLIB_PyUnicode_FromString(g_type_tag_to_string(type_tag));
@@ -706,6 +971,11 @@ static PyMethodDef _PyGIArgInfo_methods[] = {
     { "is_return_value", (PyCFunction) _wrap_g_arg_info_is_return_value, METH_NOARGS },
     { "is_optional", (PyCFunction) _wrap_g_arg_info_is_optional, METH_NOARGS },
     { "may_be_null", (PyCFunction) _wrap_g_arg_info_may_be_null, METH_NOARGS },
+    { "get_ownership_transfer", (PyCFunction) _wrap_g_arg_info_get_ownership_transfer, METH_NOARGS },
+    { "get_scope", (PyCFunction) _wrap_g_arg_info_get_scope, METH_NOARGS },
+    { "get_closure", (PyCFunction) _wrap_g_arg_info_get_closure, METH_NOARGS },
+    { "get_destroy", (PyCFunction) _wrap_g_arg_info_get_destroy, METH_NOARGS },
+    { "get_type", (PyCFunction) _wrap_g_arg_info_get_type, METH_NOARGS },
     { "get_pytype_hint", (PyCFunction) _g_arg_get_pytype_hint, METH_NOARGS },
     { NULL, NULL, 0 }
 };
@@ -714,45 +984,126 @@ static PyMethodDef _PyGIArgInfo_methods[] = {
 /* TypeInfo */
 PYGLIB_DEFINE_TYPE ("gi.TypeInfo", PyGITypeInfo_Type, PyGIBaseInfo);
 
-static PyMethodDef _PyGITypeInfo_methods[] = {
-    { NULL, NULL, 0 }
-};
-
-
-/* FunctionInfo */
-PYGLIB_DEFINE_TYPE ("gi.FunctionInfo", PyGIFunctionInfo_Type, PyGICallableInfo);
-
 static PyObject *
-_wrap_g_function_info_is_constructor (PyGIBaseInfo *self)
+_wrap_g_type_info_is_pointer (PyGIBaseInfo *self)
 {
-    GIFunctionInfoFlags flags;
-    gboolean is_constructor;
-
-    flags = g_function_info_get_flags ( (GIFunctionInfo*) self->info);
-    is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR;
-
-    return PyBool_FromLong (is_constructor);
+    return PyBool_FromLong (g_type_info_is_pointer (self->info));
 }
 
 static PyObject *
-_wrap_g_function_info_is_method (PyGIBaseInfo *self)
+_wrap_g_type_info_get_tag (PyGIBaseInfo *self)
 {
-    GIFunctionInfoFlags flags;
-    gboolean is_method;
-
-    flags = g_function_info_get_flags ( (GIFunctionInfo*) self->info);
-    is_method = flags & GI_FUNCTION_IS_METHOD;
+    return PYGLIB_PyLong_FromLong (g_type_info_get_tag (self->info));
+}
 
-    return PyBool_FromLong (is_method);
+static PyObject *
+_wrap_g_type_info_get_tag_as_string (PyGIBaseInfo *self)
+{
+    GITypeTag tag = g_type_info_get_tag (self->info);
+    return PYGLIB_PyUnicode_FromString (g_type_tag_to_string(tag));
 }
 
-gsize
-_pygi_g_type_tag_size (GITypeTag type_tag)
+static PyObject *
+_wrap_g_type_info_get_param_type (PyGIBaseInfo *self, PyObject *py_n)
 {
-    gsize size = 0;
+    GIBaseInfo *info;
+    PyObject *py_info;
+    gint n;
 
-    switch (type_tag) {
-        case GI_TYPE_TAG_BOOLEAN:
+    if (!PYGLIB_PyLong_Check (py_n)) {
+        PyErr_SetString(PyExc_TypeError, "expected integer value");
+        return NULL;
+    }
+
+    n = PYGLIB_PyLong_AsLong (py_n);
+    info = (GIBaseInfo *) g_type_info_get_param_type ( (GITypeInfo *) self->info, n);
+    if (info == NULL) {
+        Py_RETURN_NONE;
+    }
+
+    py_info = _pygi_info_new (info);
+    g_base_info_unref (info);
+    return py_info;
+}
+
+static PyObject *
+_wrap_g_type_info_get_interface (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_type_info_get_interface);
+}
+
+static PyObject *
+_wrap_g_type_info_get_array_length (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_type_info_get_array_length (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_get_array_fixed_size (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_type_info_get_array_fixed_size (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_is_zero_terminated (PyGIBaseInfo *self)
+{
+    return PyBool_FromLong (g_type_info_is_zero_terminated (self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_get_array_type (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_type_info_get_array_type (self->info));
+}
+
+static PyMethodDef _PyGITypeInfo_methods[] = {
+    { "is_pointer", (PyCFunction) _wrap_g_type_info_is_pointer, METH_NOARGS },
+    { "get_tag", (PyCFunction) _wrap_g_type_info_get_tag, METH_NOARGS },
+    { "get_tag_as_string", (PyCFunction) _wrap_g_type_info_get_tag_as_string, METH_NOARGS },
+    { "get_param_type", (PyCFunction) _wrap_g_type_info_get_param_type, METH_O },
+    { "get_interface", (PyCFunction) _wrap_g_type_info_get_interface, METH_NOARGS },
+    { "get_array_length", (PyCFunction) _wrap_g_type_info_get_array_length, METH_NOARGS },
+    { "get_array_fixed_size", (PyCFunction) _wrap_g_type_info_get_array_fixed_size, METH_NOARGS },
+    { "is_zero_terminated", (PyCFunction) _wrap_g_type_info_is_zero_terminated, METH_NOARGS },
+    { "get_array_type", (PyCFunction) _wrap_g_type_info_get_array_type, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+
+/* FunctionInfo */
+PYGLIB_DEFINE_TYPE ("gi.FunctionInfo", PyGIFunctionInfo_Type, PyGICallableInfo);
+
+static PyObject *
+_wrap_g_function_info_is_constructor (PyGIBaseInfo *self)
+{
+    GIFunctionInfoFlags flags;
+    gboolean is_constructor;
+
+    flags = g_function_info_get_flags ( (GIFunctionInfo*) self->info);
+    is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR;
+
+    return PyBool_FromLong (is_constructor);
+}
+
+static PyObject *
+_wrap_g_function_info_is_method (PyGIBaseInfo *self)
+{
+    GIFunctionInfoFlags flags;
+    gboolean is_method;
+
+    flags = g_function_info_get_flags ( (GIFunctionInfo*) self->info);
+    is_method = flags & GI_FUNCTION_IS_METHOD;
+
+    return PyBool_FromLong (is_method);
+}
+
+gsize
+_pygi_g_type_tag_size (GITypeTag type_tag)
+{
+    gsize size = 0;
+
+    switch (type_tag) {
+        case GI_TYPE_TAG_BOOLEAN:
             size = sizeof (gboolean);
             break;
         case GI_TYPE_TAG_INT8:
@@ -900,9 +1251,37 @@ _pygi_g_type_info_size (GITypeInfo *type_info)
     return size;
 }
 
+static PyObject *
+_wrap_g_function_info_get_symbol (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_function_info_get_symbol);
+}
+
+static PyObject *
+_wrap_g_function_info_get_flags (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_function_info_get_flags (self->info));
+}
+
+static PyObject *
+_wrap_g_function_info_get_property (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_function_info_get_property);
+}
+
+static PyObject *
+_wrap_g_function_info_get_vfunc (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_function_info_get_vfunc);
+}
+
 static PyMethodDef _PyGIFunctionInfo_methods[] = {
     { "is_constructor", (PyCFunction) _wrap_g_function_info_is_constructor, METH_NOARGS },
     { "is_method", (PyCFunction) _wrap_g_function_info_is_method, METH_NOARGS },
+    { "get_symbol", (PyCFunction) _wrap_g_function_info_get_symbol, METH_NOARGS },
+    { "get_flags", (PyCFunction) _wrap_g_function_info_get_flags, METH_NOARGS },
+    { "get_property", (PyCFunction) _wrap_g_function_info_get_property, METH_NOARGS },
+    { "get_vfunc", (PyCFunction) _wrap_g_function_info_get_vfunc, METH_NOARGS },
     { NULL, NULL, 0 }
 };
 
@@ -910,6 +1289,18 @@ static PyMethodDef _PyGIFunctionInfo_methods[] = {
 PYGLIB_DEFINE_TYPE ("gi.RegisteredTypeInfo", PyGIRegisteredTypeInfo_Type, PyGIBaseInfo);
 
 static PyObject *
+_wrap_g_registered_type_info_get_type_name (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_registered_type_info_get_type_name);
+}
+
+static PyObject *
+_wrap_g_registered_type_info_get_type_init (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_registered_type_info_get_type_init);
+}
+
+static PyObject *
 _wrap_g_registered_type_info_get_g_type (PyGIBaseInfo *self)
 {
     GType type;
@@ -920,6 +1311,8 @@ _wrap_g_registered_type_info_get_g_type (PyGIBaseInfo *self)
 }
 
 static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = {
+    { "get_type_name", (PyCFunction) _wrap_g_registered_type_info_get_type_name, METH_NOARGS },
+    { "get_type_init", (PyCFunction) _wrap_g_registered_type_info_get_type_init, METH_NOARGS },
     { "get_g_type", (PyCFunction) _wrap_g_registered_type_info_get_g_type, METH_NOARGS },
     { NULL, NULL, 0 }
 };
@@ -929,236 +1322,48 @@ static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = {
 PYGLIB_DEFINE_TYPE ("StructInfo", PyGIStructInfo_Type, PyGIBaseInfo);
 
 static PyObject *
-_get_fields (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_fields (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    switch (info_type) {
-        case GI_INFO_TYPE_STRUCT:
-            n_infos = g_struct_info_get_n_fields ( (GIStructInfo *) self->info);
-            break;
-        case GI_INFO_TYPE_OBJECT:
-            n_infos = g_object_info_get_n_fields ( (GIObjectInfo *) self->info);
-            break;
-        default:
-            g_assert_not_reached();
-    }
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        switch (info_type) {
-            case GI_INFO_TYPE_STRUCT:
-                info = (GIBaseInfo *) g_struct_info_get_field ( (GIStructInfo *) self->info, i);
-                break;
-            case GI_INFO_TYPE_OBJECT:
-                info = (GIBaseInfo *) g_object_info_get_field ( (GIObjectInfo *) self->info, i);
-                break;
-            default:
-                g_assert_not_reached();
-        }
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
-
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
-
-    return infos;
+    return _make_infos_tuple (self, g_struct_info_get_n_fields, g_struct_info_get_field);
 }
 
 static PyObject *
-_get_methods (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_methods (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    switch (info_type) {
-        case GI_INFO_TYPE_STRUCT:
-            n_infos = g_struct_info_get_n_methods ( (GIStructInfo *) self->info);
-            break;
-        case GI_INFO_TYPE_OBJECT:
-            n_infos = g_object_info_get_n_methods ( (GIObjectInfo *) self->info);
-            break;
-        default:
-            g_assert_not_reached();
-    }
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        switch (info_type) {
-            case GI_INFO_TYPE_STRUCT:
-                info = (GIBaseInfo *) g_struct_info_get_method ( (GIStructInfo *) self->info, i);
-                break;
-            case GI_INFO_TYPE_OBJECT:
-                info = (GIBaseInfo *) g_object_info_get_method ( (GIObjectInfo *) self->info, i);
-                break;
-            default:
-                g_assert_not_reached();
-        }
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
-
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
-
-    return infos;
+    return _make_infos_tuple (self, g_struct_info_get_n_methods, g_struct_info_get_method);
 }
 
 static PyObject *
-_get_constants (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_size (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    switch (info_type) {
-        case GI_INFO_TYPE_INTERFACE:
-            n_infos = g_interface_info_get_n_constants ( (GIInterfaceInfo *) self->info);
-            break;
-        case GI_INFO_TYPE_OBJECT:
-            n_infos = g_object_info_get_n_constants ( (GIObjectInfo *) self->info);
-            break;
-        default:
-            g_assert_not_reached();
-    }
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        switch (info_type) {
-            case GI_INFO_TYPE_INTERFACE:
-                info = (GIBaseInfo *) g_interface_info_get_constant ( (GIInterfaceInfo *) self->info, i);
-                break;
-            case GI_INFO_TYPE_OBJECT:
-                info = (GIBaseInfo *) g_object_info_get_constant ( (GIObjectInfo *) self->info, i);
-                break;
-            default:
-                g_assert_not_reached();
-        }
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
-
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
-
-    return infos;
+    return PYGLIB_PyLong_FromSize_t (g_struct_info_get_size (self->info));
 }
 
 static PyObject *
-_get_vfuncs (PyGIBaseInfo *self, GIInfoType info_type)
+_wrap_g_struct_info_get_alignment (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    switch (info_type) {
-        case GI_INFO_TYPE_INTERFACE:
-            n_infos = g_interface_info_get_n_vfuncs ( (GIInterfaceInfo *) self->info);
-            break;
-        case GI_INFO_TYPE_OBJECT:
-            n_infos = g_object_info_get_n_vfuncs ( (GIObjectInfo *) self->info);
-            break;
-        default:
-            g_assert_not_reached();
-    }
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        switch (info_type) {
-            case GI_INFO_TYPE_INTERFACE:
-                info = (GIBaseInfo *) g_interface_info_get_vfunc ( (GIInterfaceInfo *) self->info, i);
-                break;
-            case GI_INFO_TYPE_OBJECT:
-                info = (GIBaseInfo *) g_object_info_get_vfunc ( (GIObjectInfo *) self->info, i);
-                break;
-            default:
-                g_assert_not_reached();
-        }
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
-
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
-
-    return infos;
+    return PYGLIB_PyLong_FromSize_t (g_struct_info_get_alignment (self->info));
 }
 
 static PyObject *
-_wrap_g_struct_info_get_fields (PyGIBaseInfo *self)
+_wrap_g_struct_info_is_gtype_struct (PyGIBaseInfo *self)
 {
-    return _get_fields (self, GI_INFO_TYPE_STRUCT);
+    return PyBool_FromLong (g_struct_info_is_gtype_struct (self->info));
 }
 
 static PyObject *
-_wrap_g_struct_info_get_methods (PyGIBaseInfo *self)
+_wrap_g_struct_info_is_foreign (PyGIBaseInfo *self)
 {
-    return _get_methods (self, GI_INFO_TYPE_STRUCT);
+    return PyBool_FromLong (g_struct_info_is_foreign (self->info));
 }
 
 static PyMethodDef _PyGIStructInfo_methods[] = {
     { "get_fields", (PyCFunction) _wrap_g_struct_info_get_fields, METH_NOARGS },
     { "get_methods", (PyCFunction) _wrap_g_struct_info_get_methods, METH_NOARGS },
+    { "get_size", (PyCFunction) _wrap_g_struct_info_get_size, METH_NOARGS },
+    { "get_alignment", (PyCFunction) _wrap_g_struct_info_get_alignment, METH_NOARGS },
+    { "is_gtype_struct", (PyCFunction) _wrap_g_struct_info_is_gtype_struct, METH_NOARGS },
+    { "is_foreign", (PyCFunction) _wrap_g_struct_info_is_foreign, METH_NOARGS },
     { NULL, NULL, 0 }
 };
 
@@ -1261,55 +1466,25 @@ pygi_g_struct_info_is_simple (GIStructInfo *struct_info)
                 }
 
                 g_base_info_unref (info);
-                break;
-            }
-        }
-
-        g_base_info_unref ( (GIBaseInfo *) field_type_info);
-        g_base_info_unref ( (GIBaseInfo *) field_info);
-    }
-
-    return is_simple;
-}
-
-
-/* EnumInfo */
-PYGLIB_DEFINE_TYPE ("gi.EnumInfo", PyGIEnumInfo_Type, PyGIBaseInfo);
-
-static PyObject *
-_wrap_g_enum_info_get_values (PyGIBaseInfo *self)
-{
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    n_infos = g_enum_info_get_n_values ( (GIEnumInfo *) self->info);
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        info = (GIBaseInfo *) g_enum_info_get_value ( (GIEnumInfo *) self->info, i);
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
+                break;
+            }
         }
 
-        PyTuple_SET_ITEM (infos, i, py_info);
+        g_base_info_unref ( (GIBaseInfo *) field_type_info);
+        g_base_info_unref ( (GIBaseInfo *) field_info);
     }
 
-    return infos;
+    return is_simple;
+}
+
+
+/* EnumInfo */
+PYGLIB_DEFINE_TYPE ("gi.EnumInfo", PyGIEnumInfo_Type, PyGIBaseInfo);
+
+static PyObject *
+_wrap_g_enum_info_get_values (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_enum_info_get_n_values, g_enum_info_get_value);
 }
 
 static PyObject *
@@ -1326,9 +1501,23 @@ _wrap_g_enum_info_is_flags (PyGIBaseInfo *self)
     }
 }
 
+static PyObject *
+_wrap_g_enum_info_get_methods (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_enum_info_get_n_methods, g_enum_info_get_method);
+}
+
+static PyObject *
+_wrap_g_enum_info_get_storage_type (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_enum_info_get_storage_type ((GIBaseInfo *) self->info));
+}
+
 static PyMethodDef _PyGIEnumInfo_methods[] = {
     { "get_values", (PyCFunction) _wrap_g_enum_info_get_values, METH_NOARGS },
     { "is_flags", (PyCFunction) _wrap_g_enum_info_is_flags, METH_NOARGS },
+    { "get_methods", (PyCFunction) _wrap_g_enum_info_get_methods, METH_NOARGS },
+    { "get_storage_type", (PyCFunction) _wrap_g_enum_info_get_storage_type, METH_NOARGS },
     { NULL, NULL, 0 }
 };
 
@@ -1339,80 +1528,55 @@ PYGLIB_DEFINE_TYPE ("ObjectInfo", PyGIObjectInfo_Type, PyGIBaseInfo);
 static PyObject *
 _wrap_g_object_info_get_parent (PyGIBaseInfo *self)
 {
-    GIBaseInfo *info;
-    PyObject *py_info;
-
-    info = (GIBaseInfo *) g_object_info_get_parent ( (GIObjectInfo*) self->info);
-
-    if (info == NULL) {
-        Py_RETURN_NONE;
-    }
-
-    py_info = _pygi_info_new (info);
-
-    g_base_info_unref (info);
-
-    return py_info;
+    return _get_child_info (self, g_object_info_get_parent);
 }
 
 static PyObject *
 _wrap_g_object_info_get_methods (PyGIBaseInfo *self)
 {
-    return _get_methods (self, GI_INFO_TYPE_OBJECT);
+    return _make_infos_tuple (self, g_object_info_get_n_methods, g_object_info_get_method);
 }
 
 static PyObject *
-_wrap_g_object_info_get_fields (PyGIBaseInfo *self)
+_wrap_g_object_info_find_method (PyGIBaseInfo *self, PyObject *py_name)
 {
-    return _get_fields (self, GI_INFO_TYPE_OBJECT);
+    return _get_child_info_by_name (self, py_name, g_object_info_find_method);
 }
 
 static PyObject *
-_wrap_g_object_info_get_interfaces (PyGIBaseInfo *self)
+_wrap_g_object_info_get_fields (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    n_infos = g_object_info_get_n_interfaces ( (GIObjectInfo *) self->info);
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        info = (GIBaseInfo *) g_object_info_get_interface ( (GIObjectInfo *) self->info, i);
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
+    return _make_infos_tuple (self, g_object_info_get_n_fields, g_object_info_get_field);
+}
 
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
+static PyObject *
+_wrap_g_object_info_get_properties (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_object_info_get_n_properties, g_object_info_get_property);
+}
 
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
+static PyObject *
+_wrap_g_object_info_get_signals (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_object_info_get_n_signals, g_object_info_get_signal);
+}
 
-    return infos;
+static PyObject *
+_wrap_g_object_info_get_interfaces (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_object_info_get_n_interfaces, g_object_info_get_interface);
 }
 
 static PyObject *
 _wrap_g_object_info_get_constants (PyGIBaseInfo *self)
 {
-    return _get_constants (self, GI_INFO_TYPE_OBJECT);
+    return _make_infos_tuple (self, g_object_info_get_n_constants, g_object_info_get_constant);
 }
 
 static PyObject *
 _wrap_g_object_info_get_vfuncs (PyGIBaseInfo *self)
 {
-    return _get_vfuncs (self, GI_INFO_TYPE_OBJECT);
+    return _make_infos_tuple (self, g_object_info_get_n_vfuncs, g_object_info_get_vfunc);
 }
 
 static PyObject *
@@ -1423,28 +1587,79 @@ _wrap_g_object_info_get_abstract (PyGIBaseInfo *self)
 }
 
 static PyObject *
+_wrap_g_object_info_get_type_name (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_object_info_get_type_name);
+}
+
+static PyObject *
+_wrap_g_object_info_get_type_init (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_object_info_get_type_init);
+}
+
+static PyObject *
+_wrap_g_object_info_get_fundamental (PyGIBaseInfo *self)
+{
+    return PyBool_FromLong (g_object_info_get_fundamental ( (GIObjectInfo*) self->info));
+}
+
+static PyObject *
 _wrap_g_object_info_get_class_struct (PyGIBaseInfo *self)
 {
-    GIBaseInfo *info;
+    return _get_child_info (self, g_object_info_get_class_struct);
+}
 
-    info = g_object_info_get_class_struct ((GIObjectInfo*)self->info);
+static PyObject *
+_wrap_g_object_info_find_vfunc (PyGIBaseInfo *self, PyObject *py_name)
+{
+    return _get_child_info_by_name (self, py_name, g_object_info_find_vfunc);
+}
 
-    if (info == NULL) {
-        Py_RETURN_NONE;
-    }
+static PyObject *
+_wrap_g_object_info_get_unref_function (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_object_info_get_unref_function);
+}
 
-    return _pygi_info_new (info);
+static PyObject *
+_wrap_g_object_info_get_ref_function (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_object_info_get_ref_function);
+}
+
+static PyObject *
+_wrap_g_object_info_get_set_value_function (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_object_info_get_set_value_function);
+}
+
+static PyObject *
+_wrap_g_object_info_get_get_value_function (PyGIBaseInfo *self)
+{
+    return _get_info_string (self, g_object_info_get_get_value_function);
 }
 
 static PyMethodDef _PyGIObjectInfo_methods[] = {
     { "get_parent", (PyCFunction) _wrap_g_object_info_get_parent, METH_NOARGS },
     { "get_methods", (PyCFunction) _wrap_g_object_info_get_methods, METH_NOARGS },
+    { "find_method", (PyCFunction) _wrap_g_object_info_find_method, METH_O },
     { "get_fields", (PyCFunction) _wrap_g_object_info_get_fields, METH_NOARGS },
+    { "get_properties", (PyCFunction) _wrap_g_object_info_get_properties, METH_NOARGS },
+    { "get_signals", (PyCFunction) _wrap_g_object_info_get_signals, METH_NOARGS },
     { "get_interfaces", (PyCFunction) _wrap_g_object_info_get_interfaces, METH_NOARGS },
     { "get_constants", (PyCFunction) _wrap_g_object_info_get_constants, METH_NOARGS },
     { "get_vfuncs", (PyCFunction) _wrap_g_object_info_get_vfuncs, METH_NOARGS },
+    { "find_vfunc", (PyCFunction) _wrap_g_object_info_find_vfunc, METH_O },
     { "get_abstract", (PyCFunction) _wrap_g_object_info_get_abstract, METH_NOARGS },
+    { "get_type_name", (PyCFunction) _wrap_g_object_info_get_type_name, METH_NOARGS },
+    { "get_type_init", (PyCFunction) _wrap_g_object_info_get_type_init, METH_NOARGS },
+    { "get_fundamental", (PyCFunction) _wrap_g_object_info_get_fundamental, METH_NOARGS },
     { "get_class_struct", (PyCFunction) _wrap_g_object_info_get_class_struct, METH_NOARGS },
+    { "get_unref_function", (PyCFunction) _wrap_g_object_info_get_unref_function, METH_NOARGS },
+    { "get_ref_function", (PyCFunction) _wrap_g_object_info_get_ref_function, METH_NOARGS },
+    { "get_set_value_function", (PyCFunction) _wrap_g_object_info_get_set_value_function, METH_NOARGS },
+    { "get_get_value_function", (PyCFunction) _wrap_g_object_info_get_get_value_function, METH_NOARGS },
     { NULL, NULL, 0 }
 };
 
@@ -1455,55 +1670,74 @@ PYGLIB_DEFINE_TYPE ("InterfaceInfo", PyGIInterfaceInfo_Type, PyGIBaseInfo);
 static PyObject *
 _wrap_g_interface_info_get_methods (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    n_infos = g_interface_info_get_n_methods ( (GIInterfaceInfo *) self->info);
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
+    return _make_infos_tuple (self, g_interface_info_get_n_methods, g_interface_info_get_method);
+}
 
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
+static PyObject *
+_wrap_g_interface_info_find_method (PyGIBaseInfo *self, PyObject *py_name)
+{
+    return _get_child_info_by_name (self, py_name, g_interface_info_find_method);
+}
 
-        info = (GIBaseInfo *) g_interface_info_get_method ( (GIInterfaceInfo *) self->info, i);
-        g_assert (info != NULL);
+static PyObject *
+_wrap_g_interface_info_get_constants (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_interface_info_get_n_constants, g_interface_info_get_constant);
+}
 
-        py_info = _pygi_info_new (info);
+static PyObject *
+_wrap_g_interface_info_get_vfuncs (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_interface_info_get_n_vfuncs, g_interface_info_get_vfunc);
+}
 
-        g_base_info_unref (info);
+static PyObject *
+_wrap_g_interface_info_find_vfunc (PyGIBaseInfo *self, PyObject *py_name)
+{
+    return _get_child_info_by_name (self, py_name, g_interface_info_find_vfunc);
+}
 
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
+static PyObject *
+_wrap_g_interface_info_get_prerequisites (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_interface_info_get_n_prerequisites, g_interface_info_get_prerequisite);
+}
 
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
+static PyObject *
+_wrap_g_interface_info_get_properties (PyGIBaseInfo *self)
+{
+    return _make_infos_tuple (self, g_interface_info_get_n_properties, g_interface_info_get_property);
+}
 
-    return infos;
+static PyObject *
+_wrap_g_interface_info_get_iface_struct (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_interface_info_get_iface_struct);
 }
 
 static PyObject *
-_wrap_g_interface_info_get_constants (PyGIBaseInfo *self)
+_wrap_g_interface_info_get_signals (PyGIBaseInfo *self)
 {
-    return _get_constants (self, GI_INFO_TYPE_INTERFACE);
+    return _make_infos_tuple (self, g_interface_info_get_n_signals, g_interface_info_get_signal);
 }
 
 static PyObject *
-_wrap_g_interface_info_get_vfuncs (PyGIBaseInfo *self)
+_wrap_g_interface_info_find_signal (PyGIBaseInfo *self, PyObject *py_name)
 {
-    return _get_vfuncs (self, GI_INFO_TYPE_INTERFACE);
+    return _get_child_info_by_name (self, py_name, g_interface_info_find_signal);
 }
 
 static PyMethodDef _PyGIInterfaceInfo_methods[] = {
+    { "get_prerequisites", (PyCFunction) _wrap_g_interface_info_get_prerequisites, METH_NOARGS },
+    { "get_properties", (PyCFunction) _wrap_g_interface_info_get_properties, METH_NOARGS },
     { "get_methods", (PyCFunction) _wrap_g_interface_info_get_methods, METH_NOARGS },
-    { "get_constants", (PyCFunction) _wrap_g_interface_info_get_constants, METH_NOARGS },
+    { "find_method", (PyCFunction) _wrap_g_interface_info_find_method, METH_O },
+    { "get_signals", (PyCFunction) _wrap_g_interface_info_get_signals, METH_NOARGS },
+    { "find_signal", (PyCFunction) _wrap_g_interface_info_find_signal, METH_O },
     { "get_vfuncs", (PyCFunction) _wrap_g_interface_info_get_vfuncs, METH_NOARGS },
+    { "get_constants", (PyCFunction) _wrap_g_interface_info_get_constants, METH_NOARGS },
+    { "get_iface_struct", (PyCFunction) _wrap_g_interface_info_get_iface_struct, METH_NOARGS },
+    { "find_vfunc", (PyCFunction) _wrap_g_interface_info_find_vfunc, METH_O },
     { NULL, NULL, 0 }
 };
 
@@ -1828,9 +2062,37 @@ out:
     return retval;
 }
 
+static PyObject *
+_wrap_g_field_info_get_flags (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_field_info_get_flags (self->info));
+}
+
+static PyObject *
+_wrap_g_field_info_get_size (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_field_info_get_size (self->info));
+}
+
+static PyObject *
+_wrap_g_field_info_get_offset (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_field_info_get_offset (self->info));
+}
+
+static PyObject *
+_wrap_g_field_info_get_type (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_field_info_get_type);
+}
+
 static PyMethodDef _PyGIFieldInfo_methods[] = {
     { "get_value", (PyCFunction) _wrap_g_field_info_get_value, METH_VARARGS },
     { "set_value", (PyCFunction) _wrap_g_field_info_set_value, METH_VARARGS },
+    { "get_flags", (PyCFunction) _wrap_g_field_info_get_flags, METH_VARARGS },
+    { "get_size", (PyCFunction) _wrap_g_field_info_get_size, METH_VARARGS },
+    { "get_offset", (PyCFunction) _wrap_g_field_info_get_offset, METH_VARARGS },
+    { "get_type", (PyCFunction) _wrap_g_field_info_get_type, METH_VARARGS },
     { NULL, NULL, 0 }
 };
 
@@ -1846,21 +2108,33 @@ static PyMethodDef _PyGIUnresolvedInfo_methods[] = {
 PYGLIB_DEFINE_TYPE ("gi.VFuncInfo", PyGIVFuncInfo_Type, PyGICallableInfo);
 
 static PyObject *
-_wrap_g_vfunc_info_get_invoker (PyGIBaseInfo *self)
+_wrap_g_vfunc_info_get_flags (PyGIBaseInfo *self)
 {
-    PyObject *result = Py_None;
-    GIBaseInfo *info;
+    return PYGLIB_PyLong_FromLong (g_vfunc_info_get_flags ((GIVFuncInfo *) self->info));
+}
 
-    info = (GIBaseInfo *) g_vfunc_info_get_invoker ( (GIVFuncInfo *) self->info );
-    if (info)
-        result = _pygi_info_new(info);
-    else
-        Py_INCREF(Py_None);
+static PyObject *
+_wrap_g_vfunc_info_get_offset (PyGIBaseInfo *self)
+{
+    return PYGLIB_PyLong_FromLong (g_vfunc_info_get_offset ((GIVFuncInfo *) self->info));
+}
 
-    return result;
+static PyObject *
+_wrap_g_vfunc_info_get_signal (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_vfunc_info_get_signal);
+}
+
+static PyObject *
+_wrap_g_vfunc_info_get_invoker (PyGIBaseInfo *self)
+{
+    return _get_child_info (self, g_vfunc_info_get_invoker);
 }
 
 static PyMethodDef _PyGIVFuncInfo_methods[] = {
+    { "get_flags", (PyCFunction) _wrap_g_vfunc_info_get_flags, METH_NOARGS },
+    { "get_offset", (PyCFunction) _wrap_g_vfunc_info_get_offset, METH_NOARGS },
+    { "get_signal", (PyCFunction) _wrap_g_vfunc_info_get_signal, METH_NOARGS },
     { "get_invoker", (PyCFunction) _wrap_g_vfunc_info_get_invoker, METH_NOARGS },
     { NULL, NULL, 0 }
 };
@@ -1872,73 +2146,13 @@ PYGLIB_DEFINE_TYPE ("gi.UnionInfo", PyGIUnionInfo_Type, PyGIBaseInfo);
 static PyObject *
 _wrap_g_union_info_get_fields (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    n_infos = g_union_info_get_n_fields ( (GIUnionInfo *) self->info);
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        info = (GIBaseInfo *) g_union_info_get_field ( (GIUnionInfo *) self->info, i);
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
-
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
-
-    return infos;
+    return _make_infos_tuple (self, g_union_info_get_n_fields, g_union_info_get_field);
 }
 
 static PyObject *
 _wrap_g_union_info_get_methods (PyGIBaseInfo *self)
 {
-    gssize n_infos;
-    PyObject *infos;
-    gssize i;
-
-    n_infos = g_union_info_get_n_methods ( (GIUnionInfo *) self->info);
-
-    infos = PyTuple_New (n_infos);
-    if (infos == NULL) {
-        return NULL;
-    }
-
-    for (i = 0; i < n_infos; i++) {
-        GIBaseInfo *info;
-        PyObject *py_info;
-
-        info = (GIBaseInfo *) g_union_info_get_method ( (GIUnionInfo *) self->info, i);
-        g_assert (info != NULL);
-
-        py_info = _pygi_info_new (info);
-
-        g_base_info_unref (info);
-
-        if (py_info == NULL) {
-            Py_CLEAR (infos);
-            break;
-        }
-
-        PyTuple_SET_ITEM (infos, i, py_info);
-    }
-
-    return infos;
+    return _make_infos_tuple (self, g_union_info_get_n_methods, g_union_info_get_method);
 }
 
 static PyMethodDef _PyGIUnionInfo_methods[] = {
@@ -1959,12 +2173,12 @@ _pygi_g_base_info_get_fullname (GIBaseInfo *info)
     if (container_info != NULL) {
         fullname = g_strdup_printf ("%s.%s.%s",
                                     g_base_info_get_namespace (container_info),
-                                    g_base_info_get_name (container_info),
-                                    g_base_info_get_name (info));
+                                    _safe_base_info_get_name (container_info),
+                                    _safe_base_info_get_name (info));
     } else {
         fullname = g_strdup_printf ("%s.%s",
                                     g_base_info_get_namespace (info),
-                                    g_base_info_get_name (info));
+                                    _safe_base_info_get_name (info));
     }
 
     if (fullname == NULL) {
@@ -1974,6 +2188,7 @@ _pygi_g_base_info_get_fullname (GIBaseInfo *info)
     return fullname;
 }
 
+
 void
 _pygi_info_register_types (PyObject *m)
 {
@@ -2004,13 +2219,6 @@ _pygi_info_register_types (PyObject *m)
     if (PyModule_AddObject(m, "BaseInfo", (PyObject *)&PyGIBaseInfo_Type))
         return;
 
-    if (PyModule_AddObject(m, "DIRECTION_IN", PyLong_FromLong(GI_DIRECTION_IN)))
-        return;
-    if (PyModule_AddObject(m, "DIRECTION_OUT", PyLong_FromLong(GI_DIRECTION_OUT)))
-        return;
-    if (PyModule_AddObject(m, "DIRECTION_INOUT", PyLong_FromLong(GI_DIRECTION_INOUT)))
-        return;
-
     _PyGI_REGISTER_TYPE (m, PyGICallableInfo_Type, CallableInfo,
                          PyGIBaseInfo_Type);
     PyGICallableInfo_Type.tp_call = (ternaryfunc) _callable_info_call;
@@ -2025,6 +2233,9 @@ _pygi_info_register_types (PyObject *m)
                          PyGICallableInfo_Type);
     PyGIVFuncInfo_Type.tp_descr_get = (descrgetfunc) _vfunc_info_descr_get;
 
+    _PyGI_REGISTER_TYPE (m, PyGISignalInfo_Type, SignalInfo,
+                         PyGICallableInfo_Type);
+
     _PyGI_REGISTER_TYPE (m, PyGIUnresolvedInfo_Type, UnresolvedInfo,
                          PyGIBaseInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGICallbackInfo_Type, CallbackInfo,
@@ -2051,8 +2262,6 @@ _pygi_info_register_types (PyObject *m)
                          PyGIBaseInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGIErrorDomainInfo_Type, ErrorDomainInfo,
                          PyGIBaseInfo_Type);
-    _PyGI_REGISTER_TYPE (m, PyGISignalInfo_Type, SignalInfo,
-                         PyGIBaseInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGIPropertyInfo_Type, PropertyInfo,
                          PyGIBaseInfo_Type);
     _PyGI_REGISTER_TYPE (m, PyGIArgInfo_Type, ArgInfo,
@@ -2060,6 +2269,147 @@ _pygi_info_register_types (PyObject *m)
     _PyGI_REGISTER_TYPE (m, PyGITypeInfo_Type, TypeInfo,
                          PyGIBaseInfo_Type);
 
-
 #undef _PyGI_REGISTER_TYPE
+
+#define _PyGI_ENUM_BEGIN(name) \
+        { \
+            const char *__enum_name = #name; \
+            PyObject *__enum_value = NULL; \
+            PyObject *__new_enum_cls = NULL; \
+            PyObject *__enum_instance_dict = PyDict_New(); \
+            PyObject *__module_name = PyObject_GetAttrString (m, "__name__"); \
+            PyDict_SetItemString (__enum_instance_dict, "__module__", __module_name); \
+            Py_DECREF (__module_name);
+
+#define _PyGI_ENUM_ADD_VALUE(prefix, name) \
+            __enum_value = PYGLIB_PyLong_FromLong (prefix##_##name); \
+            if (PyDict_SetItemString(__enum_instance_dict, #name, __enum_value)) { \
+                Py_DECREF (__enum_instance_dict); \
+                Py_DECREF (__enum_value); \
+                return; \
+            } \
+            Py_DECREF (__enum_value);
+
+#define _PyGI_ENUM_END \
+            __new_enum_cls = PyObject_CallFunction ((PyObject *)&PyType_Type, "s(O)O", \
+                                                    __enum_name, (PyObject *)&PyType_Type, \
+                                                    __enum_instance_dict); \
+            Py_DECREF (__enum_instance_dict); \
+            PyModule_AddObject (m, __enum_name, __new_enum_cls); /* steals ref */ \
+        }
+
+
+    /* GIDirection */
+    _PyGI_ENUM_BEGIN (Direction)
+        _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, IN)
+        _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, OUT)
+        _PyGI_ENUM_ADD_VALUE (GI_DIRECTION, INOUT)
+    _PyGI_ENUM_END
+
+
+    /* GITransfer */
+    _PyGI_ENUM_BEGIN (Transfer)
+        _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, NOTHING)
+        _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, CONTAINER)
+        _PyGI_ENUM_ADD_VALUE (GI_TRANSFER, EVERYTHING)
+    _PyGI_ENUM_END
+
+    /* GIArrayType */
+    _PyGI_ENUM_BEGIN (ArrayType)
+        _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, C)
+        _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, ARRAY)
+        _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, PTR_ARRAY)
+        _PyGI_ENUM_ADD_VALUE (GI_ARRAY_TYPE, BYTE_ARRAY)
+    _PyGI_ENUM_END
+
+    /* GIScopeType */
+    _PyGI_ENUM_BEGIN (ScopeType)
+        _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, INVALID)
+        _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, CALL)
+        _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, ASYNC)
+        _PyGI_ENUM_ADD_VALUE (GI_SCOPE_TYPE, NOTIFIED)
+    _PyGI_ENUM_END
+
+    /* GIVFuncInfoFlags */
+    _PyGI_ENUM_BEGIN (VFuncInfoFlags)
+        _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, CHAIN_UP)
+        _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, OVERRIDE)
+        _PyGI_ENUM_ADD_VALUE (GI_VFUNC_MUST, NOT_OVERRIDE)
+    _PyGI_ENUM_END
+
+    /* GIFieldInfoFlags */
+    _PyGI_ENUM_BEGIN (FieldInfoFlags)
+        _PyGI_ENUM_ADD_VALUE (GI_FIELD, IS_READABLE)
+        _PyGI_ENUM_ADD_VALUE (GI_FIELD, IS_WRITABLE)
+    _PyGI_ENUM_END
+
+    /* GIFunctionInfoFlags */
+    _PyGI_ENUM_BEGIN (FunctionInfoFlags)
+        _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_METHOD)
+        _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_CONSTRUCTOR)
+        _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_GETTER)
+        _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, IS_SETTER)
+        _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, WRAPS_VFUNC)
+        _PyGI_ENUM_ADD_VALUE (GI_FUNCTION, THROWS)
+    _PyGI_ENUM_END
+
+    /* GITypeTag */
+    _PyGI_ENUM_BEGIN (TypeTag)
+        /* Basic types */
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, VOID)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, BOOLEAN)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT8)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT8)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT16)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT16)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT32)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT32)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INT64)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UINT64)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, FLOAT)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, DOUBLE)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GTYPE)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UTF8)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, FILENAME)
+
+        /* Non-basic types; compare with G_TYPE_TAG_IS_BASIC */
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, ARRAY)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, INTERFACE)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GLIST)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GSLIST)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, GHASH)
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, ERROR)
+
+        /* Another basic type */
+        _PyGI_ENUM_ADD_VALUE (GI_TYPE_TAG, UNICHAR)
+    _PyGI_ENUM_END
+
+    /* GIInfoType */
+    _PyGI_ENUM_BEGIN (InfoType)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, INVALID)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, FUNCTION)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, CALLBACK)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, STRUCT)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, BOXED)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, ENUM)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, FLAGS)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, OBJECT)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, INTERFACE)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, CONSTANT)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, INVALID_0)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, UNION)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, VALUE)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, SIGNAL)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, VFUNC)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, PROPERTY)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, FIELD)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, ARG)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, TYPE)
+        _PyGI_ENUM_ADD_VALUE (GI_INFO_TYPE, UNRESOLVED)
+    _PyGI_ENUM_END
+
+#undef _PyGI_ENUM_BEGIN
+#undef _PyGI_ENUM_ADD_VALUE
+#undef _PyGI_ENUM_END
+
 }
index 1d9e49c..139b878 100644 (file)
@@ -18,9 +18,10 @@ typedef struct _PyGIInvokeState
     GIArgument **args;
     GIArgument *in_args;
 
-    /* Generic array allocated to the same length as args
-     * for use as extra per-arg state data. */
-    gpointer *args_data;
+    /* Array of pointers allocated to the same length as args which holds from_py
+     * marshaler cleanup data.
+     */
+    gpointer *args_cleanup_data;
 
     /* Out args and out values
      * In order to pass a parameter and get something back out in C
index 17cd278..675b0ef 100644 (file)
@@ -120,7 +120,11 @@ _check_for_unexpected_kwargs (const gchar *function_name,
             }
         }
 
-        if (g_hash_table_lookup (arg_name_hash, PyBytes_AsString(key)) == NULL) {
+        /* Use extended lookup because it returns whether or not the key actually
+         * exists in the hash table. g_hash_table_lookup returns NULL for keys not
+         * found which maps to index 0 for our hash lookup.
+         */
+        if (!g_hash_table_lookup_extended (arg_name_hash, PyBytes_AsString(key), NULL, NULL)) {
             PyErr_Format (PyExc_TypeError,
                           "%.200s() got an unexpected keyword argument '%.400s'",
                           function_name,
@@ -161,12 +165,12 @@ _py_args_combine_and_check_length (PyGICallableCache *cache,
 
     /* Fast path, we already have the exact number of args and not kwargs. */
     n_expected_args = g_slist_length (cache->arg_name_list);
-    if (n_py_kwargs == 0 && n_py_args == n_expected_args) {
+    if (n_py_kwargs == 0 && n_py_args == n_expected_args && cache->user_data_varargs_index < 0) {
         Py_INCREF (py_args);
         return py_args;
     }
 
-    if (n_expected_args < n_py_args) {
+    if (cache->user_data_varargs_index < 0 && n_expected_args < n_py_args) {
         PyErr_Format (PyExc_TypeError,
                       "%.200s() takes exactly %d %sargument%s (%zd given)",
                       function_name,
@@ -177,6 +181,13 @@ _py_args_combine_and_check_length (PyGICallableCache *cache,
         return NULL;
     }
 
+    if (cache->user_data_varargs_index >= 0 && n_py_kwargs > 0 && n_expected_args < n_py_args) {
+        PyErr_Format (PyExc_TypeError,
+                      "%.200s() cannot use variable user data arguments with keyword arguments",
+                      function_name);
+        return NULL;
+    }
+
     if (n_py_kwargs > 0 && !_check_for_unexpected_kwargs (function_name,
                                                           cache->arg_name_hash,
                                                           py_kwargs)) {
@@ -187,39 +198,73 @@ _py_args_combine_and_check_length (PyGICallableCache *cache,
      * when they are combined into a single tuple */
     combined_py_args = PyTuple_New (n_expected_args);
 
-    for (i = 0; i < n_py_args; i++) {
-        PyObject *item = PyTuple_GET_ITEM (py_args, i);
-        Py_INCREF (item);
-        PyTuple_SET_ITEM (combined_py_args, i, item);
-    }
-
     for (i = 0, l = cache->arg_name_list; i < n_expected_args && l; i++, l = l->next) {
-        PyObject *py_arg_item, *kw_arg_item = NULL;
+        PyObject *py_arg_item = NULL;
+        PyObject *kw_arg_item = NULL;
         const gchar *arg_name = l->data;
+        int arg_cache_index = -1;
+        gboolean is_varargs_user_data = FALSE;
+
+        if (arg_name != NULL)
+            arg_cache_index = GPOINTER_TO_INT (g_hash_table_lookup (cache->arg_name_hash, arg_name));
+
+        is_varargs_user_data = cache->user_data_varargs_index >= 0 &&
+                                arg_cache_index == cache->user_data_varargs_index;
 
         if (n_py_kwargs > 0 && arg_name != NULL) {
             /* NULL means this argument has no keyword name */
             /* ex. the first argument to a method or constructor */
             kw_arg_item = PyDict_GetItemString (py_kwargs, arg_name);
         }
-        py_arg_item = PyTuple_GET_ITEM (combined_py_args, i);
 
-        if (kw_arg_item != NULL && py_arg_item == NULL) {
-            Py_INCREF (kw_arg_item);
-            PyTuple_SET_ITEM (combined_py_args, i, kw_arg_item);
+        /* use a bounded retrieval of the original input */
+        if (i < n_py_args)
+            py_arg_item = PyTuple_GET_ITEM (py_args, i);
+
+        if (kw_arg_item == NULL && py_arg_item != NULL) {
+            if (is_varargs_user_data) {
+                /* For tail end user_data varargs, pull a slice off and we are done. */
+                PyObject *user_data = PyTuple_GetSlice (py_args, i, PY_SSIZE_T_MAX);
+                PyTuple_SET_ITEM (combined_py_args, i, user_data);
+                return combined_py_args;
+            } else {
+                Py_INCREF (py_arg_item);
+                PyTuple_SET_ITEM (combined_py_args, i, py_arg_item);
+            }
+        } else if (kw_arg_item != NULL && py_arg_item == NULL) {
+            if (is_varargs_user_data) {
+                /* Special case where user_data is passed as a keyword argument (user_data=foo)
+                 * Wrap the value in a tuple to represent variable args for marshaling later on.
+                 */
+                PyObject *user_data = Py_BuildValue("(O)", kw_arg_item, NULL);
+                PyTuple_SET_ITEM (combined_py_args, i, user_data);
+            } else {
+                Py_INCREF (kw_arg_item);
+                PyTuple_SET_ITEM (combined_py_args, i, kw_arg_item);
+            }
 
         } else if (kw_arg_item == NULL && py_arg_item == NULL) {
-            PyErr_Format (PyExc_TypeError,
-                          "%.200s() takes exactly %d %sargument%s (%zd given)",
-                          function_name,
-                          n_expected_args,
-                          n_py_kwargs > 0 ? "non-keyword " : "",
-                          n_expected_args == 1 ? "" : "s",
-                          n_py_args);
-
-            Py_DECREF (combined_py_args);
-            return NULL;
-
+            if (is_varargs_user_data) {
+                /* For varargs user_data, pass an empty tuple when nothing is given. */
+                PyTuple_SET_ITEM (combined_py_args, i, PyTuple_New (0));
+            } else if (arg_cache_index >= 0 && _pygi_callable_cache_get_arg (cache, arg_cache_index)->has_default) {
+                /* If the argument supports a default, use a place holder in the
+                 * argument tuple, this will be checked later during marshaling.
+                 */
+                Py_INCREF (_PyGIDefaultArgPlaceholder);
+                PyTuple_SET_ITEM (combined_py_args, i, _PyGIDefaultArgPlaceholder);
+            } else {
+                PyErr_Format (PyExc_TypeError,
+                              "%.200s() takes exactly %d %sargument%s (%zd given)",
+                              function_name,
+                              n_expected_args,
+                              n_py_kwargs > 0 ? "non-keyword " : "",
+                              n_expected_args == 1 ? "" : "s",
+                              n_py_args);
+
+                Py_DECREF (combined_py_args);
+                return NULL;
+            }
         } else if (kw_arg_item != NULL && py_arg_item != NULL) {
             PyErr_Format (PyExc_TypeError,
                           "%.200s() got multiple values for keyword argument '%.200s'",
@@ -299,14 +344,14 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
     }
     state->n_py_in_args = PyTuple_Size (state->py_in_args);
 
-    state->args = g_slice_alloc0 (cache->n_args * sizeof (GIArgument *));
-    if (state->args == NULL && cache->n_args != 0) {
+    state->args = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (GIArgument *));
+    if (state->args == NULL && _pygi_callable_cache_args_len (cache) != 0) {
         PyErr_NoMemory();
         return FALSE;
     }
 
-    state->args_data = g_slice_alloc0 (cache->n_args * sizeof (gpointer));
-    if (state->args_data == NULL && cache->n_args != 0) {
+    state->args_cleanup_data = g_slice_alloc0 (_pygi_callable_cache_args_len (cache) * sizeof (gpointer));
+    if (state->args_cleanup_data == NULL && _pygi_callable_cache_args_len (cache) != 0) {
         PyErr_NoMemory();
         return FALSE;
     }
@@ -337,8 +382,8 @@ _invoke_state_init_from_callable_cache (PyGIInvokeState *state,
 static inline void
 _invoke_state_clear (PyGIInvokeState *state, PyGICallableCache *cache)
 {
-    g_slice_free1 (cache->n_args * sizeof(GIArgument *), state->args);
-    g_slice_free1 (cache->n_args * sizeof(gpointer), state->args_data);
+    g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(GIArgument *), state->args);
+    g_slice_free1 (_pygi_callable_cache_args_len (cache) * sizeof(gpointer), state->args_cleanup_data);
     g_slice_free1 (cache->n_from_py_args * sizeof(GIArgument), state->in_args);
     g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_args);
     g_slice_free1 (cache->n_to_py_args * sizeof(GIArgument), state->out_values);
@@ -408,9 +453,9 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
         return FALSE;
     }
 
-    for (i = 0; i < cache->n_args; i++) {
+    for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
         GIArgument *c_arg;
-        PyGIArgCache *arg_cache = cache->args_cache[i];
+        PyGIArgCache *arg_cache = g_ptr_array_index (cache->args_cache, i);
         PyObject *py_arg = NULL;
 
         switch (arg_cache->direction) {
@@ -490,8 +535,12 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
         }
 
         c_arg = state->args[i];
-        if (arg_cache->from_py_marshaller != NULL) {
+        if (py_arg == _PyGIDefaultArgPlaceholder) {
+            *c_arg = arg_cache->default_value;
+        } else if (arg_cache->from_py_marshaller != NULL) {
             gboolean success;
+            gpointer cleanup_data = NULL;
+
             if (!arg_cache->allow_none && py_arg == Py_None) {
                 PyErr_Format (PyExc_TypeError,
                               "Argument %zd does not allow None as a value",
@@ -503,10 +552,13 @@ _invoke_marshal_in_args (PyGIInvokeState *state, PyGICallableCache *cache)
                  return FALSE;
             }
             success = arg_cache->from_py_marshaller (state,
-                                                              cache,
-                                                              arg_cache,
-                                                              py_arg,
-                                                              c_arg);
+                                                     cache,
+                                                     arg_cache,
+                                                     py_arg,
+                                                     c_arg,
+                                                     &cleanup_data);
+            state->args_cleanup_data[i] = cleanup_data;
+
             if (!success) {
                 pygi_marshal_cleanup_args_from_py_parameter_fail (state,
                                                                   cache,
@@ -563,6 +615,7 @@ _invoke_marshal_out_args (PyGIInvokeState *state, PyGICallableCache *cache)
                 if (to_py_cleanup != NULL)
                     to_py_cleanup ( state,
                                     cache->return_cache,
+                                    NULL,
                                    &state->return_arg,
                                     FALSE);
             }
@@ -652,9 +705,9 @@ pygi_callable_info_invoke (GIBaseInfo *info, PyObject *py_args,
     if (!_invoke_callable (&state, cache, info, function_ptr))
         goto err;
 
+    ret = _invoke_marshal_out_args (&state, cache);
     pygi_marshal_cleanup_args_from_py_marshal_success (&state, cache);
 
-    ret = _invoke_marshal_out_args (&state, cache);
     if (ret)
         pygi_marshal_cleanup_args_to_py_marshal_success (&state, cache);
 err:
index c197bab..33d0339 100644 (file)
@@ -24,6 +24,7 @@
 static inline void
 _cleanup_caller_allocates (PyGIInvokeState    *state,
                            PyGIArgCache       *cache,
+                           PyObject           *py_obj,
                            gpointer            data,
                            gboolean            was_processed)
 {
@@ -93,20 +94,23 @@ pygi_marshal_cleanup_args_from_py_marshal_success (PyGIInvokeState   *state,
 {
     gssize i;
 
-    /* For in success, call cleanup for all GI_DIRECTION_IN values only. */
-    for (i = 0; i < cache->n_args; i++) {
-        PyGIArgCache *arg_cache = cache->args_cache[i];
+    for (i = 0; i < _pygi_callable_cache_args_len (cache); i++) {
+        PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
         PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
-
-        if (cleanup_func &&
-                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);
+        PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args,
+                                             arg_cache->py_arg_index);
+        gpointer cleanup_data = state->args_cleanup_data[i];
+
+        /* Only cleanup using args_cleanup_data when available.
+         * It is the responsibility of the various "from_py" marshalers to return
+         * cleanup_data which is then passed into their respective cleanup function.
+         * PyGIInvokeState.args_cleanup_data stores this data (via _invoke_marshal_in_args)
+         * for the duration of the invoke up until this point.
+         */
+        if (cleanup_func && cleanup_data != NULL &&
+                arg_cache->direction & PYGI_DIRECTION_FROM_PYTHON) {
+            cleanup_func (state, arg_cache, py_arg, cleanup_data, TRUE);
+            state->args_cleanup_data[i] = NULL;
         }
     }
 }
@@ -122,6 +126,7 @@ pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState   *state,
         if (cleanup_func && state->return_arg.v_pointer != NULL)
             cleanup_func (state,
                           cache->return_cache,
+                          NULL,
                           state->return_arg.v_pointer,
                           TRUE);
     }
@@ -136,11 +141,13 @@ pygi_marshal_cleanup_args_to_py_marshal_success (PyGIInvokeState   *state,
         if (cleanup_func != NULL && data != NULL)
             cleanup_func (state,
                           arg_cache,
+                          NULL,
                           data,
                           TRUE);
         else if (arg_cache->is_caller_allocates && data != NULL) {
             _cleanup_caller_allocates (state,
                                        arg_cache,
+                                       NULL,
                                        data,
                                        TRUE);
         }
@@ -158,22 +165,26 @@ pygi_marshal_cleanup_args_from_py_parameter_fail (PyGIInvokeState   *state,
 
     state->failed = TRUE;
 
-    for (i = 0; i < cache->n_args  && i <= failed_arg_index; i++) {
-        PyGIArgCache *arg_cache = cache->args_cache[i];
+    for (i = 0; i < _pygi_callable_cache_args_len (cache)  && i <= failed_arg_index; i++) {
+        PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (cache, i);
         PyGIMarshalCleanupFunc cleanup_func = arg_cache->from_py_cleanup;
         gpointer data = state->args[i]->v_pointer;
+        PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args,
+                                             arg_cache->py_arg_index);
 
         if (cleanup_func &&
                 arg_cache->direction == PYGI_DIRECTION_FROM_PYTHON &&
                     data != NULL) {
             cleanup_func (state,
                           arg_cache,
+                          py_arg,
                           data,
                           i < failed_arg_index);
 
         } else if (arg_cache->is_caller_allocates && data != NULL) {
             _cleanup_caller_allocates (state,
                                        arg_cache,
+                                       py_arg,
                                        data,
                                        FALSE);
         }
@@ -198,18 +209,19 @@ pygi_marshal_cleanup_args_to_py_parameter_fail (PyGIInvokeState   *state,
 void
 _pygi_marshal_cleanup_from_py_utf8 (PyGIInvokeState *state,
                                     PyGIArgCache    *arg_cache,
+                                    PyObject        *py_arg,
                                     gpointer         data,
                                     gboolean         was_processed)
 {
-    /* We strdup strings so always free if we have processed this
-       parameter for input */
-    if (was_processed)
+    /* We strdup strings so free unless ownership is transferred to C. */
+    if (was_processed && arg_cache->transfer == GI_TRANSFER_NOTHING)
         g_free (data);
 }
 
 void
 _pygi_marshal_cleanup_to_py_utf8 (PyGIInvokeState *state,
                                   PyGIArgCache    *arg_cache,
+                                  PyObject        *dummy,
                                   gpointer         data,
                                   gboolean         was_processed)
 {
@@ -223,6 +235,7 @@ _pygi_marshal_cleanup_to_py_utf8 (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_from_py_interface_object (PyGIInvokeState *state,
                                                 PyGIArgCache    *arg_cache,
+                                                PyObject        *py_arg,
                                                 gpointer         data,
                                                 gboolean         was_processed)
 {
@@ -236,6 +249,7 @@ _pygi_marshal_cleanup_from_py_interface_object (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *state,
                                               PyGIArgCache    *arg_cache,
+                                              PyObject        *dummy,
                                               gpointer         data,
                                               gboolean         was_processed)
 {
@@ -249,28 +263,31 @@ _pygi_marshal_cleanup_to_py_interface_object (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_from_py_interface_callback (PyGIInvokeState *state,
                                                   PyGIArgCache    *arg_cache,
+                                                  PyObject        *py_arg,
                                                   gpointer         data,
                                                   gboolean         was_processed)
 {
     PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
     if (was_processed && callback_cache->scope == GI_SCOPE_TYPE_CALL) {
-        _pygi_invoke_closure_free (state->args_data[arg_cache->c_arg_index]);
-        state->args_data[arg_cache->c_arg_index] = NULL;
+        _pygi_invoke_closure_free (data);
     }
 }
 
 void 
 _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
                                                        PyGIArgCache    *arg_cache,
+                                                       PyObject        *py_arg,
                                                        gpointer         data,
                                                        gboolean         was_processed)
 {
-    if (was_processed) {
-        PyObject *py_arg = PyTuple_GET_ITEM (state->py_in_args,
-                                             arg_cache->py_arg_index);
+    /* Note py_arg can be NULL for hash table which is a bug. */
+    if (was_processed && py_arg != NULL) {
         GType py_object_type =
             pyg_type_from_object_strict ( (PyObject *) py_arg->ob_type, FALSE);
 
+        /* When a GValue was not passed, it means the marshalers created a new
+         * one to pass in, clean this up.
+         */
         if (py_object_type != G_TYPE_VALUE) {
             g_value_unset ((GValue *) data);
             g_slice_free (GValue, data);
@@ -281,6 +298,7 @@ _pygi_marshal_cleanup_from_py_interface_struct_gvalue (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state,
                                                         PyGIArgCache    *arg_cache,
+                                                        PyObject        *py_arg,
                                                         gpointer         data,
                                                         gboolean         was_processed)
 {
@@ -293,6 +311,7 @@ _pygi_marshal_cleanup_from_py_interface_struct_foreign (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
                                                       PyGIArgCache    *arg_cache,
+                                                      PyObject        *dummy,
                                                       gpointer         data,
                                                       gboolean         was_processed)
 {
@@ -336,6 +355,7 @@ _wrap_c_array (PyGIInvokeState   *state,
 void
 _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
                                      PyGIArgCache    *arg_cache,
+                                     PyObject        *py_arg,
                                      gpointer         data,
                                      gboolean         was_processed)
 {
@@ -344,15 +364,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
         GPtrArray *ptr_array_ = NULL;
         PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
 
-        /* If this isn't a garray create one to help process variable sized
-           array elements */
-        if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
-            array_ = _wrap_c_array (state, sequence_cache, data);
-            
-            if (array_ == NULL)
-                return;
-            
-        } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+        if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
             ptr_array_ = (GPtrArray *) data;
         } else {
             array_ = (GArray *) data;
@@ -367,6 +379,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
 
             for (i = 0; i < len; i++) {
                 gpointer item;
+                PyObject *py_item = NULL;
 
                 /* case 1: GPtrArray */
                 if (ptr_array_ != NULL)
@@ -387,19 +400,23 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
                     }
                 }
 
-                cleanup_func (state, sequence_cache->item_cache, item, TRUE);
+                py_item = PySequence_GetItem (py_arg, i);
+                cleanup_func (state, sequence_cache->item_cache, py_item, item, TRUE);
+                Py_XDECREF (py_item);
             }
         }
 
         /* Only free the array when we didn't transfer ownership */
         if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
+            /* always free the GArray wrapper created in from_py marshaling and
+             * passed back as cleanup_data
+             */
             g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
-        } else if (state->failed ||
-                   arg_cache->transfer == GI_TRANSFER_NOTHING) {
+        } else {
             if (array_ != NULL)
-                g_array_free (array_, TRUE);
+                g_array_unref (array_);
             else
-                g_ptr_array_free (ptr_array_, TRUE);
+                g_ptr_array_unref (ptr_array_);
         }
     }
 }
@@ -407,6 +424,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
                                    PyGIArgCache    *arg_cache,
+                                   PyObject        *dummy,
                                    gpointer         data,
                                    gboolean         was_processed)
 {
@@ -438,6 +456,7 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
             for (i = 0; i < len; i++) {
                 cleanup_func (state,
                               sequence_cache->item_cache,
+                              NULL,
                               (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
                               was_processed);
             }
@@ -453,6 +472,7 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_from_py_glist  (PyGIInvokeState *state,
                                       PyGIArgCache    *arg_cache,
+                                      PyObject        *py_arg,
                                       gpointer         data,
                                       gboolean         was_processed)
 {
@@ -467,28 +487,26 @@ _pygi_marshal_cleanup_from_py_glist  (PyGIInvokeState *state,
             PyGIMarshalCleanupFunc cleanup_func =
                 sequence_cache->item_cache->from_py_cleanup;
             GSList *node = list_;
+            gsize i = 0;
             while (node != NULL) {
+                PyObject *py_item = PySequence_GetItem (py_arg, i);
                 cleanup_func (state,
                               sequence_cache->item_cache,
+                              py_item,
                               node->data,
                               TRUE);
+                Py_XDECREF (py_item);
                 node = node->next;
+                i++;
             }
         }
 
-        if (state->failed ||
-               arg_cache->transfer == GI_TRANSFER_NOTHING ||
-                  arg_cache->transfer == GI_TRANSFER_CONTAINER) {
-            switch (arg_cache->type_tag) {
-                case GI_TYPE_TAG_GLIST:
-                    g_list_free ( (GList *)list_);
-                    break;
-                case GI_TYPE_TAG_GSLIST:
-                    g_slist_free (list_);
-                    break;
-                default:
-                    g_assert_not_reached();
-            }
+        if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) {
+            g_list_free ( (GList *)list_);
+        } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) {
+            g_slist_free (list_);
+        } else {
+            g_assert_not_reached();
         }
     }
 }
@@ -496,11 +514,11 @@ _pygi_marshal_cleanup_from_py_glist  (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
                                    PyGIArgCache    *arg_cache,
+                                   PyObject        *dummy,
                                    gpointer         data,
                                    gboolean         was_processed)
 {
     PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
-
     if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
             arg_cache->transfer == GI_TRANSFER_CONTAINER) {
         GSList *list_ = (GSList *)data;
@@ -513,23 +531,19 @@ _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
             while (node != NULL) {
                 cleanup_func (state,
                               sequence_cache->item_cache,
+                              NULL,
                               node->data,
                               was_processed);
                 node = node->next;
             }
         }
 
-        if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
-            switch (arg_cache->type_tag) {
-                case GI_TYPE_TAG_GLIST:
-                    g_list_free ( (GList *)list_);
-                    break;
-                case GI_TYPE_TAG_GSLIST:
-                    g_slist_free (list_);
-                    break;
-                default:
-                    g_assert_not_reached();
-            }
+        if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) {
+            g_list_free ( (GList *)list_);
+        } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) {
+            g_slist_free (list_);
+        } else {
+            g_assert_not_reached();
         }
     }
 }
@@ -537,6 +551,7 @@ _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
 void
 _pygi_marshal_cleanup_from_py_ghash  (PyGIInvokeState *state,
                                       PyGIArgCache    *arg_cache,
+                                      PyObject        *py_arg,
                                       gpointer         data,
                                       gboolean         was_processed)
 {
@@ -566,27 +581,26 @@ _pygi_marshal_cleanup_from_py_ghash  (PyGIInvokeState *state,
                 if (key != NULL && key_cleanup_func != NULL)
                     key_cleanup_func (state,
                                       hash_cache->key_cache,
+                                      NULL,
                                       key,
                                       TRUE);
                 if (value != NULL && value_cleanup_func != NULL)
                     value_cleanup_func (state,
                                         hash_cache->value_cache,
+                                        NULL,
                                         value,
                                         TRUE);
             }
         }
 
-        if (state->failed ||
-               arg_cache->transfer == GI_TRANSFER_NOTHING ||
-                  arg_cache->transfer == GI_TRANSFER_CONTAINER)
-            g_hash_table_destroy (hash_);
-
+        g_hash_table_unref (hash_);
     }
 }
 
 void
 _pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state,
                                    PyGIArgCache    *arg_cache,
+                                   PyObject        *dummy,
                                    gpointer         data,
                                    gboolean         was_processed)
 {
@@ -594,6 +608,6 @@ _pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state,
         return;
 
     /* assume hashtable has boxed key and value */
-    if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
-        g_hash_table_destroy ( (GHashTable *)data);
+    if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER)
+        g_hash_table_unref ( (GHashTable *)data);
 }
index 234e49c..3acfbeb 100644 (file)
@@ -42,58 +42,72 @@ void pygi_marshal_cleanup_args_to_py_parameter_fail  (PyGIInvokeState   *state,
 
 void _pygi_marshal_cleanup_from_py_utf8                      (PyGIInvokeState *state,
                                                               PyGIArgCache    *arg_cache,
+                                                              PyObject        *py_arg,
                                                               gpointer         data,
                                                               gboolean         was_processed);
 void _pygi_marshal_cleanup_to_py_utf8                        (PyGIInvokeState *state,
                                                               PyGIArgCache    *arg_cache,
+                                                              PyObject        *dummy,
                                                               gpointer         data,
                                                               gboolean         was_processed);
 void _pygi_marshal_cleanup_from_py_interface_struct_gvalue   (PyGIInvokeState *state,
                                                               PyGIArgCache    *arg_cache,
+                                                              PyObject        *py_arg,
                                                               gpointer         data,
                                                               gboolean         was_processed);
 void _pygi_marshal_cleanup_from_py_interface_struct_foreign  (PyGIInvokeState *state,
                                                               PyGIArgCache    *arg_cache,
+                                                              PyObject        *py_arg,
                                                               gpointer         data,
                                                               gboolean         was_processed);
 void _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *dummy,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_from_py_interface_object       (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *py_arg,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_to_py_interface_object         (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *dummy,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_from_py_interface_callback     (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *py_arg,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_from_py_array                  (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *py_arg,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_to_py_array                    (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *dummy,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_from_py_glist                  (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *py_arg,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_to_py_glist                    (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *dummy,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_from_py_ghash                  (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *py_arg,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 void _pygi_marshal_cleanup_to_py_ghash                    (PyGIInvokeState *state,
                                                            PyGIArgCache    *arg_cache,
+                                                           PyObject        *dummy,
                                                            gpointer         data,
                                                            gboolean         was_processed);
 G_END_DECLS
index 57b4126..7bcba66 100644 (file)
@@ -247,7 +247,8 @@ _pygi_marshal_from_py_void (PyGIInvokeState   *state,
                             PyGICallableCache *callable_cache,
                             PyGIArgCache      *arg_cache,
                             PyObject          *py_arg,
-                            GIArgument        *arg)
+                            GIArgument        *arg,
+                            gpointer          *cleanup_data)
 {
     g_warn_if_fail (arg_cache->transfer == GI_TRANSFER_NOTHING);
 
@@ -255,23 +256,16 @@ _pygi_marshal_from_py_void (PyGIInvokeState   *state,
         arg->v_pointer = NULL;
     } else if (PYGLIB_CPointer_Check(py_arg)) {
         arg->v_pointer = PYGLIB_CPointer_GetPointer (py_arg, NULL);
+    } else if (PYGLIB_PyLong_Check(py_arg) || PyLong_Check(py_arg)) {
+        arg->v_pointer = PyLong_AsVoidPtr (py_arg);
     } else {
-        /* NOTE: This will change to only allow integers and the deprecation
-         * warning will become a runtime exception. Using the following:
-         * arg->v_pointer = PyLong_AsVoidPtr (py_arg);
-         * See: https://bugzilla.gnome.org/show_bug.cgi?id=688081
-         */
-
-        if (!PYGLIB_PyLong_Check(py_arg) && !PyLong_Check(py_arg)) {
-            if (PyErr_WarnEx(PyGIDeprecationWarning,
-                             "Pointer arguments will be restricted to integers, capsules, and None. "
-                             "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599",
-                             1))
-                return FALSE;
-        }
-        arg->v_pointer = py_arg;
+        PyErr_SetString(PyExc_ValueError,
+                        "Pointer arguments are restricted to integers, capsules, and None. "
+                        "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
+        return FALSE;
     }
 
+    *cleanup_data = arg->v_pointer;
     return TRUE;
 }
 
@@ -416,7 +410,8 @@ _pygi_marshal_from_py_gtype (PyObject          *py_arg,
 
 static gboolean
 _pygi_marshal_from_py_utf8 (PyObject          *py_arg,
-                            GIArgument        *arg)
+                            GIArgument        *arg,
+                            gpointer          *cleanup_data)
 {
     gchar *string_;
 
@@ -445,12 +440,14 @@ _pygi_marshal_from_py_utf8 (PyObject          *py_arg,
     }
 
     arg->v_string = string_;
+    *cleanup_data = arg->v_string;
     return TRUE;
 }
 
 static gboolean
 _pygi_marshal_from_py_filename (PyObject          *py_arg,
-                                GIArgument        *arg)
+                                GIArgument        *arg,
+                                gpointer          *cleanup_data)
 {
     gchar *string_;
     GError *error = NULL;
@@ -484,6 +481,7 @@ _pygi_marshal_from_py_filename (PyObject          *py_arg,
         return FALSE;
     }
 
+    *cleanup_data = arg->v_string;
     return TRUE;
 }
 
@@ -634,7 +632,8 @@ gboolean
 _pygi_marshal_from_py_basic_type (PyObject   *object,   /* in */
                                   GIArgument *arg,      /* out */
                                   GITypeTag   type_tag,
-                                  GITransfer  transfer)
+                                  GITransfer  transfer,
+                                  gpointer   *cleanup_data /* out */)
 {
     switch (type_tag) {
         case GI_TYPE_TAG_VOID:
@@ -647,6 +646,7 @@ _pygi_marshal_from_py_basic_type (PyObject   *object,   /* in */
                     "See: https://bugzilla.gnome.org/show_bug.cgi?id=683599");
             } else {
                 arg->v_pointer = PyLong_AsVoidPtr (object);
+                *cleanup_data = arg->v_pointer;
             }
             break;
         case GI_TYPE_TAG_INT8:
@@ -690,10 +690,10 @@ _pygi_marshal_from_py_basic_type (PyObject   *object,   /* in */
             return _pygi_marshal_from_py_unichar (object, arg);
 
         case GI_TYPE_TAG_UTF8:
-            return _pygi_marshal_from_py_utf8 (object, arg);
+            return _pygi_marshal_from_py_utf8 (object, arg, cleanup_data);
 
         case GI_TYPE_TAG_FILENAME:
-            return _pygi_marshal_from_py_filename (object, arg);
+            return _pygi_marshal_from_py_filename (object, arg, cleanup_data);
 
         default:
             return FALSE;
@@ -710,12 +710,14 @@ _pygi_marshal_from_py_basic_type_cache_adapter (PyGIInvokeState   *state,
                                                 PyGICallableCache *callable_cache,
                                                 PyGIArgCache      *arg_cache,
                                                 PyObject          *py_arg,
-                                                GIArgument        *arg)
+                                                GIArgument        *arg,
+                                                gpointer          *cleanup_data)
 {
     return _pygi_marshal_from_py_basic_type (py_arg,
                                              arg,
                                              arg_cache->type_tag,
-                                             arg_cache->transfer);
+                                             arg_cache->transfer,
+                                             cleanup_data);
 }
 
 gboolean
@@ -723,10 +725,12 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
                              PyGICallableCache *callable_cache,
                              PyGIArgCache      *arg_cache,
                              PyObject          *py_arg,
-                             GIArgument        *arg)
+                             GIArgument        *arg,
+                             gpointer          *cleanup_data)
 {
     PyGIMarshalFromPyFunc from_py_marshaller;
     int i = 0;
+    int success_count = 0;
     Py_ssize_t length;
     gssize item_size;
     gboolean is_ptr_array;
@@ -760,10 +764,10 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
     item_size = sequence_cache->item_size;
     is_ptr_array = (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
     if (is_ptr_array) {
-        array_ = (GArray *)g_ptr_array_new ();
+        array_ = (GArray *)g_ptr_array_sized_new (length);
     } else {
         array_ = g_array_sized_new (sequence_cache->is_zero_terminated,
-                                    FALSE,
+                                    TRUE,
                                     item_size,
                                     length);
     }
@@ -786,8 +790,9 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
     }
 
     from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
-    for (i = 0; i < length; i++) {
-        GIArgument item;
+    for (i = 0, success_count = 0; i < length; i++) {
+        GIArgument item = {0};
+        gpointer item_cleanup_data = NULL;
         PyObject *py_item = PySequence_GetItem (py_arg, i);
         if (py_item == NULL)
             goto err;
@@ -796,8 +801,26 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
                                   callable_cache,
                                   sequence_cache->item_cache,
                                   py_item,
-                                 &item))
+                                 &item,
+                                 &item_cleanup_data)) {
+            Py_DECREF (py_item);
+            goto err;
+        }
+        Py_DECREF (py_item);
+
+        if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) {
+            /* We only support one level of data discrepancy between an items
+             * data and its cleanup data. This is because we only track a single
+             * extra cleanup data pointer per-argument and cannot track the entire
+             * array of items differing data and cleanup_data.
+             * For example, this would fail if trying to marshal an array of
+             * callback closures marked with SCOPE call type where the cleanup data
+             * is different from the items v_pointer, likewise an array of arrays.
+             */
+            PyErr_SetString(PyExc_RuntimeError, "Cannot cleanup item data for array due to "
+                                                "the items data its cleanup data being different.");
             goto err;
+        }
 
         /* FIXME: it is much more efficent to have seperate marshaller
          *        for ptr arrays than doing the evaluation
@@ -805,7 +828,12 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
          */
         if (is_ptr_array) {
             g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
+        } else if (sequence_cache->item_cache->is_pointer) {
+            /* if the item is a pointer, simply copy the pointer */
+            g_assert (item_size == sizeof (item.v_pointer));
+            g_array_insert_val (array_, i, item);
         } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
+            /* Special case handling of flat arrays of gvalue/boxed/struct */
             PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
             GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
             GIInfoType info_type = g_base_info_get_type (base_info);
@@ -816,58 +844,41 @@ _pygi_marshal_from_py_array (PyGIInvokeState   *state,
                 {
                     PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
                     PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
-                    gboolean is_boxed = g_type_is_a (item_iface_cache->g_type, G_TYPE_BOXED);
-                    gboolean is_gvalue = item_iface_cache->g_type == G_TYPE_VALUE;
-                    gboolean is_gvariant = item_iface_cache->g_type == G_TYPE_VARIANT;
-                    
-                    if (is_gvariant) {
-                        /* Item size will always be that of a pointer,
-                         * since GVariants are opaque hence always passed by ref */
-                        g_assert (item_size == sizeof (item.v_pointer));
-                        g_array_insert_val (array_, i, item.v_pointer);
-                    } else if (is_gvalue) {
+
+                    if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) {
+                        /* Special case GValue flat arrays to properly init and copy the contents. */
                         GValue* dest = (GValue*) (array_->data + (i * item_size));
-                        memset (dest, 0, item_size);
                         if (item.v_pointer != NULL) {
+                            memset (dest, 0, item_size);
                             g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
                             g_value_copy ((GValue*) item.v_pointer, dest);
                         }
-                        /* 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);
-                    } 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
-                         * value, and don't attempt to free it. TODO: find out
-                         * if there are other data types with similar behaviour
-                         * and generalize. */
-                        if (g_strcmp0 (item_iface_cache->type_name, "Gdk.Atom") == 0) {
-                            g_assert (item_size == sizeof (item.v_pointer));
-                            memcpy (array_->data + (i * item_size), &item.v_pointer, item_size);
-                        } else {
-                            memcpy (array_->data + (i * item_size), item.v_pointer, item_size);
-
-                            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);
+                        /* Manually increment the length because we are manually setting the memory. */
+                        array_->len++;
+
                     } else {
-                        g_array_insert_val (array_, i, item);
+                        /* Handles flat arrays of boxed or struct types. */
+                        g_array_insert_vals (array_, i, item.v_pointer, 1);
                     }
+
+                    /* Cleanup any memory left by the per-item marshaler because
+                     * _pygi_marshal_cleanup_from_py_array will not know about this
+                     * due to "item" being a temporarily marshaled value done on the stack.
+                     */
+                    if (from_py_cleanup)
+                        from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE);
+
                     break;
                 }
                 default:
                     g_array_insert_val (array_, i, item);
             }
         } else {
+            /* default value copy of a simple type */
             g_array_insert_val (array_, i, item);
         }
+
+        success_count++;
         continue;
 err:
         if (sequence_cache->item_cache->from_py_cleanup != NULL) {
@@ -875,11 +886,19 @@ err:
             PyGIMarshalCleanupFunc cleanup_func =
                 sequence_cache->item_cache->from_py_cleanup;
 
-            for(j = 0; j < i; j++) {
-                cleanup_func (state,
-                              sequence_cache->item_cache,
-                              g_array_index (array_, gpointer, j),
-                              TRUE);
+            /* Only attempt per item cleanup on pointer items */
+            if (sequence_cache->item_cache->is_pointer) {
+                for(j = 0; j < success_count; j++) {
+                    PyObject *py_item = PySequence_GetItem (py_arg, j);
+                    cleanup_func (state,
+                                  sequence_cache->item_cache,
+                                  py_item,
+                                  is_ptr_array ?
+                                          g_ptr_array_index ((GPtrArray *)array_, j) :
+                                          g_array_index (array_, gpointer, j),
+                                  TRUE);
+                    Py_DECREF (py_item);
+                }
             }
         }
 
@@ -895,7 +914,7 @@ array_success:
     if (sequence_cache->len_arg_index >= 0) {
         /* we have an child arg to handle */
         PyGIArgCache *child_cache =
-            callable_cache->args_cache[sequence_cache->len_arg_index];
+            _pygi_callable_cache_get_arg (callable_cache, sequence_cache->len_arg_index);
 
         if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) {
             gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer;
@@ -919,14 +938,34 @@ array_success:
     }
 
     if (sequence_cache->array_type == GI_ARRAY_TYPE_C) {
+        /* In the case of GI_ARRAY_C, we give the data directly as the argument
+         * but keep the array_ wrapper as cleanup data so we don't have to find
+         * it's length again.
+         */
         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;
+
+        if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
+            g_array_free (array_, FALSE);
+            *cleanup_data = NULL;
+        } else {
+            *cleanup_data = array_;
+        }
     } else {
         arg->v_pointer = array_;
+
+        if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+            /* Free everything in cleanup. */
+            *cleanup_data = array_;
+        } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+            /* Make a shallow copy so we can free the elements later in cleanup
+             * because it is possible invoke will free the list before our cleanup. */
+            *cleanup_data = is_ptr_array ?
+                    (gpointer)g_ptr_array_ref ((GPtrArray *)array_) :
+                    (gpointer)g_array_ref (array_);
+        } else { /* GI_TRANSFER_EVERYTHING */
+            /* No cleanup, everything is given to the callee. */
+            *cleanup_data = NULL;
+        }
     }
 
     return TRUE;
@@ -937,7 +976,8 @@ _pygi_marshal_from_py_glist (PyGIInvokeState   *state,
                              PyGICallableCache *callable_cache,
                              PyGIArgCache      *arg_cache,
                              PyObject          *py_arg,
-                             GIArgument        *arg)
+                             GIArgument        *arg,
+                             gpointer          *cleanup_data)
 {
     PyGIMarshalFromPyFunc from_py_marshaller;
     int i;
@@ -971,7 +1011,8 @@ _pygi_marshal_from_py_glist (PyGIInvokeState   *state,
 
     from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
     for (i = 0; i < length; i++) {
-        GIArgument item;
+        GIArgument item = {0};
+        gpointer item_cleanup_data = NULL;
         PyObject *py_item = PySequence_GetItem (py_arg, i);
         if (py_item == NULL)
             goto err;
@@ -980,9 +1021,11 @@ _pygi_marshal_from_py_glist (PyGIInvokeState   *state,
                                   callable_cache,
                                   sequence_cache->item_cache,
                                   py_item,
-                                 &item))
+                                 &item,
+                                 &item_cleanup_data))
             goto err;
 
+        Py_DECREF (py_item);
         list_ = g_list_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_tag));
         continue;
 err:
@@ -991,12 +1034,25 @@ err:
             PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
         }
         */
+        Py_DECREF (py_item);
         g_list_free (list_);
         _PyGI_ERROR_PREFIX ("Item %i: ", i);
         return FALSE;
     }
 
     arg->v_pointer = g_list_reverse (list_);
+
+    if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+        /* Free everything in cleanup. */
+        *cleanup_data = arg->v_pointer;
+    } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+        /* Make a shallow copy so we can free the elements later in cleanup
+         * because it is possible invoke will free the list before our cleanup. */
+        *cleanup_data = g_list_copy (arg->v_pointer);
+    } else { /* GI_TRANSFER_EVERYTHING */
+        /* No cleanup, everything is given to the callee. */
+        *cleanup_data = NULL;
+    }
     return TRUE;
 }
 
@@ -1005,7 +1061,8 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState   *state,
                               PyGICallableCache *callable_cache,
                               PyGIArgCache      *arg_cache,
                               PyObject          *py_arg,
-                              GIArgument        *arg)
+                              GIArgument        *arg,
+                              gpointer          *cleanup_data)
 {
     PyGIMarshalFromPyFunc from_py_marshaller;
     int i;
@@ -1038,7 +1095,8 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState   *state,
 
     from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
     for (i = 0; i < length; i++) {
-        GIArgument item;
+        GIArgument item = {0};
+        gpointer item_cleanup_data = NULL;
         PyObject *py_item = PySequence_GetItem (py_arg, i);
         if (py_item == NULL)
             goto err;
@@ -1047,9 +1105,11 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState   *state,
                              callable_cache,
                              sequence_cache->item_cache,
                              py_item,
-                            &item))
+                            &item,
+                            &item_cleanup_data))
             goto err;
 
+        Py_DECREF (py_item);
         list_ = g_slist_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_tag));
         continue;
 err:
@@ -1059,12 +1119,26 @@ err:
         }
         */
 
+        Py_DECREF (py_item);
         g_slist_free (list_);
         _PyGI_ERROR_PREFIX ("Item %i: ", i);
         return FALSE;
     }
 
     arg->v_pointer = g_slist_reverse (list_);
+
+    if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+        /* Free everything in cleanup. */
+        *cleanup_data = arg->v_pointer;
+    } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+        /* Make a shallow copy so we can free the elements later in cleanup
+         * because it is possible invoke will free the list before our cleanup. */
+        *cleanup_data = g_slist_copy (arg->v_pointer);
+    } else { /* GI_TRANSFER_EVERYTHING */
+        /* No cleanup, everything is given to the callee. */
+        *cleanup_data = NULL;
+    }
+
     return TRUE;
 }
 
@@ -1073,7 +1147,8 @@ _pygi_marshal_from_py_ghash (PyGIInvokeState   *state,
                              PyGICallableCache *callable_cache,
                              PyGIArgCache      *arg_cache,
                              PyObject          *py_arg,
-                             GIArgument        *arg)
+                             GIArgument        *arg,
+                             gpointer          *cleanup_data)
 {
     PyGIMarshalFromPyFunc key_from_py_marshaller;
     PyGIMarshalFromPyFunc value_from_py_marshaller;
@@ -1136,6 +1211,8 @@ _pygi_marshal_from_py_ghash (PyGIInvokeState   *state,
 
     for (i = 0; i < length; i++) {
         GIArgument key, value;
+        gpointer key_cleanup_data = NULL;
+        gpointer value_cleanup_data = NULL;
         PyObject *py_key = PyList_GET_ITEM (py_keys, i);
         PyObject *py_value = PyList_GET_ITEM (py_values, i);
         if (py_key == NULL || py_value == NULL)
@@ -1145,14 +1222,16 @@ _pygi_marshal_from_py_ghash (PyGIInvokeState   *state,
                                       callable_cache,
                                       hash_cache->key_cache,
                                       py_key,
-                                     &key))
+                                     &key,
+                                     &key_cleanup_data))
             goto err;
 
         if (!value_from_py_marshaller ( state,
                                         callable_cache,
                                         hash_cache->value_cache,
                                         py_value,
-                                       &value))
+                                       &value,
+                                       &value_cleanup_data))
             goto err;
 
         g_hash_table_insert (hash_,
@@ -1171,6 +1250,21 @@ err:
     }
 
     arg->v_pointer = hash_;
+
+    if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
+        /* Free everything in cleanup. */
+        *cleanup_data = arg->v_pointer;
+    } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
+        /* Make a shallow copy so we can free the elements later in cleanup
+         * because it is possible invoke will free the list before our cleanup. */
+        *cleanup_data = g_hash_table_ref (arg->v_pointer);
+    } else { /* GI_TRANSFER_EVERYTHING */
+        /* No cleanup, everything is given to the callee.
+         * Note that the keys and values will leak for transfer everything because
+         * we do not use g_hash_table_new_full and set key/value_destroy_func. */
+        *cleanup_data = NULL;
+    }
+
     return TRUE;
 }
 
@@ -1179,7 +1273,8 @@ _pygi_marshal_from_py_gerror (PyGIInvokeState   *state,
                               PyGICallableCache *callable_cache,
                               PyGIArgCache      *arg_cache,
                               PyObject          *py_arg,
-                              GIArgument        *arg)
+                              GIArgument        *arg,
+                              gpointer          *cleanup_data)
 {
     PyErr_Format (PyExc_NotImplementedError,
                   "Marshalling for GErrors is not implemented");
@@ -1245,7 +1340,8 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState   *state,
                                           PyGICallableCache *callable_cache,
                                           PyGIArgCache      *arg_cache,
                                           PyObject          *py_arg,
-                                          GIArgument        *arg)
+                                          GIArgument        *arg,
+                                          gpointer          *cleanup_data)
 {
     GICallableInfo *callable_info;
     PyGICClosure *closure;
@@ -1257,12 +1353,17 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState   *state,
     callback_cache = (PyGICallbackCache *)arg_cache;
 
     if (callback_cache->user_data_index > 0) {
-        user_data_cache = callable_cache->args_cache[callback_cache->user_data_index];
+        user_data_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->user_data_index);
         if (user_data_cache->py_arg_index < state->n_py_in_args) {
             /* py_user_data is a borrowed reference. */
             py_user_data = PyTuple_GetItem (state->py_in_args, user_data_cache->py_arg_index);
             if (!py_user_data)
                 return FALSE;
+            /* NULL out user_data if it was not supplied and the default arg placeholder
+             * was used instead.
+             */
+            if (py_user_data == _PyGIDefaultArgPlaceholder)
+                py_user_data = NULL;
         }
     }
 
@@ -1305,7 +1406,7 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState   *state,
      * later on in _pygi_destroy_notify_callback_closure.
      */
     if (callback_cache->destroy_notify_index > 0) {
-        destroy_cache = callable_cache->args_cache[callback_cache->destroy_notify_index];
+        destroy_cache = _pygi_callable_cache_get_arg (callable_cache, callback_cache->destroy_notify_index);
     }
 
     if (destroy_cache) {
@@ -1327,10 +1428,8 @@ _pygi_marshal_from_py_interface_callback (PyGIInvokeState   *state,
         }
     }
 
-    /* Store the PyGIClosure as extra args data so _pygi_marshal_cleanup_from_py_interface_callback
-     * can clean it up later for GI_SCOPE_TYPE_CALL based closures.
-     */
-    state->args_data[arg_cache->c_arg_index] = closure;
+    /* Use the PyGIClosure as data passed to cleanup for GI_SCOPE_TYPE_CALL. */
+    *cleanup_data = closure;
 
     return TRUE;
 }
@@ -1340,7 +1439,8 @@ _pygi_marshal_from_py_interface_enum (PyGIInvokeState   *state,
                                       PyGICallableCache *callable_cache,
                                       PyGIArgCache      *arg_cache,
                                       PyObject          *py_arg,
-                                      GIArgument        *arg)
+                                      GIArgument        *arg,
+                                      gpointer          *cleanup_data)
 {
     PyObject *py_long;
     long c_long;
@@ -1408,7 +1508,8 @@ _pygi_marshal_from_py_interface_flags (PyGIInvokeState   *state,
                                        PyGICallableCache *callable_cache,
                                        PyGIArgCache      *arg_cache,
                                        PyObject          *py_arg,
-                                       GIArgument        *arg)
+                                       GIArgument        *arg,
+                                       gpointer          *cleanup_data)
 {
     PyObject *py_long;
     long c_long;
@@ -1455,20 +1556,27 @@ _pygi_marshal_from_py_interface_struct_cache_adapter (PyGIInvokeState   *state,
                                                       PyGICallableCache *callable_cache,
                                                       PyGIArgCache      *arg_cache,
                                                       PyObject          *py_arg,
-                                                      GIArgument        *arg)
+                                                      GIArgument        *arg,
+                                                      gpointer          *cleanup_data)
 {
     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
 
-    return _pygi_marshal_from_py_interface_struct (py_arg,
-                                                   arg,
-                                                   arg_cache->arg_name,
-                                                   iface_cache->interface_info,
-                                                   arg_cache->type_info,
-                                                   iface_cache->g_type,
-                                                   iface_cache->py_type,
-                                                   arg_cache->transfer,
-                                                   TRUE, /*copy_reference*/
-                                                   iface_cache->is_foreign);
+    gboolean res =  _pygi_marshal_from_py_interface_struct (py_arg,
+                                                            arg,
+                                                            arg_cache->arg_name,
+                                                            iface_cache->interface_info,
+                                                            iface_cache->g_type,
+                                                            iface_cache->py_type,
+                                                            arg_cache->transfer,
+                                                            TRUE, /*copy_reference*/
+                                                            iface_cache->is_foreign,
+                                                            arg_cache->is_pointer);
+
+    /* Assume struct marshaling is always a pointer and assign cleanup_data
+     * here rather than passing it further down the chain.
+     */
+    *cleanup_data = arg->v_pointer;
+    return res;
 }
 
 gboolean
@@ -1476,7 +1584,8 @@ _pygi_marshal_from_py_interface_boxed (PyGIInvokeState   *state,
                                        PyGICallableCache *callable_cache,
                                        PyGIArgCache      *arg_cache,
                                        PyObject          *py_arg,
-                                       GIArgument        *arg)
+                                       GIArgument        *arg,
+                                       gpointer          *cleanup_data)
 {
     PyErr_Format (PyExc_NotImplementedError,
                   "Marshalling for this type is not implemented yet");
@@ -1488,8 +1597,11 @@ _pygi_marshal_from_py_interface_object (PyGIInvokeState   *state,
                                         PyGICallableCache *callable_cache,
                                         PyGIArgCache      *arg_cache,
                                         PyObject          *py_arg,
-                                        GIArgument        *arg)
+                                        GIArgument        *arg,
+                                        gpointer          *cleanup_data)
 {
+    gboolean res = FALSE;
+
     if (py_arg == Py_None) {
         arg->v_pointer = NULL;
         return TRUE;
@@ -1509,7 +1621,9 @@ _pygi_marshal_from_py_interface_object (PyGIInvokeState   *state,
         return FALSE;
     }
 
-    return _pygi_marshal_from_py_gobject (py_arg, arg, arg_cache->transfer);
+    res = _pygi_marshal_from_py_gobject (py_arg, arg, arg_cache->transfer);
+    *cleanup_data = arg->v_pointer;
+    return res;
 }
 
 gboolean
@@ -1517,90 +1631,14 @@ _pygi_marshal_from_py_interface_union (PyGIInvokeState   *state,
                                        PyGICallableCache *callable_cache,
                                        PyGIArgCache      *arg_cache,
                                        PyObject          *py_arg,
-                                       GIArgument        *arg)
+                                       GIArgument        *arg,
+                                       gpointer          *cleanup_data)
 {
     PyErr_Format(PyExc_NotImplementedError,
                  "Marshalling for this type is not implemented yet");
     return FALSE;
 }
 
-gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState   *state,
-                                                   PyGICallableCache *callable_cache,
-                                                   PyGIArgCache      *arg_cache,
-                                                   PyObject          *py_arg,
-                                                   GIArgument        *arg)
-{
-    GIInfoType info_type;
-    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
-
-    info_type = g_base_info_get_type (iface_cache->interface_info);
-    switch (info_type) {
-        case GI_INFO_TYPE_UNION:
-        case GI_INFO_TYPE_STRUCT:
-        {
-            GType type = iface_cache->g_type;
-
-            if (!PyObject_IsInstance (py_arg, iface_cache->py_type)) {
-                /* wait, we might be a member of a union so manually check */
-                if (!_is_union_member (iface_cache->interface_info, py_arg)) {
-                    if (!PyErr_Occurred()) {
-                        PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
-                        PyErr_Format (PyExc_TypeError,
-                                      "argument %s: Expected a %s, but got %s%s%s",
-                                      arg_cache->arg_name ? arg_cache->arg_name : "self",
-                                      iface_cache->type_name,
-                                      module ? PYGLIB_PyUnicode_AsString(module) : "",
-                                      module ? "." : "",
-                                      py_arg->ob_type->tp_name);
-                        if (module)
-                            Py_DECREF (module);
-                    }
-                    return FALSE;
-                }
-            }
-
-            if (g_type_is_a (type, G_TYPE_BOXED)) {
-                arg->v_pointer = pyg_boxed_get (py_arg, void);
-            } else if (g_type_is_a (type, G_TYPE_POINTER) ||
-                           g_type_is_a (type, G_TYPE_VARIANT) ||
-                               type == G_TYPE_NONE) {
-                arg->v_pointer = pyg_pointer_get (py_arg, void);
-            } else {
-                 PyErr_Format (PyExc_TypeError, "unable to convert an instance of '%s'", g_type_name (type));
-                 return FALSE;
-            }
-
-            break;
-        }
-        case GI_INFO_TYPE_OBJECT:
-        case GI_INFO_TYPE_INTERFACE:
-            arg->v_pointer = pygobject_get (py_arg);
-            if (arg->v_pointer != NULL) {
-                GType obj_type = G_OBJECT_TYPE (( GObject *)arg->v_pointer);
-                GType expected_type = iface_cache->g_type;
-
-                if (!g_type_is_a (obj_type, expected_type)) {
-                    PyObject *module = PyObject_GetAttrString(py_arg, "__module__");
-                    PyErr_Format (PyExc_TypeError, "argument %s: Expected %s, but got %s%s%s",
-                                  arg_cache->arg_name ? arg_cache->arg_name : "self",
-                                  iface_cache->type_name,
-                                  module ? PYGLIB_PyUnicode_AsString(module) : "",
-                                  module ? "." : "",
-                                  py_arg->ob_type->tp_name);
-                    if (module)
-                        Py_DECREF (module);
-                    return FALSE;
-                }
-            }
-            break;
-        default:
-            /* Other types don't have methods. */
-            g_assert_not_reached ();
-   }
-
-   return TRUE;
-}
-
 /* _pygi_marshal_from_py_gobject:
  * py_arg: (in):
  * arg: (out):
@@ -1773,12 +1811,12 @@ _pygi_marshal_from_py_interface_struct (PyObject *py_arg,
                                         GIArgument *arg,
                                         const gchar *arg_name,
                                         GIBaseInfo *interface_info,
-                                        GITypeInfo *type_info,
                                         GType g_type,
                                         PyObject *py_type,
                                         GITransfer transfer,
                                         gboolean copy_reference,
-                                        gboolean is_foreign)
+                                        gboolean is_foreign,
+                                        gboolean is_pointer)
 {
     gboolean is_union = FALSE;
 
@@ -1834,7 +1872,7 @@ _pygi_marshal_from_py_interface_struct (PyObject *py_arg,
     } else if (g_type_is_a (g_type, G_TYPE_POINTER) ||
                g_type_is_a (g_type, G_TYPE_VARIANT) ||
                g_type  == G_TYPE_NONE) {
-        g_warn_if_fail (g_type_is_a (g_type, G_TYPE_VARIANT) || !g_type_info_is_pointer (type_info) || transfer == GI_TRANSFER_NOTHING);
+        g_warn_if_fail (g_type_is_a (g_type, G_TYPE_VARIANT) || !is_pointer || transfer == GI_TRANSFER_NOTHING);
 
         if (g_type_is_a (g_type, G_TYPE_VARIANT) &&
                 pyg_type_from_object (py_arg) != G_TYPE_VARIANT) {
@@ -1842,6 +1880,9 @@ _pygi_marshal_from_py_interface_struct (PyObject *py_arg,
             return FALSE;
         }
         arg->v_pointer = pyg_pointer_get (py_arg, void);
+        if (transfer == GI_TRANSFER_EVERYTHING) {
+            g_variant_ref ((GVariant *)arg->v_pointer);
+        }
 
     } else {
         PyErr_Format (PyExc_NotImplementedError,
index 9f56a6f..f8e4699 100644 (file)
@@ -37,88 +37,93 @@ gboolean _pygi_marshal_from_py_void        (PyGIInvokeState   *state,
                                             PyGICallableCache *callable_cache,
                                             PyGIArgCache      *arg_cache,
                                             PyObject          *py_arg,
-                                            GIArgument        *arg);
+                                            GIArgument        *arg,
+                                            gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_array       (PyGIInvokeState   *state,
                                             PyGICallableCache *callable_cache,
                                             PyGIArgCache      *arg_cache,
                                             PyObject          *py_arg,
-                                            GIArgument        *arg);
+                                            GIArgument        *arg,
+                                            gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_glist       (PyGIInvokeState   *state,
                                             PyGICallableCache *callable_cache,
                                             PyGIArgCache      *arg_cache,
                                             PyObject          *py_arg,
-                                            GIArgument        *arg);
+                                            GIArgument        *arg,
+                                            gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_gslist      (PyGIInvokeState   *state,
                                             PyGICallableCache *callable_cache,
                                             PyGIArgCache      *arg_cache,
                                             PyObject          *py_arg,
-                                            GIArgument        *arg);
+                                            GIArgument        *arg,
+                                            gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_ghash       (PyGIInvokeState   *state,
                                             PyGICallableCache *callable_cache,
                                             PyGIArgCache      *arg_cache,
                                             PyObject          *py_arg,
-                                            GIArgument        *arg);
+                                            GIArgument        *arg,
+                                            gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_gerror      (PyGIInvokeState   *state,
                                             PyGICallableCache *callable_cache,
                                             PyGIArgCache      *arg_cache,
                                             PyObject          *py_arg,
-                                            GIArgument        *arg);
+                                            GIArgument        *arg,
+                                            gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_interface_callback (PyGIInvokeState   *state,
                                                    PyGICallableCache *callable_cache,
                                                    PyGIArgCache      *arg_cache,
                                                    PyObject          *py_arg,
-                                                   GIArgument        *arg);
+                                                   GIArgument        *arg,
+                                                   gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_interface_enum     (PyGIInvokeState   *state,
                                                    PyGICallableCache *callable_cache,
                                                    PyGIArgCache      *arg_cache,
                                                    PyObject          *py_arg,
-                                                   GIArgument        *arg);
+                                                   GIArgument        *arg,
+                                                   gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_interface_flags    (PyGIInvokeState   *state,
                                                    PyGICallableCache *callable_cache,
                                                    PyGIArgCache      *arg_cache,
                                                    PyObject          *py_arg,
-                                                   GIArgument        *arg);
+                                                   GIArgument        *arg,
+                                                   gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_interface_struct_cache_adapter   (PyGIInvokeState   *state,
                                                                  PyGICallableCache *callable_cache,
                                                                  PyGIArgCache      *arg_cache,
                                                                  PyObject          *py_arg,
-                                                                 GIArgument        *arg);
-gboolean _pygi_marshal_from_py_interface_interface(PyGIInvokeState   *state,
-                                                   PyGICallableCache *callable_cache,
-                                                   PyGIArgCache      *arg_cache,
-                                                   PyObject          *py_arg,
-                                                   GIArgument        *arg);
+                                                                 GIArgument        *arg,
+                                                                 gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_interface_boxed    (PyGIInvokeState   *state,
                                                    PyGICallableCache *callable_cache,
                                                    PyGIArgCache      *arg_cache,
                                                    PyObject          *py_arg,
-                                                   GIArgument        *arg);
+                                                   GIArgument        *arg,
+                                                   gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_interface_object   (PyGIInvokeState   *state,
                                                    PyGICallableCache *callable_cache,
                                                    PyGIArgCache      *arg_cache,
                                                    PyObject          *py_arg,
-                                                   GIArgument        *arg);
+                                                   GIArgument        *arg,
+                                                   gpointer          *cleanup_data);
 gboolean _pygi_marshal_from_py_interface_union    (PyGIInvokeState   *state,
                                                    PyGICallableCache *callable_cache,
                                                    PyGIArgCache      *arg_cache,
                                                    PyObject          *py_arg,
-                                                   GIArgument        *arg);
-gboolean _pygi_marshal_from_py_interface_instance (PyGIInvokeState   *state,
-                                                   PyGICallableCache *callable_cache,
-                                                   PyGIArgCache      *arg_cache,
-                                                   PyObject          *py_arg,
-                                                   GIArgument        *arg);
+                                                   GIArgument        *arg,
+                                                   gpointer          *cleanup_data);
 
 /* Simplified marshalers shared between vfunc/closure and direct function calls. */
 gboolean _pygi_marshal_from_py_basic_type (PyObject   *object,   /* in */
                                            GIArgument *arg,      /* out */
                                            GITypeTag   type_tag,
-                                           GITransfer  transfer);
+                                           GITransfer  transfer,
+                                           gpointer   *cleanup_data);
 gboolean _pygi_marshal_from_py_basic_type_cache_adapter  (PyGIInvokeState   *state,
                                                           PyGICallableCache *callable_cache,
                                                           PyGIArgCache      *arg_cache,
                                                           PyObject          *py_arg,
-                                                          GIArgument        *arg);
+                                                          GIArgument        *arg,
+                                                          gpointer          *cleanup_data);
 
 gboolean _pygi_marshal_from_py_gobject (PyObject *py_arg, /*in*/
                                         GIArgument *arg,  /*out*/
@@ -139,12 +144,12 @@ gboolean _pygi_marshal_from_py_interface_struct (PyObject *py_arg,
                                                  GIArgument *arg,
                                                  const gchar *arg_name,
                                                  GIBaseInfo *interface_info,
-                                                 GITypeInfo *type_info,
                                                  GType g_type,
                                                  PyObject *py_type,
                                                  GITransfer transfer,
-                                                gboolean is_allocated,
-                                                gboolean is_foreign);
+                                                 gboolean is_allocated,
+                                                 gboolean is_foreign,
+                                                 gboolean is_pointer);
 
 G_END_DECLS
 
index 7c260f7..2c7a8de 100644 (file)
@@ -117,20 +117,10 @@ _pygi_marshal_to_py_void (PyGIInvokeState   *state,
                           PyGIArgCache      *arg_cache,
                           GIArgument        *arg)
 {
-    PyObject *py_obj = NULL;
     if (arg_cache->is_pointer) {
-        /* NOTE: This will change to interpret pointers as integer values
-         * by using the following:
-         * py_obj = PyLong_FromVoidPtr (arg->v_pointer);
-         * See: https://bugzilla.gnome.org/show_bug.cgi?id=688081
-         */
-        py_obj = arg->v_pointer;
-    } else {
-        py_obj = Py_None;
+        return PyLong_FromVoidPtr (arg->v_pointer);
     }
-
-    Py_XINCREF (py_obj);
-    return py_obj;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -306,10 +296,10 @@ _pygi_marshal_to_py_array (PyGIInvokeState   *state,
             }
         } else {
             GIArgument *len_arg = state->args[seq_cache->len_arg_index];
+            PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
+                                                                    seq_cache->len_arg_index);
 
-            if (!gi_argument_to_gsize (len_arg,
-                                       &len,
-                                       callable_cache->args_cache[seq_cache->len_arg_index]->type_tag)) {
+            if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
                 return NULL;
             }
         }
@@ -361,36 +351,35 @@ _pygi_marshal_to_py_array (PyGIInvokeState   *state,
             item_size = g_array_get_element_size (array_);
 
             for (i = 0; i < array_->len; i++) {
-                GIArgument item_arg;
+                GIArgument item_arg = {0};
                 PyObject *py_item;
 
+                /* If we are receiving an array of pointers, simply assign the pointer
+                 * and move on, letting the per-item marshaler deal with the
+                 * various transfer modes and ref counts (e.g. g_variant_ref_sink).
+                 */
                 if (seq_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
                     item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
+
+                } else if (item_arg_cache->is_pointer) {
+                    item_arg.v_pointer = g_array_index (array_, gpointer, i);
+
                 } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
                     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
-                    gboolean is_gvariant = iface_cache->g_type == G_TYPE_VARIANT;
 
                     // FIXME: This probably doesn't work with boxed types or gvalues. See fx. _pygi_marshal_from_py_array()
                     switch (g_base_info_get_type (iface_cache->interface_info)) {
                         case GI_INFO_TYPE_STRUCT:
-                            if (is_gvariant) {
-                              g_assert (item_size == sizeof (gpointer));
-                              if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
-                                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 && !item_arg_cache->is_pointer &&
+                            if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
                                        !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)
-                                /* array elements are pointers to values */
-                                item_arg.v_pointer = g_array_index (array_, gpointer, i);
-                            else
+                            } else {
                                 item_arg.v_pointer = array_->data + i * item_size;
+                            }
                             break;
                         default:
                             item_arg.v_pointer = g_array_index (array_, gpointer, i);
@@ -435,6 +424,7 @@ err:
             for (j = processed_items; j < array_->len; j++) {
                 cleanup_func (state,
                               seq_cache->item_cache,
+                              NULL,
                               g_array_index (array_, gpointer, j),
                               FALSE);
             }
@@ -867,10 +857,13 @@ _pygi_marshal_to_py_interface_struct (GIArgument *arg,
                                        transfer == GI_TRANSFER_EVERYTHING);
         }
     } else if (g_type_is_a (g_type, G_TYPE_VARIANT)) {
-        /* Note we do not use transfer for the structs free_on_dealloc because
-         * GLib.Variant overrides __del__ to call "g_variant_unref". */
+        /* Note: sink the variant (add a ref) only if we are not transfered ownership.
+         * GLib.Variant overrides __del__ which will then call "g_variant_unref" for
+         * cleanup in either case. */
         if (py_type) {
-            g_variant_ref_sink (arg->v_pointer);
+            if (transfer == GI_TRANSFER_NOTHING) {
+                g_variant_ref_sink (arg->v_pointer);
+            }
             py_obj = _pygi_struct_new ((PyTypeObject *) py_type,
                                        arg->v_pointer,
                                        FALSE);
index 3bf40bb..dcd91b3 100644 (file)
--- a/gi/pygi.h
+++ b/gi/pygi.h
@@ -33,6 +33,7 @@
 #include "pygi-cache.h"
 
 extern PyObject *PyGIDeprecationWarning;
+extern PyObject *_PyGIDefaultArgPlaceholder;
 
 typedef struct {
     PyObject_HEAD
index aa8bef5..72cbd29 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
index dc9b80b..ab80a82 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
index b845e4b..a7b0323 100644 (file)
@@ -110,6 +110,7 @@ EXTRA_DIST = \
        test_atoms.py \
        test_generictreemodel.py \
        test_docstring.py \
+       test_repository.py \
        compat_test_pygtk.py \
        gi/__init__.py \
        gi/overrides/__init__.py \
@@ -152,4 +153,12 @@ check.nemiver:
        EXEC_NAME="nemiver" $(MAKE) check
 
 check.valgrind:
-       EXEC_NAME="valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
+       EXEC_NAME="G_SLICE=always-malloc valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
+
+check.valgrindlog:
+       mkdir -p $(top_builddir)/tmp
+       EXEC_NAME="G_SLICE=always-malloc valgrind --log-file=$(top_builddir)/tmp/`git rev-parse HEAD | cut -c1-8`-$$TEST_NAMES.log --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
+
+check.valgrindxml:
+       mkdir -p $(top_builddir)/tmp
+       EXEC_NAME="G_SLICE=always-malloc valgrind --xml=yes --xml-file=$(top_builddir)/tmp/`git rev-parse HEAD | cut -c1-8`-$$TEST_NAMES.xml --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
index 7eda339..fc936c6 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.14 from Makefile.am.
+# Makefile.in generated by automake 1.13.3 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994-2013 Free Software Foundation, Inc.
@@ -410,6 +410,7 @@ EXTRA_DIST = \
        test_atoms.py \
        test_generictreemodel.py \
        test_docstring.py \
+       test_repository.py \
        compat_test_pygtk.py \
        gi/__init__.py \
        gi/overrides/__init__.py \
@@ -494,14 +495,14 @@ distclean-compile:
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
 
 .c.obj:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
 @am__fastdepCC_TRUE@   $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_FALSE@  $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
 
 .c.lo:
 @am__fastdepCC_TRUE@   $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@@ -832,7 +833,15 @@ check.nemiver:
        EXEC_NAME="nemiver" $(MAKE) check
 
 check.valgrind:
-       EXEC_NAME="valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
+       EXEC_NAME="G_SLICE=always-malloc valgrind --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
+
+check.valgrindlog:
+       mkdir -p $(top_builddir)/tmp
+       EXEC_NAME="G_SLICE=always-malloc valgrind --log-file=$(top_builddir)/tmp/`git rev-parse HEAD | cut -c1-8`-$$TEST_NAMES.log --leak-check=full --show-possibly-lost=no --suppressions=python.supp" G_DEBUG=gc-friendly $(MAKE) check
+
+check.valgrindxml:
+       mkdir -p $(top_builddir)/tmp
+       EXEC_NAME="G_SLICE=always-malloc valgrind --xml=yes --xml-file=$(top_builddir)/tmp/`git rev-parse HEAD | cut -c1-8`-$$TEST_NAMES.xml --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 1628295..54349b8 100644 (file)
@@ -2,6 +2,7 @@ import unittest
 
 import gi.docstring
 from gi.repository import GIMarshallingTests
+from gi.repository import Gio
 
 
 class Test(unittest.TestCase):
@@ -47,3 +48,12 @@ class Test(unittest.TestCase):
     def test_overridden_doc_is_not_clobbered(self):
         self.assertEqual(GIMarshallingTests.OverridesObject.method.__doc__,
                          'Overridden doc string.')
+
+    def test_allow_none_with_user_data_defaults(self):
+        g_file_copy_doc = 'copy(self, destination:Gio.File, ' \
+                          'flags:Gio.FileCopyFlags, ' \
+                          'cancellable:Gio.Cancellable=None, ' \
+                          'progress_callback:Gio.FileProgressCallback=None, ' \
+                          'progress_callback_data=None)'
+
+        self.assertEqual(Gio.File.copy.__doc__, g_file_copy_doc)
index b2f0528..5c4ba6b 100644 (file)
@@ -717,6 +717,51 @@ class TestCallbacks(unittest.TestCase):
 
         self.assertEqual(TestCallbacks.called, 100)
 
+    def test_callback_userdata_no_user_data(self):
+        TestCallbacks.called = 0
+
+        def callback():
+            TestCallbacks.called += 1
+            return TestCallbacks.called
+
+        for i in range(100):
+            val = Everything.test_callback_user_data(callback)
+            self.assertEqual(val, i + 1)
+
+        self.assertEqual(TestCallbacks.called, 100)
+
+    def test_callback_userdata_varargs(self):
+        TestCallbacks.called = 0
+        collected_user_data = []
+
+        def callback(a, b):
+            collected_user_data.extend([a, b])
+            TestCallbacks.called += 1
+            return TestCallbacks.called
+
+        for i in range(10):
+            val = Everything.test_callback_user_data(callback, 1, 2)
+            self.assertEqual(val, i + 1)
+
+        self.assertEqual(TestCallbacks.called, 10)
+        self.assertSequenceEqual(collected_user_data, [1, 2] * 10)
+
+    def test_callback_userdata_as_kwarg_tuple(self):
+        TestCallbacks.called = 0
+        collected_user_data = []
+
+        def callback(user_data):
+            collected_user_data.extend(user_data)
+            TestCallbacks.called += 1
+            return TestCallbacks.called
+
+        for i in range(10):
+            val = Everything.test_callback_user_data(callback, user_data=(1, 2))
+            self.assertEqual(val, i + 1)
+
+        self.assertEqual(TestCallbacks.called, 10)
+        self.assertSequenceEqual(collected_user_data, [1, 2] * 10)
+
     def test_async_ready_callback(self):
         TestCallbacks.called = False
         TestCallbacks.main_loop = GLib.MainLoop()
index da55187..43c226e 100644 (file)
@@ -813,6 +813,15 @@ class TestArray(unittest.TestCase):
 
         GIMarshallingTests.array_struct_in([struct1, struct2, struct3])
 
+    def test_array_boxed_struct_in_item_marshal_failure(self):
+        struct1 = GIMarshallingTests.BoxedStruct()
+        struct1.long_ = 1
+        struct2 = GIMarshallingTests.BoxedStruct()
+        struct2.long_ = 2
+
+        self.assertRaises(TypeError, GIMarshallingTests.array_struct_in,
+                          [struct1, struct2, 'not_a_struct'])
+
     def test_array_boxed_struct_value_in(self):
         struct1 = GIMarshallingTests.BoxedStruct()
         struct1.long_ = 1
@@ -823,6 +832,15 @@ class TestArray(unittest.TestCase):
 
         GIMarshallingTests.array_struct_value_in([struct1, struct2, struct3])
 
+    def test_array_boxed_struct_value_in_item_marshal_failure(self):
+        struct1 = GIMarshallingTests.BoxedStruct()
+        struct1.long_ = 1
+        struct2 = GIMarshallingTests.BoxedStruct()
+        struct2.long_ = 2
+
+        self.assertRaises(TypeError, GIMarshallingTests.array_struct_value_in,
+                          [struct1, struct2, 'not_a_struct'])
+
     def test_array_boxed_struct_take_in(self):
         struct1 = GIMarshallingTests.BoxedStruct()
         struct1.long_ = 1
@@ -854,6 +872,15 @@ class TestArray(unittest.TestCase):
 
         GIMarshallingTests.array_simple_struct_in([struct1, struct2, struct3])
 
+    def test_array_simple_struct_in_item_marshal_failure(self):
+        struct1 = GIMarshallingTests.SimpleStruct()
+        struct1.long_ = 1
+        struct2 = GIMarshallingTests.SimpleStruct()
+        struct2.long_ = 2
+
+        self.assertRaises(TypeError, GIMarshallingTests.array_simple_struct_in,
+                          [struct1, struct2, 'not_a_struct'])
+
     def test_array_multi_array_key_value_in(self):
         GIMarshallingTests.multi_array_key_value_in(["one", "two", "three"],
                                                     [1, 2, 3])
@@ -1219,8 +1246,6 @@ class TestGValue(unittest.TestCase):
         value = GObject.Value(GObject.TYPE_INT, 42)
         GIMarshallingTests.gvalue_in(value)
 
-    @unittest.skipUnless(hasattr(GIMarshallingTests, 'gvalue_in_with_modification'),
-                         'Newer version of gi needed.')
     def test_gvalue_in_with_modification(self):
         value = GObject.Value(GObject.TYPE_INT, 42)
         GIMarshallingTests.gvalue_in_with_modification(value)
@@ -1261,6 +1286,11 @@ class TestGValue(unittest.TestCase):
         # the function already asserts the correct values
         GIMarshallingTests.gvalue_flat_array([42, "42", True])
 
+    def test_gvalue_flat_array_in_item_marshal_failure(self):
+        # Tests the failure to marshal 2^256 to a GValue mid-way through the array marshaling.
+        self.assertRaises(RuntimeError, GIMarshallingTests.gvalue_flat_array,
+                          [42, 2 ** 256, True])
+
     def test_gvalue_flat_array_out(self):
         values = GIMarshallingTests.return_gvalue_flat_array()
         self.assertEqual(values, [42, '42', True])
@@ -1479,17 +1509,6 @@ class TestEnum(unittest.TestCase):
         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,
@@ -1648,17 +1667,6 @@ class TestNoTypeFlags(unittest.TestCase):
         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):
 
@@ -1986,7 +1994,11 @@ class TestGObject(unittest.TestCase):
 
         GIMarshallingTests.Object.none_inout(GIMarshallingTests.SubObject(int=42))
 
+    @unittest.expectedFailure  # https://bugzilla.gnome.org/show_bug.cgi?id=709796
     def test_object_full_inout(self):
+        # Using gimarshallingtests.c from GI versions > 1.38.0 will show this
+        # test as an "unexpected success" due to reference leak fixes in that file.
+        # TODO: remove the expectedFailure once PyGI relies on GI > 1.38.0.
         object_ = GIMarshallingTests.Object(int=42)
         new_object = GIMarshallingTests.Object.full_inout(object_)
 
@@ -1994,7 +2006,7 @@ class TestGObject(unittest.TestCase):
 
         self.assertFalse(object_ is new_object)
 
-        self.assertEqual(object_.__grefcount__, 2)
+        self.assertEqual(object_.__grefcount__, 1)
         self.assertEqual(new_object.__grefcount__, 1)
 
 # FIXME: Doesn't actually return the same object.
@@ -2642,6 +2654,36 @@ class TestKeywordArgs(unittest.TestCase):
         GIMarshallingTests.int_three_in_three_out(1, c=4, **d)
         self.assertEqual(d, d2)
 
+    @unittest.skipUnless(hasattr(GIMarshallingTests, 'int_one_in_utf8_two_in_one_allows_none'),
+                         'Requires newer GIMarshallingTests')
+    def test_allow_none_as_default(self):
+        GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2, '3', '4')
+        GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2, '3')
+        GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2)
+        GIMarshallingTests.int_two_in_utf8_two_in_with_allow_none(1, 2, d='4')
+
+        GIMarshallingTests.array_in_utf8_two_in_out_of_order('1', [-1, 0, 1, 2])
+        GIMarshallingTests.array_in_utf8_two_in_out_of_order('1', [-1, 0, 1, 2], '2')
+        self.assertRaises(TypeError,
+                          GIMarshallingTests.array_in_utf8_two_in_out_of_order,
+                          [-1, 0, 1, 2], a='1')
+        self.assertRaises(TypeError,
+                          GIMarshallingTests.array_in_utf8_two_in_out_of_order,
+                          [-1, 0, 1, 2])
+
+        GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2], '1', '2')
+        GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2], '1')
+        GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2])
+        GIMarshallingTests.array_in_utf8_two_in([-1, 0, 1, 2], b='2')
+
+        GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none(1, '2', '3')
+        self.assertRaises(TypeError,
+                          GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none,
+                          1, '3')
+        self.assertRaises(TypeError,
+                          GIMarshallingTests.int_one_in_utf8_two_in_one_allows_none,
+                          1, c='3')
+
 
 class TestPropertiesObject(unittest.TestCase):
 
@@ -2851,6 +2893,20 @@ class TestPropertiesObject(unittest.TestCase):
         self.assertEqual(42, obj.props.some_int)
         self.assertEqual(54, obj.props.some_uchar)
 
+    def test_props_accessor_dir(self):
+        # Test class
+        props = dir(GIMarshallingTests.PropertiesObject.props)
+        self.assertTrue('some_float' in props)
+        self.assertTrue('some_double' in props)
+        self.assertTrue('some_variant' in props)
+
+        # Test instance
+        obj = GIMarshallingTests.PropertiesObject()
+        props = dir(obj.props)
+        self.assertTrue('some_float' in props)
+        self.assertTrue('some_double' in props)
+        self.assertTrue('some_variant' in props)
+
 
 class TestKeywords(unittest.TestCase):
     def test_method(self):
@@ -2927,22 +2983,6 @@ class TestProjectVersion(unittest.TestCase):
         gi.check_version("3.3.5")
 
 
-class TestObjectInfo(unittest.TestCase):
-    def test_get_abstract_with_abstract(self):
-        repo = gi.gi.Repository.get_default()
-        info = repo.find_by_name('GObject', 'TypeModule')
-        self.assertTrue(info.get_abstract())
-
-    def test_get_abstract_with_concrete(self):
-        repo = gi.gi.Repository.get_default()
-        info = repo.find_by_name('GObject', 'Object')
-        self.assertFalse(info.get_abstract())
-
-    def test_get_class_struct(self):
-        self.assertEqual(GObject.Object.__info__.get_class_struct(),
-                         GObject.ObjectClass.__info__)
-
-
 class TestDeprecation(unittest.TestCase):
     def test_method(self):
         d = GLib.Date.new()
index 3cde168..a01e83e 100644 (file)
@@ -165,6 +165,27 @@ https://my.org/q?x=1&y=2
         self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b'a', 'moo'),
                                      (r, GLib.IOCondition.IN, b'b', 'moo')])
 
+    def test_io_add_watch_with_multiple_data(self):
+        (r, w) = os.pipe()
+        call_data = []
+
+        def cb(fd, condition, *user_data):
+            call_data.append((fd, condition, os.read(fd, 1), user_data))
+            return True
+
+        # io_add_watch() takes an IOChannel, calling with an fd is deprecated
+        with warnings.catch_warnings(record=True) as warn:
+            warnings.simplefilter('always')
+            GLib.io_add_watch(r, GLib.IOCondition.IN, cb, 'moo', 'foo')
+            self.assertTrue(issubclass(warn[0].category, PyGIDeprecationWarning))
+
+        ml = GLib.MainLoop()
+        GLib.timeout_add(10, lambda: os.write(w, b'a') and False)
+        GLib.timeout_add(100, ml.quit)
+        ml.run()
+
+        self.assertEqual(call_data, [(r, GLib.IOCondition.IN, b'a', ('moo', 'foo'))])
+
     def test_io_add_watch_pyfile(self):
         call_data = []
 
index 57d3822..d49011f 100644 (file)
@@ -415,6 +415,8 @@ class TestContextManagers(unittest.TestCase):
         self.assertEqual(self.tracking, [2])
 
 
+@unittest.skipUnless(hasattr(GObject.Binding, 'unbind'),
+                     'Requires newer GLib which has g_binding_unbind')
 class TestPropertyBindings(unittest.TestCase):
     class TestObject(GObject.GObject):
         int_prop = GObject.Property(default=0, type=int)
@@ -509,8 +511,8 @@ class TestPropertyBindings(unittest.TestCase):
                                             GObject.BindingFlags.BIDIRECTIONAL,
                                             transform_to, transform_from, test_data)
         binding = binding  # PyFlakes
-        binding_ref_count = sys.getrefcount(binding())
-        binding_gref_count = binding().__grefcount__
+        binding_ref_count = sys.getrefcount(binding)
+        binding_gref_count = binding.__grefcount__
 
         self.source.int_prop = 1
         self.assertEqual(self.source.int_prop, 1)
@@ -520,8 +522,8 @@ 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)
+        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)
@@ -530,9 +532,6 @@ class TestPropertyBindings(unittest.TestCase):
 
         # 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
@@ -554,8 +553,9 @@ class TestPropertyBindings(unittest.TestCase):
         self.assertEqual(self.source.int_prop, 1)
         self.assertEqual(self.target.int_prop, 1)
 
+        # unbind should clear out the bindings self reference
         binding.unbind()
-        self.assertEqual(binding(), None)
+        self.assertEqual(binding.__grefcount__, 1)
 
         self.source.int_prop = 10
         self.assertEqual(self.source.int_prop, 10)
@@ -572,7 +572,7 @@ class TestPropertyBindings(unittest.TestCase):
         # the act of binding and the ref incurred by using __call__ to generate
         # a wrapper from the weak binding ref within python.
         binding = self.source.bind_property('int_prop', self.target, 'int_prop')
-        self.assertEqual(binding().__grefcount__, 2)
+        self.assertEqual(binding.__grefcount__, 2)
 
         # Creating a binding does not inc refs on source and target (they are weak
         # on the binding object itself)
@@ -581,18 +581,25 @@ class TestPropertyBindings(unittest.TestCase):
 
         # Use GObject.get_property because the "props" accessor leaks.
         # Note property names are canonicalized.
-        self.assertEqual(binding().get_property('source'), self.source)
-        self.assertEqual(binding().get_property('source_property'), 'int-prop')
-        self.assertEqual(binding().get_property('target'), self.target)
-        self.assertEqual(binding().get_property('target_property'), 'int-prop')
-        self.assertEqual(binding().get_property('flags'), GObject.BindingFlags.DEFAULT)
-
-        # Delete reference to source or target and the binding should listen.
+        self.assertEqual(binding.get_property('source'), self.source)
+        self.assertEqual(binding.get_property('source_property'), 'int-prop')
+        self.assertEqual(binding.get_property('target'), self.target)
+        self.assertEqual(binding.get_property('target_property'), 'int-prop')
+        self.assertEqual(binding.get_property('flags'), GObject.BindingFlags.DEFAULT)
+
+        # Delete reference to source or target and the binding will remove its own
+        # "self reference".
         ref = self.source.weak_ref()
         del self.source
         gc.collect()
         self.assertEqual(ref(), None)
-        self.assertEqual(binding(), None)
+        self.assertEqual(binding.__grefcount__, 1)
+
+        # Finally clear out the last ref held by the python wrapper
+        ref = binding.weak_ref()
+        del binding
+        gc.collect()
+        self.assertEqual(ref(), None)
 
 
 class TestGValue(unittest.TestCase):
diff --git a/tests/test_repository.py b/tests/test_repository.py
new file mode 100644 (file)
index 0000000..6fd7906
--- /dev/null
@@ -0,0 +1,344 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# vim: tabstop=4 shiftwidth=4 expandtab
+#
+# Copyright (C) 2013 Simon Feltman <sfeltman@gnome.org>
+#
+#   test_repository.py: Test for the GIRepository module
+#
+# 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 St, Fifth Floor, Boston, MA  02110-1301
+# USA
+
+import unittest
+import collections
+
+import gi._gi as GIRepository
+from gi.module import repository as repo
+from gi.repository import GObject
+from gi.repository import GLib
+from gi.repository import GIMarshallingTests
+
+try:
+    import cairo
+    cairo
+    has_cairo = True
+except ImportError:
+    has_cairo = False
+
+
+def find_child_info(info, getter_name, name):
+    getter = getattr(info, getter_name)
+    for child in getter():
+        if child.get_name() == name:
+            return child
+    else:
+        raise ValueError('child info %s not found' % name)
+
+
+class Test(unittest.TestCase):
+    def setUp(self):
+        repo.require('GObject')
+        repo.require('GIMarshallingTests')
+
+    def test_arg_info(self):
+        func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
+        args = func_info.get_arguments()
+        self.assertTrue(len(args), 1)
+
+        arg = args[0]
+        self.assertEqual(arg.get_container(), func_info)
+        self.assertEqual(arg.get_direction(), GIRepository.Direction.OUT)
+        self.assertEqual(arg.get_name(), 'structs')
+        self.assertEqual(arg.get_namespace(), 'GIMarshallingTests')
+        self.assertEqual(arg.get_pytype_hint(), 'list')
+        self.assertFalse(arg.is_caller_allocates())
+        self.assertFalse(arg.is_optional())
+        self.assertFalse(arg.is_return_value())
+        self.assertFalse(arg.may_be_null())
+        self.assertEqual(arg.get_destroy(), -1)
+        self.assertEqual(arg.get_ownership_transfer(), GIRepository.Transfer.NOTHING)
+        self.assertEqual(arg.get_scope(), GIRepository.ScopeType.INVALID)
+        self.assertEqual(arg.get_type().get_tag(), GIRepository.TypeTag.ARRAY)
+
+    def test_base_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Object')
+        self.assertEqual(info.__name__, 'Object')
+        self.assertEqual(info.get_name(), 'Object')
+        self.assertEqual(info.__module__, 'gi.repository.GIMarshallingTests')
+        self.assertEqual(info.get_name_unescaped(), 'Object')
+        self.assertEqual(info.get_namespace(), 'GIMarshallingTests')
+        self.assertEqual(info.get_container(), None)
+        info2 = repo.find_by_name('GIMarshallingTests', 'Object')
+        self.assertFalse(info is info2)
+        self.assertEqual(info, info2)
+        self.assertTrue(info.equal(info2))
+
+    def test_object_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Object')
+        self.assertEqual(info.get_parent(), repo.find_by_name('GObject', 'Object'))
+        self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_interfaces(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
+        self.assertFalse(info.get_abstract())
+        self.assertEqual(info.get_class_struct(), repo.find_by_name('GIMarshallingTests', 'ObjectClass'))
+        self.assertEqual(info.get_type_name(), 'GIMarshallingTestsObject')
+        self.assertEqual(info.get_type_init(), 'gi_marshalling_tests_object_get_type')
+        self.assertFalse(info.get_fundamental())
+        self.assertEqual(info.get_parent(), repo.find_by_name('GObject', 'Object'))
+
+    def test_registered_type_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Object')
+        # Call these from the class because GIObjectInfo overrides them
+        self.assertEqual(GIRepository.RegisteredTypeInfo.get_g_type(info),
+                         GObject.type_from_name('GIMarshallingTestsObject'))
+        self.assertEqual(GIRepository.RegisteredTypeInfo.get_type_name(info),
+                         'GIMarshallingTestsObject')
+        self.assertEqual(GIRepository.RegisteredTypeInfo.get_type_init(info),
+                         'gi_marshalling_tests_object_get_type')
+
+    @unittest.skipUnless(has_cairo, 'Regress needs cairo')
+    def test_fundamental_object_info(self):
+        repo.require('Regress')
+        info = repo.find_by_name('Regress', 'TestFundamentalObject')
+        self.assertTrue(info.get_abstract())
+        self.assertTrue(info.get_fundamental())
+        self.assertEqual(info.get_ref_function(), 'regress_test_fundamental_object_ref')
+        self.assertEqual(info.get_unref_function(), 'regress_test_fundamental_object_unref')
+        self.assertEqual(info.get_get_value_function(), 'regress_test_value_get_fundamental_object')
+        self.assertEqual(info.get_set_value_function(), 'regress_test_value_set_fundamental_object')
+
+    def test_interface_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Interface')
+        self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_vfuncs(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_constants(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_prerequisites(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_properties(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_signals(), collections.Iterable))
+
+        method = info.find_method('test_int8_in')
+        vfunc = info.find_vfunc('test_int8_in')
+        self.assertEqual(method.get_name(), 'test_int8_in')
+        self.assertEqual(vfunc.get_invoker(), method)
+        self.assertEqual(method.get_vfunc(), vfunc)
+
+        iface = info.get_iface_struct()
+        self.assertEqual(iface, repo.find_by_name('GIMarshallingTests', 'InterfaceIface'))
+
+    def test_struct_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'InterfaceIface')
+        self.assertTrue(isinstance(info, GIRepository.StructInfo))
+        self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_size(), int))
+        self.assertTrue(isinstance(info.get_alignment(), int))
+        self.assertTrue(info.is_gtype_struct())
+        self.assertFalse(info.is_foreign())
+
+    def test_enum_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Enum')
+        self.assertTrue(isinstance(info, GIRepository.EnumInfo))
+        self.assertTrue(isinstance(info.get_values(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
+        self.assertFalse(info.is_flags())
+        self.assertTrue(info.get_storage_type() > 0)  # might be platform dependent
+
+    def test_union_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Union')
+        self.assertTrue(isinstance(info, GIRepository.UnionInfo))
+        self.assertTrue(isinstance(info.get_fields(), collections.Iterable))
+        self.assertTrue(isinstance(info.get_methods(), collections.Iterable))
+
+    def test_type_info(self):
+        func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
+        arg_info, = func_info.get_arguments()
+        type_info = arg_info.get_type()
+
+        self.assertTrue(type_info.is_pointer())
+        self.assertEqual(type_info.get_tag(), GIRepository.TypeTag.ARRAY)
+        self.assertEqual(type_info.get_tag_as_string(), 'array')
+        self.assertEqual(type_info.get_param_type(0).get_tag(),
+                         GIRepository.TypeTag.INTERFACE)
+        self.assertEqual(type_info.get_param_type(0).get_interface(),
+                         repo.find_by_name('GIMarshallingTests', 'SimpleStruct'))
+        self.assertEqual(type_info.get_interface(), None)
+        self.assertEqual(type_info.get_array_length(), -1)
+        self.assertEqual(type_info.get_array_fixed_size(), 2)
+        self.assertFalse(type_info.is_zero_terminated())
+        self.assertEqual(type_info.get_array_type(), GIRepository.ArrayType.C)
+
+    def test_field_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'InterfaceIface')
+        field = find_child_info(info, 'get_fields', 'test_int8_in')
+        self.assertEqual(field.get_name(), 'test_int8_in')
+        self.assertTrue(field.get_flags() & GIRepository.FieldInfoFlags.IS_READABLE)
+        self.assertFalse(field.get_flags() & GIRepository.FieldInfoFlags.IS_WRITABLE)
+        self.assertEqual(field.get_type().get_tag(), GIRepository.TypeTag.INTERFACE)
+
+        # don't test actual values because that might fail with architecture differences
+        self.assertTrue(isinstance(field.get_size(), int))
+        self.assertTrue(isinstance(field.get_offset(), int))
+
+    def test_property_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'PropertiesObject')
+        prop = find_child_info(info, 'get_properties', 'some-object')
+
+        flags = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE | GObject.ParamFlags.CONSTRUCT
+        self.assertEqual(prop.get_flags(), flags)
+        self.assertEqual(prop.get_type().get_tag(), GIRepository.TypeTag.INTERFACE)
+        self.assertEqual(prop.get_type().get_interface(),
+                         repo.find_by_name('GObject', 'Object'))
+        self.assertEqual(prop.get_ownership_transfer(), GIRepository.Transfer.NOTHING)
+
+    def test_callable_info(self):
+        func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
+        self.assertTrue(hasattr(func_info, 'invoke'))
+        self.assertTrue(isinstance(func_info.get_arguments(), collections.Iterable))
+        self.assertEqual(func_info.get_caller_owns(), GIRepository.Transfer.NOTHING)
+        self.assertFalse(func_info.may_return_null())
+        self.assertEqual(func_info.get_return_type().get_tag(), GIRepository.TypeTag.VOID)
+        self.assertRaises(AttributeError, func_info.get_return_attribute, '_not_an_attr')
+
+    @unittest.expectedFailure  # https://bugzilla.gnome.org/show_bug.cgi?id=709462
+    @unittest.skipUnless(has_cairo, 'Regress needs cairo')
+    def test_signal_info(self):
+        repo.require('Regress')
+        info = repo.find_by_name('Regress', 'TestObj')
+        sig_info = find_child_info(info, 'get_signals', 'test')
+
+        sig_flags = GObject.SignalFlags.RUN_LAST | \
+            GObject.SignalFlags.NO_RECURSE | GObject.SignalFlags.NO_HOOKS
+
+        self.assertTrue(sig_info is not None)
+        self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo))
+        self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo))
+        self.assertEqual(sig_info.get_name(), 'test')
+        self.assertEqual(sig_info.get_class_closure(), None)
+        self.assertFalse(sig_info.true_stops_emit())
+        self.assertEqual(sig_info.get_flags(), sig_flags)
+
+    @unittest.expectedFailure  # https://bugzilla.gnome.org/show_bug.cgi?id=709462
+    @unittest.skipUnless(has_cairo, 'Regress needs cairo')
+    def test_notify_signal_info_with_obj(self):
+        repo.require('Regress')
+        info = repo.find_by_name('Regress', 'TestObj')
+        sig_info = find_child_info(info, 'get_signals', 'sig-with-array-prop')
+
+        sig_flags = GObject.SignalFlags.RUN_LAST
+
+        self.assertTrue(sig_info is not None)
+        self.assertTrue(isinstance(sig_info, GIRepository.CallableInfo))
+        self.assertTrue(isinstance(sig_info, GIRepository.SignalInfo))
+        self.assertEqual(sig_info.get_name(), 'sig-with-array-prop')
+        self.assertEqual(sig_info.get_class_closure(), None)
+        self.assertFalse(sig_info.true_stops_emit())
+        self.assertEqual(sig_info.get_flags(), sig_flags)
+
+    def test_object_constructor(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Object')
+        method = find_child_info(info, 'get_methods', 'new')
+
+        self.assertTrue(isinstance(method, GIRepository.CallableInfo))
+        self.assertTrue(isinstance(method, GIRepository.FunctionInfo))
+        self.assertTrue(method in info.get_methods())
+        self.assertEqual(method.get_name(), 'new')
+        self.assertFalse(method.is_method())
+        self.assertTrue(method.is_constructor())
+        self.assertEqual(method.get_symbol(), 'gi_marshalling_tests_object_new')
+
+        flags = method.get_flags()
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_METHOD)
+        self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.THROWS)
+
+    def test_method_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Object')
+        method = find_child_info(info, 'get_methods', 'vfunc_return_value_only')
+
+        self.assertTrue(isinstance(method, GIRepository.CallableInfo))
+        self.assertTrue(isinstance(method, GIRepository.FunctionInfo))
+        self.assertTrue(method in info.get_methods())
+        self.assertEqual(method.get_name(), 'vfunc_return_value_only')
+        self.assertFalse(method.is_constructor())
+        self.assertEqual(method.get_symbol(), 'gi_marshalling_tests_object_vfunc_return_value_only')
+        self.assertTrue(method.is_method())
+
+        flags = method.get_flags()
+        self.assertTrue(flags & GIRepository.FunctionInfoFlags.IS_METHOD)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_CONSTRUCTOR)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_GETTER)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.IS_SETTER)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.WRAPS_VFUNC)
+        self.assertFalse(flags & GIRepository.FunctionInfoFlags.THROWS)
+
+    def test_vfunc_info(self):
+        info = repo.find_by_name('GIMarshallingTests', 'Object')
+        invoker = find_child_info(info, 'get_methods', 'vfunc_return_value_only')
+        vfunc = find_child_info(info, 'get_vfuncs', 'vfunc_return_value_only')
+
+        self.assertTrue(isinstance(vfunc, GIRepository.CallableInfo))
+        self.assertTrue(isinstance(vfunc, GIRepository.VFuncInfo))
+        self.assertEqual(vfunc.get_name(), 'vfunc_return_value_only')
+        self.assertEqual(vfunc.get_invoker(), invoker)
+        self.assertEqual(invoker, info.find_method('vfunc_return_value_only'))
+        self.assertEqual(vfunc.get_flags(), 0)
+        self.assertEqual(vfunc.get_offset(), 0xFFFF)  # unknown offset
+        self.assertEqual(vfunc.get_signal(), None)
+
+    def test_flags_double_registration_error(self):
+        # a warning is printed for double registration and pygobject will
+        # also raise a RuntimeError.
+        GIMarshallingTests.NoTypeFlags  # cause flags registration
+        info = repo.find_by_name('GIMarshallingTests', 'NoTypeFlags')
+        old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
+        try:
+            self.assertRaises(RuntimeError,
+                              GIRepository.flags_register_new_gtype_and_add,
+                              info)
+        finally:
+            GLib.log_set_always_fatal(old_mask)
+
+    def test_enum_double_registration_error(self):
+        # a warning is printed for double registration and pygobject will
+        # also raise a RuntimeError.
+        GIMarshallingTests.Enum  # cause enum registration
+        info = repo.find_by_name('GIMarshallingTests', 'Enum')
+        old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
+        try:
+            self.assertRaises(RuntimeError,
+                              GIRepository.enum_register_new_gtype_and_add,
+                              info)
+        finally:
+            GLib.log_set_always_fatal(old_mask)
+
+    def test_enums(self):
+        self.assertTrue(hasattr(GIRepository, 'Direction'))
+        self.assertTrue(hasattr(GIRepository, 'Transfer'))
+        self.assertTrue(hasattr(GIRepository, 'ArrayType'))
+        self.assertTrue(hasattr(GIRepository, 'ScopeType'))
+        self.assertTrue(hasattr(GIRepository, 'VFuncInfoFlags'))
+        self.assertTrue(hasattr(GIRepository, 'FieldInfoFlags'))
+        self.assertTrue(hasattr(GIRepository, 'FunctionInfoFlags'))
+        self.assertTrue(hasattr(GIRepository, 'TypeTag'))
+        self.assertTrue(hasattr(GIRepository, 'InfoType'))
+
+
+if __name__ == '__main__':
+    unittest.main()
index ec13896..e90264a 100644 (file)
@@ -327,9 +327,6 @@ class TestMatching(unittest.TestCase):
         self.assertEqual(obj.status, 2)
 
     def test_signal_handler_find(self):
-        def dummy(*args):
-            "Hack to work around: "
-
         def foo(obj):
             obj.status += 1
 
@@ -340,7 +337,7 @@ class TestMatching(unittest.TestCase):
         found_id = GObject.signal_handler_find(obj,
                                                GObject.SignalMatchType.ID,
                                                signal_id=signal_id, detail=detail,
-                                               closure=None, func=dummy, data=dummy)
+                                               closure=None, func=0, data=0)
         self.assertEqual(handler_id, found_id)
 
 
index d0e28e4..6f69927 100644 (file)
@@ -128,13 +128,19 @@ class TestSource(unittest.TestCase):
     def test_remove(self):
         s = GLib.idle_add(dir)
         self.assertEqual(GLib.source_remove(s), True)
-        # s is now removed, should fail now
-        self.assertEqual(GLib.source_remove(s), False)
 
-        # accepts large source IDs (they are unsigned)
-        self.assertEqual(GLib.source_remove(GObject.G_MAXINT32), False)
-        self.assertEqual(GLib.source_remove(GObject.G_MAXINT32 + 1), False)
-        self.assertEqual(GLib.source_remove(GObject.G_MAXUINT32), False)
+        # Removing sources not found cause critical
+        old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR)
+        try:
+            # s is now removed, should fail now
+            self.assertEqual(GLib.source_remove(s), False)
+
+            # accepts large source IDs (they are unsigned)
+            self.assertEqual(GLib.source_remove(GObject.G_MAXINT32), False)
+            self.assertEqual(GLib.source_remove(GObject.G_MAXINT32 + 1), False)
+            self.assertEqual(GLib.source_remove(GObject.G_MAXUINT32), False)
+        finally:
+            GLib.log_set_always_fatal(old_mask)
 
     def test_recurse_property(self):
         s = GLib.Idle()
index ef4c35e..6da8ad2 100644 (file)
@@ -12,68 +12,58 @@ from gi import PyGIDeprecationWarning
 class TestProcess(unittest.TestCase):
 
     def test_deprecated_child_watch_no_data(self):
-        def cb(pid, status):
-            self.status = status
-            self.loop.quit()
-
-        self.status = None
-        self.loop = GLib.MainLoop()
-        argv = [sys.executable, '-c', 'import sys']
-        pid, stdin, stdout, stderr = GLib.spawn_async(
-            argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
-        pid.close()
+        cb = lambda pid, status: None
+        pid = object()
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter('always')
-            GLib.child_watch_add(pid, cb)
+            res = GLib._child_watch_add_get_args(pid, cb)
             self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
-        self.loop.run()
-        self.assertEqual(self.status, 0)
 
-    def test_deprecated_child_watch_data_priority(self):
-        def cb(pid, status, data):
-            self.data = data
-            self.status = status
-            self.loop.quit()
+        self.assertEqual(len(res), 4)
+        self.assertEqual(res[0], GLib.PRIORITY_DEFAULT)
+        self.assertEqual(res[1], pid)
+        self.assertTrue(callable(cb))
+        self.assertSequenceEqual(res[3], [])
 
-        self.status = None
-        self.data = None
-        self.loop = GLib.MainLoop()
-        argv = [sys.executable, '-c', 'import sys']
-        pid, stdin, stdout, stderr = GLib.spawn_async(
-            argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
-        pid.close()
+    def test_deprecated_child_watch_data_priority(self):
+        cb = lambda pid, status: None
+        pid = object()
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter('always')
-            id = GLib.child_watch_add(pid, cb, 12345, GLib.PRIORITY_HIGH)
+            res = GLib._child_watch_add_get_args(pid, cb, 12345, GLib.PRIORITY_HIGH)
             self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
-        self.assertEqual(self.loop.get_context().find_source_by_id(id).priority,
-                         GLib.PRIORITY_HIGH)
-        self.loop.run()
-        self.assertEqual(self.data, 12345)
-        self.assertEqual(self.status, 0)
 
-    def test_deprecated_child_watch_data_priority_kwargs(self):
-        def cb(pid, status, data):
-            self.data = data
-            self.status = status
-            self.loop.quit()
+        self.assertEqual(len(res), 4)
+        self.assertEqual(res[0], GLib.PRIORITY_HIGH)
+        self.assertEqual(res[1], pid)
+        self.assertEqual(res[2], cb)
+        self.assertSequenceEqual(res[3], [12345])
 
-        self.status = None
-        self.data = None
-        self.loop = GLib.MainLoop()
-        argv = [sys.executable, '-c', 'import sys']
-        pid, stdin, stdout, stderr = GLib.spawn_async(
-            argv, flags=GLib.SpawnFlags.DO_NOT_REAP_CHILD)
-        pid.close()
+    def test_deprecated_child_watch_data_priority_kwargs(self):
+        cb = lambda pid, status: None
+        pid = object()
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter('always')
-            id = GLib.child_watch_add(pid, cb, priority=GLib.PRIORITY_HIGH, data=12345)
+            res = GLib._child_watch_add_get_args(pid, cb, priority=GLib.PRIORITY_HIGH, data=12345)
             self.assertTrue(issubclass(w[0].category, PyGIDeprecationWarning))
-        self.assertEqual(self.loop.get_context().find_source_by_id(id).priority,
-                         GLib.PRIORITY_HIGH)
-        self.loop.run()
-        self.assertEqual(self.data, 12345)
-        self.assertEqual(self.status, 0)
+
+        self.assertEqual(len(res), 4)
+        self.assertEqual(res[0], GLib.PRIORITY_HIGH)
+        self.assertEqual(res[1], pid)
+        self.assertEqual(res[2], cb)
+        self.assertSequenceEqual(res[3], [12345])
+
+    @unittest.expectedFailure  # using keyword args is fully supported by PyGObject machinery
+    def test_child_watch_all_kwargs(self):
+        cb = lambda pid, status: None
+        pid = object()
+
+        res = GLib._child_watch_add_get_args(priority=GLib.PRIORITY_HIGH, pid=pid, function=cb, data=12345)
+        self.assertEqual(len(res), 4)
+        self.assertEqual(res[0], GLib.PRIORITY_HIGH)
+        self.assertEqual(res[1], pid)
+        self.assertEqual(res[2], cb)
+        self.assertSequenceEqual(res[3], [12345])
 
     def test_child_watch_no_data(self):
         def cb(pid, status):