-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 | 4 ++++
- 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
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
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
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
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
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
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@
-# 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.
$(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
$(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)
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.
-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)
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
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
============
* 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
-# generated automatically by aclocal 1.14 -*- Autoconf -*-
+# generated automatically by aclocal 1.13.3 -*- Autoconf -*-
# Copyright (C) 1996-2013 Free Software Foundation, Inc.
# 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
])
# 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]))])
# 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])
# -----------------------------------------------
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
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.
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.
# 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])
# ---------------------------------------------------------------------------
*/
#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
#! /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>.
#
# 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/'
# 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]...
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
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.
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 $@
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"
fi
AM_BACKSLASH='\'
-am__api_version='1.14'
+am__api_version='1.13'
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
# Define the identity of the package.
PACKAGE='pygobject'
- VERSION='3.10.2'
+ VERSION='3.11.1'
cat >>confdefs.h <<_ACEOF
-# 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"
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
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
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
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; }
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
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
_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
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
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
_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
# 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
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\\"
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],
-# 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.
-# 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.
@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 $@ $<
-# 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.
@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 $@ $<
#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
-# 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.
@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 $@ $<
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);
g_free(name);
}
- g_type_class_unref(class);
-
if (props)
g_free(props);
return props_list;
}
+
static PyObject*
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
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)
{
return NULL;
}
- return pygbinding_weak_ref_new(G_OBJECT (binding));
+ return pygobject_new (G_OBJECT (binding));
}
static PyObject *
}
}
-
-/* -------------- 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)
{
"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;
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);
}
from ._gi import \
VFuncInfo, \
FunctionInfo, \
- DIRECTION_IN, \
- DIRECTION_OUT, \
- DIRECTION_INOUT
+ Direction
#: Module storage for currently registered doc string generator function.
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)
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)
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)
#include <pyglib-python-compat.h>
PyObject *PyGIDeprecationWarning;
+PyObject *_PyGIDefaultArgPlaceholder;
static PyObject *
_wrap_pyg_enum_add (PyObject *self,
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);
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)
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'):
__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)
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')
__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',
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')
__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
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):
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).
# 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
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
__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
-# 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.
{
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;
}
&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;
PyGIDirection direction,
gssize c_arg_index,
gssize py_arg_index);
+
/* cleanup */
static void
_pygi_arg_cache_free (PyGIArgCache *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);
}
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;
}
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;
}
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;
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;
{
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;
}
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;
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,
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;
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;
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;
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,
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,
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;
}
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);
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;
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);
}
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;
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 */
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 =
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);
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++;
}
- 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;
}
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);
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;
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg);
+ GIArgument *arg,
+ gpointer *cleanup_data);
typedef PyObject *(*PyGIMarshalToPyFunc) (PyGIInvokeState *state,
PyGICallableCache *callable_cache,
typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
+ PyObject *py_arg, /* always NULL for to_py cleanup */
gpointer data,
gboolean was_processed);
* - 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
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;
* 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;
gboolean is_caller_allocates;
gboolean is_skipped;
gboolean allow_none;
+ gboolean has_default;
PyGIDirection direction;
GITransfer transfer;
gssize c_arg_index;
gssize py_arg_index;
+
+ /* Set when has_default is true. */
+ GIArgument default_value;
};
typedef struct _PyGISequenceCache
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);
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__ */
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) {
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,
* 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.
*
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)
{
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;
}
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)) {
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);
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 }
};
/* 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)
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;
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 }
};
};
/* 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 }
};
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) );
}
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
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));
{ "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 }
};
/* 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:
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 }
};
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;
}
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 }
};
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 }
};
}
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 *
}
}
+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 }
};
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 *
}
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 }
};
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 }
};
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 }
};
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 }
};
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[] = {
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) {
return fullname;
}
+
void
_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;
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,
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,
_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
+
}
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
}
}
- 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,
/* 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,
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)) {
* 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'",
}
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;
}
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);
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) {
}
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",
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,
if (to_py_cleanup != NULL)
to_py_cleanup ( state,
cache->return_cache,
+ NULL,
&state->return_arg,
FALSE);
}
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:
static inline void
_cleanup_caller_allocates (PyGIInvokeState *state,
PyGIArgCache *cache,
+ PyObject *py_obj,
gpointer data,
gboolean was_processed)
{
{
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;
}
}
}
if (cleanup_func && state->return_arg.v_pointer != NULL)
cleanup_func (state,
cache->return_cache,
+ NULL,
state->return_arg.v_pointer,
TRUE);
}
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);
}
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);
}
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)
{
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)
{
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);
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_array (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
+ PyObject *py_arg,
gpointer data,
gboolean was_processed)
{
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;
for (i = 0; i < len; i++) {
gpointer item;
+ PyObject *py_item = NULL;
/* case 1: GPtrArray */
if (ptr_array_ != NULL)
}
}
- 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_);
}
}
}
void
_pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
+ PyObject *dummy,
gpointer data,
gboolean was_processed)
{
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);
}
void
_pygi_marshal_cleanup_from_py_glist (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
+ PyObject *py_arg,
gpointer data,
gboolean was_processed)
{
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();
}
}
}
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;
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();
}
}
}
void
_pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state,
PyGIArgCache *arg_cache,
+ PyObject *py_arg,
gpointer data,
gboolean was_processed)
{
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)
{
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);
}
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
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);
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;
}
static gboolean
_pygi_marshal_from_py_utf8 (PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
gchar *string_;
}
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;
return FALSE;
}
+ *cleanup_data = arg->v_string;
return TRUE;
}
_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:
"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:
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;
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
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;
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);
}
}
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;
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
*/
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);
{
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) {
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);
+ }
}
}
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;
}
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;
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyGIMarshalFromPyFunc from_py_marshaller;
int i;
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;
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:
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;
}
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyGIMarshalFromPyFunc from_py_marshaller;
int i;
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;
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:
}
*/
+ 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;
}
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;
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)
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_,
}
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;
}
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");
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
GICallableInfo *callable_info;
PyGICClosure *closure;
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;
}
}
* 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) {
}
}
- /* 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;
}
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyObject *py_long;
long c_long;
PyGICallableCache *callable_cache,
PyGIArgCache *arg_cache,
PyObject *py_arg,
- GIArgument *arg)
+ GIArgument *arg,
+ gpointer *cleanup_data)
{
PyObject *py_long;
long c_long;
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
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");
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;
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
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):
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;
} 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) {
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,
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*/
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
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 *
}
} 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;
}
}
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);
for (j = processed_items; j < array_->len; j++) {
cleanup_func (state,
seq_cache->item_cache,
+ NULL,
g_array_index (array_, gpointer, j),
FALSE);
}
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);
#include "pygi-cache.h"
extern PyObject *PyGIDeprecationWarning;
+extern PyObject *_PyGIDefaultArgPlaceholder;
typedef struct {
PyObject_HEAD
-# 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.
-# 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.
test_atoms.py \
test_generictreemodel.py \
test_docstring.py \
+ test_repository.py \
compat_test_pygtk.py \
gi/__init__.py \
gi/overrides/__init__.py \
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
-# 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.
test_atoms.py \
test_generictreemodel.py \
test_docstring.py \
+ test_repository.py \
compat_test_pygtk.py \
gi/__init__.py \
gi/overrides/__init__.py \
@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 $@ $<
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.
import gi.docstring
from gi.repository import GIMarshallingTests
+from gi.repository import Gio
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)
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()
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
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
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])
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)
# 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])
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,
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):
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_)
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.
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):
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):
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()
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 = []
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)
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)
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)
# Unbind should clear out the binding and its transforms
binding.unbind()
- self.assertEqual(binding(), None)
- del binding
- gc.collect()
# Setting source or target should not change the other.
self.target.int_prop = 3
self.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)
# 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)
# 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):
--- /dev/null
+# -*- 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()
self.assertEqual(obj.status, 2)
def test_signal_handler_find(self):
- def dummy(*args):
- "Hack to work around: "
-
def foo(obj):
obj.status += 1
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)
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()
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):