diff options
32 files changed, 1538 insertions, 989 deletions
@@ -1,3 +1,648 @@ +commit bd6da84a4aec74e47f5d70e8ed18695c37e746c6 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 17:30:48 2013 +0100 + + release 3.7.4 + + NEWS | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +commit c90ef9dfac7dd51ec82c99c3605915996bea0f73 +Author: Simonas Kazlauskas <simonas@kazlauskas.me> +Date: Tue Dec 4 15:45:00 2012 +0200 + + Allow setting values through GtkTreeModelFilter + + Previously, trying to set a value through filter throwed an exception + that the + model has no set_value() method. You had to first retrieve the + deepest child + model and set value to it. + + https://bugzilla.gnome.org/show_bug.cgi?id=689624 + + gi/overrides/Gtk.py | 5 +++++ + tests/test_overrides_gtk.py | 11 +++++++++++ + 2 files changed, 16 insertions(+) + +commit b092630efc691a6f7ae94ae896193254f5a961a6 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 12:37:18 2013 +0100 + + tests: Add (failing) test case for GParamSpec arguments + + This reproduces + https://bugzilla.gnome.org/show_bug.cgi?id=682355 + + tests/test_gi.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +commit 52d84b5da7f9fd4f65faea4e6fe3d250f937a208 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 12:20:27 2013 +0100 + + tests: Skip struct string member tests with g-i 1.34 + + We still support building against gobject-introspection 1.34, so + skip tests + which do not work with that version yet. + + tests/test_gi.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +commit f9429192cb1002725a11a75a7b8f9300375b9caf +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 12:15:27 2013 +0100 + + Support GParamSpec signal arguments from Python + + In pyg_value_from_pyobject(), recognize both the real GI + GObject.ParamSpec type + as well as the statically wrapped _gobject.GParamSpec type. + + This fixes marshalling GObject.ParamSpec signal/vfunc arguments. + + https://bugzilla.gnome.org/show_bug.cgi?id=683099 + + gi/_gobject/pygtype.c | 6 +++++- + tests/test_signal.py | 12 ++++++++++++ + tests/testhelpermodule.c | 13 +++++++++++++ + 3 files changed, 30 insertions(+), 1 deletion(-) + +commit 99f72925c7de76611f7592bce9d8217a9ff46809 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 11:48:11 2013 +0100 + + pygobject_emit(): Fix cleanup on error + + Dot not try to unset GValues which have not been initialized yet, + when type + conversion fails for a parameter. + + gi/_gobject/pygobject.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit acef1d3266d11b2465d61185a55526df879a5c62 +Author: Simon Feltman <sfeltman@src.gnome.org> +Date: Mon Dec 31 19:01:57 2012 -0800 + + Add signal emission methods to TreeModel which coerce the path + argument + + Override TreeModel row_changed, row_inserted, row_has_child_toggled, + row_deleted, and rows_reordered methods to accept python iterables as + the path parameter. This is for compatibility with pygtk and + consistency + with the rest of the TreeModel and TreePath overrides. + + https://bugzilla.gnome.org/show_bug.cgi?id=682933 + + gi/overrides/Gtk.py | 31 ++++++++++++++++++++++++++++--- + tests/test_overrides_gtk.py | 27 +++++++++++++++++++++++++++ + 2 files changed, 55 insertions(+), 3 deletions(-) + +commit 9cfba517e1a6dced5e66786b28ed5e101b7b4a29 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 10:36:36 2013 +0100 + + Simplify overrides and tests using the new GObject.Value override + + The previous commit added support for constructing a GObject.Value + with a given + GType and Python object conversion. Use this to simplify the Gtk + override and + the tests that construct GValues. + + See https://bugzilla.gnome.org/show_bug.cgi?id=677473 + + gi/overrides/Gtk.py | 88 + +++------------------------------------------ + tests/test_gi.py | 26 +++++--------- + tests/test_overrides_gtk.py | 2 +- + tests/test_signal.py | 12 ++----- + 4 files changed, 17 insertions(+), 111 deletions(-) + +commit f62b98398177991bfdbe0b6753342e79e6cf170a +Author: Bastian Winkler <buz@netbuz.org> +Date: Mon Jan 14 10:26:08 2013 +0100 + + Add override for GValue + + Override GValue with a custom constructor and set_value()/get_value() + methods. This allows you to call + + >>> GObject.Value(GObject.TYPE_FLOAT, 42.23) + + instead of + + >>> value = GObject.Value() + >>> value.init(GObject.TYPE_FLOAT) + >>> value.set_float(42.23) + + This is especially useful for overrides that need to convert a Python + value to a expected type like G_TYPE_FLOAT. + + https://bugzilla.gnome.org/show_bug.cgi?id=677473 + + gi/overrides/GObject.py | 127 + +++++++++++++++++++++++++++++++++++++++++++++++- + tests/test_gobject.py | 47 +++++++++++++++++- + 2 files changed, 172 insertions(+), 2 deletions(-) + +commit dc3d21173b75232f7ea0b9913f7309486456a69d +Author: Mike Gorse <mgorse@suse.com> +Date: Thu Jan 10 15:48:30 2013 -0600 + + Mark caller-allocated boxed structures as having a slice allocated + + When a C function takes a pointer and fills it with a boxed structure + (ie, + gtk_tree_store_insert_with_values), pygi should deallocate the slice + when the + box is no longer being used. + + https://bugzilla.gnome.org/show_bug.cgi?id=699501 + + gi/pygi-marshal-to-py.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +commit 0c496d230fee7fd3ada90ee9af10e0bc1e29ee12 +Author: Olivier Crête <olivier.crete@collabora.com> +Date: Fri Sep 14 21:31:32 2012 -0400 + + pygi-property: Support boxed GSList/GList types + + Note that this does not yet work for construct properties. + + Co-Authored-By: Martin Pitt <martinpitt@gnome.org> + + https://bugzilla.gnome.org/show_bug.cgi?id=684059 + + gi/pygi-property.c | 10 ++++++++-- + tests/test_gi.py | 21 +++++++++++++++++++++ + 2 files changed, 29 insertions(+), 2 deletions(-) + +commit 074f10d815453e58f4bee2f440c5db799add3876 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 07:48:31 2013 +0100 + + test_gio: Fix for Python 2 + + Python 2 does not yet take an "encoding" argument for str(), while + Python 3 + requires it. Use a less fancy static test string instead. + + tests/test_gio.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +commit 734979d0c8317201148a7e94a323225fba2d1635 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 07:40:10 2013 +0100 + + tests: Add missing backwards compat methods for Python 2.6 + + Define skipIf(), assertLess(), and assertLessEqual() for running + the tests with + Python 2.6. + + https://bugzilla.gnome.org/show_bug.cgi?id=691646 + + tests/runtests.py | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +commit dc0dafd1f6ca3ebbf04210768a45587387e44551 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Jan 14 07:34:46 2013 +0100 + + tests: Stop using assertSequenceEqual() + + assertSequenceEqual() does not yet exist in Python 2.6, and is + not necessary + either as assertEqual() on sequences automatically does list + comparison. + + Part of https://bugzilla.gnome.org/show_bug.cgi?id=691646 + + tests/test_gtype.py | 6 ++---- + tests/test_signal.py | 6 ++---- + 2 files changed, 4 insertions(+), 8 deletions(-) + +commit 0a5587b6a56d417a6703e342f153596f08cd5889 +Author: Simon Feltman <sfeltman@src.gnome.org> +Date: Sun Jan 13 18:19:51 2013 -0800 + + Allow setting TreeModel values to None + + Change TreeModel.set_value to use an empty but initialized GValue when + None is used as the value argument. This allows clearing of cell data + which was not accessible due to auto-coercion. + + https://bugzilla.gnome.org/show_bug.cgi?id=684094 + + gi/overrides/Gtk.py | 11 ++++++++--- + tests/test_overrides_gtk.py | 8 ++++++++ + 2 files changed, 16 insertions(+), 3 deletions(-) + +commit 5ae129da436793478750f0dc9427a174a980e10b +Author: Mike Gorse <mgorse@suse.com> +Date: Thu Jan 10 16:42:17 2013 -0600 + + Set clean-up handler for marshalled arrays + + Arrays did not have a cleanup handler set in some cases, resulting + in a leak. + + https://bugzilla.gnome.org/show_bug.cgi?id=691509 + + gi/pygi-cache.c | 1 + + 1 file changed, 1 insertion(+) + +commit 58bd307c57d542a8f69867dea2d0a0eb51230c7b +Author: Vadim Rutkovsky <vrutkovs@redhat.com> +Date: Fri Jan 11 15:41:27 2013 +0100 + + Support setting string fields in structs + + Co-Authored-By: Martin Pitt <martinpitt@gnome.org> + + https://bugzilla.gnome.org/show_bug.cgi?id=678401 + + gi/pygi-info.c | 3 ++- + tests/test_gi.py | 16 ++++++++++++++++ + 2 files changed, 18 insertions(+), 1 deletion(-) + +commit f2bcaa43c1158040a8c2cbc3a2ba5070d126a410 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Fri Jan 11 14:58:44 2013 +0100 + + Re-enable test_gi.TestPropertiesObject.test_char test + + The gobject-introspection bug got fixed: + https://bugzilla.gnome.org/show_bug.cgi?id=691524 + + tests/test_gi.py | 14 +++----------- + 1 file changed, 3 insertions(+), 11 deletions(-) + +commit 9a8c49087cf400e01c1f78241fa4d74b4d15f54e +Author: Martin Pitt <martinpitt@gnome.org> +Date: Fri Jan 11 09:46:56 2013 +0100 + + tests: Re-enable test_callback_scope_call_array() check + + Drop the expected failure from test_callback_scope_call_array() + and just add + the explicit array length arguments. While it would look cleaner to + not pass + them, it is probably not worth breaking the API for this. + + tests/test_everything.py | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +commit 609636424b5f9b659e99a4bb53a48c165187c430 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Fri Jan 11 09:13:36 2013 +0100 + + Permit plain integers for "gchar" values + + Similar to guchar/guint8, allow plain integers (withing correct + boundaries) as + values for gchar/gint8 types. + + This is covered by the test_gi.TestPropertiesObject.test_char + test when + removing the "expected failure" flag. + + gi/_gobject/pygtype.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +commit a558d3d3a9274aeccfc54705bf5effdf71dee06b +Author: Martin Pitt <martinpitt@gnome.org> +Date: Fri Jan 11 09:09:41 2013 +0100 + + Allow single byte values for int8 types + + When fixing gobject-introspection to consider "gchar" as signed (see + https://bugzilla.gnome.org/show_bug.cgi?id=691524), we must also + permit a + single-element "bytes" array as a valid value for int8, not just + for uint8. + + This is caught by the test_overrides_gtk.TestTreeModel.test_tree_store + test. + + gi/pygi-argument.c | 4 ++-- + gi/pygi-marshal-from-py.c | 34 +++++++++++++++++++++------------- + 2 files changed, 23 insertions(+), 15 deletions(-) + +commit aa7f6cd12fe403acb2cffc7890724af7abb9b990 +Author: Mike Gorse <mgorse@suse.com> +Date: Thu Jan 10 14:11:56 2013 -0600 + + Fix invalid memory access handling errors when registering an + enum type + + Don't free the name until we are done with it. + + gi/gimodule.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +commit ecd235959317d39b6d598662c00829e0ec717b17 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Thu Jan 10 16:42:46 2013 +0100 + + Fix (out) arguments in callbacks + + Do not ignore the first argument in _pygi_closure_set_out_arguments(). + Presumably that has been done to skip over "self", but callbacks + are not + required to have a self argument. As self is never (out), we can + safely include + it in the loop. + + gi/pygi-closure.c | 2 +- + tests/test_gi.py | 4 ---- + 2 files changed, 1 insertion(+), 5 deletions(-) + +commit d8e241e24a816691acbd592775b73defd9aa4f44 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Thu Jan 10 15:14:05 2013 +0100 + + Fix C to Python marshalling of struct pointer arrays + + Do not treat an array of pointers to values like an array of values on + marshalling from C. This makes the test_array_boxed_struct_return() + test case + work. + + gi/pygi-marshal-to-py.c | 5 +++-- + tests/test_gi.py | 2 -- + 2 files changed, 3 insertions(+), 4 deletions(-) + +commit 60544b02f6f98c0b212625ae83b94a4c6debddeb +Author: Simonas Kazlauskas <simonas@kazlauskas.me> +Date: Tue Jan 8 23:22:54 2013 +0200 + + Add tests for GFile + + Most notably this commit contains a test for + Gio.File.replace_contents_async(), + which currently fails. Disable the tests for now as it breaks the + other tests. + + https://bugzilla.gnome.org/show_bug.cgi?id=690525 + + tests/test_gio.py | 64 + +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +commit 118c5eaad045580455515876ba73b9537a8468b4 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Thu Jan 10 13:56:11 2013 +0100 + + Rename test_overrides_gio.py to test_gio.py + + As we want to add more tests for non-overridden API. + + tests/Makefile.am | 2 +- + tests/test_gio.py | 121 + ++++++++++++++++++++++++++++++++++++++++++++ + tests/test_overrides_gio.py | 121 + -------------------------------------------- + 3 files changed, 122 insertions(+), 122 deletions(-) + +commit 8117e6bce73581e89211371708ff7d5de7d870d4 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Thu Jan 10 12:13:16 2013 +0100 + + Don't let Property.setter() method names define property names + + Defining property names in install_properties() is too late when using + @propname.setter decorators; their method names don't define a + property name, + nor are they even required to be a valid property identifier. + + So change the logic to already fix the property name when using + a setter + decorator and use that instead of the member name in + install_properties(). + + https://bugzilla.gnome.org/show_bug.cgi?id=688971 + + gi/_gobject/propertyhelper.py | 29 ++++++++++++++++++++++------- + tests/test_properties.py | 18 ++++++++++++++++++ + 2 files changed, 40 insertions(+), 7 deletions(-) + +commit c0bd060521cc1b481995648dbe286b7e2f9ecd80 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Wed Jan 9 10:39:36 2013 +0100 + + tests: Force UTF-8 file name encoding + + The test_gi.TestFilename tests fail if the environment specifies + a non-UTF8 + file name encoding. Force it to "UTF-8" for the tests. + + https://bugzilla.gnome.org/show_bug.cgi?id=691355 + + tests/runtests.py | 1 + + 1 file changed, 1 insertion(+) + +commit c02a00ae9599a661076630b21b7e24e78fb88c29 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Tue Jan 8 16:56:40 2013 +0100 + + Use g-i stack allocation API + + Where possible, i. e. when not keeping references across functions, + use the + _load_() methods instead of the _get_() ones from + gobject-introspection, which + is faster and less prone to memory leaks: + + g_callable_info_get_arg () → g_callable_info_load_arg () + g_callable_info_get_return_type() → + g_callable_info_load_return_type () + g_arg_info_get_type() → g_arg_info_load_type () + + https://bugzilla.gnome.org/show_bug.cgi?id=615982 + + gi/pygi-argument.c | 16 ++++------ + gi/pygi-closure.c | 88 + ++++++++++++++++++++++++------------------------------ + 2 files changed, 45 insertions(+), 59 deletions(-) + +commit 23d1f14f553069740465c82eaa937b877c41e0cb +Author: Ray Strode <rstrode@redhat.com> +Date: Wed Dec 19 13:04:32 2012 -0500 + + pyg_value_from_pyobject: support GArray + + This commit adds support for marshalling a python list (or other + sequence) + returned from signal handlers to GArray, if necessary. + + This parallels the implementation written to marshal to (the now + deprecated) + GValueArray. + + This fixes a crash in rhythmbox as seen downstream here: + https://bugzilla.redhat.com/show_bug.cgi?id=872851 + + https://bugzilla.gnome.org/show_bug.cgi?id=690514 + + Co-Authored-By: Martin Pitt <martinpitt@gnome.org> + + gi/_gobject/pygtype.c | 60 + ++++++++++++++++++++++++++++++++++++++++++++++++ + tests/test_everything.py | 22 ++++++++++++++++++ + 2 files changed, 82 insertions(+) + +commit 2089dbb117bae769b0303411c2630b6f86dc7d2d +Author: Marko Lindqvist <cazfi74@gmail.com> +Date: Fri Jan 4 07:01:29 2013 +0100 + + Fix obsolete automake macros + + https://bugzilla.gnome.org/show_bug.cgi?id=691101 + + configure.ac | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +commit 6c02ab0ad720780f176192fdc6372aaa178812fd +Author: Simon Feltman <sfeltman@src.gnome.org> +Date: Mon Dec 31 02:53:07 2012 -0800 + + Change dynamic enum and flag gtype creation to use namespaced naming + + Use the combination of g_base_info_get_namespace and + g_base_info_get_name + as the name for registering enum and flag types with glib through + g_enum_register_static and g_flags_register_static. This avoids + conflicts + with types like GLib.SeekType and Gst.SeekType. Add better exceptions + and memory cleanup for invalid registration problems. + + https://bugzilla.gnome.org/show_bug.cgi?id=690455 + + gi/_gobject/pygenum.c | 6 ++-- + gi/gimodule.c | 78 + ++++++++++++++++++++++++++++++++++++++++++++------- + tests/test_gi.py | 35 +++++++++++++++++++++++ + 3 files changed, 106 insertions(+), 13 deletions(-) + +commit 692c80e11a05e2fb0515580acb22fd6fe65cede1 +Author: Dan Horák <dan@danny.cz> +Date: Fri Dec 28 22:12:32 2012 +0100 + + Fix test for GBytes.compare() + + The result of the compare method is defined as equal, less than or + greater than zero + and the test must match to that. The underlaying memcmp() function + can return other + values than -1, 0 and 1. For example on architectures where it is + implemented directly + via a CPU instruction like on s390(x) where I can see -2 as a result + instead of the + "expected" -1. + + https://bugzilla.gnome.org/show_bug.cgi?id=690837 + + tests/test_gi.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +commit 948dbcb223249a08f4398d4ad8861e92e3de0dfa +Author: Jonathan Ballet <jon@multani.info> +Date: Thu Dec 27 16:04:51 2012 +0100 + + Fix Gtk.UIManager.add_ui_from_string() override for non-ASCII chars + + The length argument is the size of the buffer in bytes, not in + characters. + + https://bugzilla.gnome.org/show_bug.cgi?id=690329 + + Co-Authored-By: Martin Pitt <martinpitt@gnome.org> + + gi/overrides/Gtk.py | 2 +- + tests/test_overrides_gtk.py | 7 +++++++ + 2 files changed, 8 insertions(+), 1 deletion(-) + +commit 53bc12a87da824cbfb006a4fd65731edec12ecc7 +Author: Mike Gorse <mgorse@suse.com> +Date: Wed Dec 19 20:51:03 2012 -0500 + + Don't dup strings before passing them to type registration functions + + Strings passed to g_enum_register_static and g_flags_register_static + are + eventually passed to g_quark_from_string, which dups the string + passed to it if + needed and does not take ownership of it, so passing in a + dynamically-allocated + string without freeing it results in a small leak. + + https://bugzilla.gnome.org/show_bug.cgi?id=690532 + + gi/gimodule.c | 2 -- + 1 file changed, 2 deletions(-) + +commit 9454c01f2b1b82d43eea0f72fe9a28ef50065fc9 +Author: Carlos Garnacho <carlos@lanedo.com> +Date: Tue Dec 18 22:47:09 2012 +0100 + + Fix marshalling of arrays of boxed struct values + + This fixes methods like gtk_selection_set_with_data(). In such cases + data is passed as an array of struct pointers, so it must be converted + to an array of structs. + + https://bugzilla.gnome.org/show_bug.cgi?id=656312 + + Co-Authored-By: Martin Pitt <martinpitt@gnome.org> + + gi/pygi-marshal-from-py.c | 6 ++++++ + tests/test_gi.py | 12 ++++++++++++ + 2 files changed, 18 insertions(+) + +commit 231d5a7cfc73518b4e2b0c926d4c1ce9a804797e +Author: Simon Feltman <sfeltman@src.gnome.org> +Date: Tue Dec 18 02:03:41 2012 -0800 + + Add reference counting tests for Object.bind_property + + Add tests which ensure transform callbacks and user_data + are propertly ref-counted. + + https://bugzilla.gnome.org/show_bug.cgi?id=690397 + + tests/test_gobject.py | 40 ++++++++++++++++++++++++++++++++++++---- + 1 file changed, 36 insertions(+), 4 deletions(-) + +commit c29e11812d176b1f057074c9bab22c9614ae4f8c +Author: Martin Pitt <martinpitt@gnome.org> +Date: Tue Dec 18 11:43:04 2012 +0100 + + testhelpermodule.c: Do not unref called method + + In _wrap_test_gerror_exception(), do not unref the method + arguments. This + causes a crash when being run with the stricter refcounting/memory + checks with + debug-enabled Python builds. + + tests/testhelpermodule.c | 1 - + 1 file changed, 1 deletion(-) + +commit ff0d9106bcd02a6b2c67cc3722481218c599a9f4 +Author: Martin Pitt <martinpitt@gnome.org> +Date: Mon Dec 17 23:20:50 2012 +0100 + + configure.ac: post-release bump to 3.7.4 + + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + commit 061b23d14386c0e54d2c3af113554231bbe85f16 Author: Martin Pitt <martinpitt@gnome.org> Date: Mon Dec 17 23:18:31 2012 +0100 @@ -1,3 +1,41 @@ +3.7.4 14-Jan-2013 + - Allow setting values through GtkTreeModelFilter (Simonas Kazlauskas) + (#689624) + - Support GParamSpec signal arguments from Python (Martin Pitt) + (#683099) + - pygobject_emit(): Fix cleanup on error (Martin Pitt) + - Add signal emission methods to TreeModel which coerce the path + argument (Simon Feltman) (#682933) + - Add override for GValue (Bastian Winkler) (#677473) + - Mark caller-allocated boxed structures as having a slice allocated + (Mike Gorse) (#699501) + - pygi-property: Support boxed GSList/GList types (Olivier Crête) + (#684059) + - tests: Add missing backwards compat methods for Python 2.6 + (Martin Pitt) (#691646) + - Allow setting TreeModel values to None (Simon Feltman) (#684094) + - Set clean-up handler for marshalled arrays (Mike Gorse) (#691509) + - Support setting string fields in structs (Vadim Rutkovsky) (#678401) + - Permit plain integers for "gchar" values (Martin Pitt) + - Allow single byte values for int8 types (Martin Pitt) (#691524) + - Fix invalid memory access handling errors when registering an enum + type (Mike Gorse) + - Fix (out) arguments in callbacks (Martin Pitt) + - Fix C to Python marshalling of struct pointer arrays (Martin Pitt) + - Don't let Property.setter() method names define property names + (Martin Pitt) (#688971) + - Use g-i stack allocation API (Martin Pitt) (#615982) + - pyg_value_from_pyobject: support GArray (Ray Strode) (#690514) + - Fix obsolete automake macros (Marko Lindqvist) (#691101) + - Change dynamic enum and flag gtype creation to use namespaced naming + (Simon Feltman) (#690455) + - Fix Gtk.UIManager.add_ui_from_string() override for non-ASCII chars + (Jonathan Ballet) (#690329) + - Don't dup strings before passing them to type registration functions + (Mike Gorse) (#690532) + - Fix marshalling of arrays of boxed struct values (Carlos Garnacho) + (#656312) + 3.7.3 17-Dec-2012 - Add support for caller-allocated GArray out arguments (Martin Pitt) (#690041) @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: PyGObject -Version: 3.7.3 +Version: 3.7.4 Summary: Python bindings for GObject Home-page: http://www.pygtk.org/ Author: James Henstridge @@ -8,7 +8,7 @@ Author-email: james@daa.com.au Maintainer: Johan Dahlin Maintainer-email: johan@gnome.org License: GNU LGPL -Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.7/pygobject-3.7.3.tar.gz +Download-url: ftp://ftp.gnome.org/pub/GNOME/sources/pygobject/3.7/pygobject-3.7.4.tar.gz Description: Python bindings for GLib and GObject Platform: POSIX, Windows Classifier: Development Status :: 5 - Production/Stable @@ -114,29 +114,6 @@ AC_PREREQ([2.50])dnl am_aux_dir=`cd $ac_aux_dir && pwd` ]) - -# Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 4 - -# This was merged into AC_PROG_CC in Autoconf. - -AU_DEFUN([AM_PROG_CC_STDC], -[AC_PROG_CC -AC_DIAGNOSE([obsolete], [$0: - your code should no longer depend upon `am_cv_prog_cc_stdc', but upon - `ac_cv_prog_cc_stdc'. Remove this warning and the assignment when - you adjust the code. You can also remove the above call to - AC_PROG_CC if you already called it elsewhere.]) -am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc -]) -AU_DEFUN([fp_PROG_CC_STDC]) - # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 @@ -439,18 +416,6 @@ AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 8 - -# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. -AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) - # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for pygobject 3.7.3. +# Generated by GNU Autoconf 2.69 for pygobject 3.7.4. # # Report bugs to <http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject>. # @@ -591,8 +591,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='pygobject' PACKAGE_TARNAME='pygobject' -PACKAGE_VERSION='3.7.3' -PACKAGE_STRING='pygobject 3.7.3' +PACKAGE_VERSION='3.7.4' +PACKAGE_STRING='pygobject 3.7.4' PACKAGE_BUGREPORT='http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject' PACKAGE_URL='https://live.gnome.org/PyGObject/' @@ -1391,7 +1391,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures pygobject 3.7.3 to adapt to many kinds of systems. +\`configure' configures pygobject 3.7.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1461,7 +1461,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of pygobject 3.7.3:";; + short | recursive ) echo "Configuration of pygobject 3.7.4:";; esac cat <<\_ACEOF @@ -1593,7 +1593,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -pygobject configure 3.7.3 +pygobject configure 3.7.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1871,7 +1871,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by pygobject $as_me 3.7.3, which was +It was created by pygobject $as_me 3.7.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2235,9 +2235,9 @@ $as_echo "#define PYGOBJECT_MINOR_VERSION 7" >>confdefs.h PYGOBJECT_MINOR_VERSION=7 -$as_echo "#define PYGOBJECT_MICRO_VERSION 3" >>confdefs.h +$as_echo "#define PYGOBJECT_MICRO_VERSION 4" >>confdefs.h -PYGOBJECT_MICRO_VERSION=3 +PYGOBJECT_MICRO_VERSION=4 ac_config_headers="$ac_config_headers config.h" @@ -2748,7 +2748,7 @@ fi # Define the identity of the package. PACKAGE='pygobject' - VERSION='3.7.3' + VERSION='3.7.4' cat >>confdefs.h <<_ACEOF @@ -12419,676 +12419,6 @@ else fi -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. -set dummy ${ac_tool_prefix}gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_CC"; then - ac_ct_CC=$CC - # Extract the first word of "gcc", so it can be a program name with args. -set dummy gcc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="gcc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -else - CC="$ac_cv_prog_CC" -fi - -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. -set dummy ${ac_tool_prefix}cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="${ac_tool_prefix}cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - fi -fi -if test -z "$CC"; then - # Extract the first word of "cc", so it can be a program name with args. -set dummy cc; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else - ac_prog_rejected=no -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then - ac_prog_rejected=yes - continue - fi - ac_cv_prog_CC="cc" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -if test $ac_prog_rejected = yes; then - # We found a bogon in the path, so make sure we never use it. - set dummy $ac_cv_prog_CC - shift - if test $# != 0; then - # We chose a different compiler from the bogus one. - # However, it has the same basename, so the bogon will be chosen - # first if we set CC to just the basename; use the full file name. - shift - ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" - fi -fi -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$CC"; then - if test -n "$ac_tool_prefix"; then - for ac_prog in cl.exe - do - # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. -set dummy $ac_tool_prefix$ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$CC"; then - ac_cv_prog_CC="$CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_CC="$ac_tool_prefix$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -CC=$ac_cv_prog_CC -if test -n "$CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 -$as_echo "$CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CC" && break - done -fi -if test -z "$CC"; then - ac_ct_CC=$CC - for ac_prog in cl.exe -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_prog_ac_ct_CC+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_CC"; then - ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_prog_ac_ct_CC="$ac_prog" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_CC=$ac_cv_prog_ac_ct_CC -if test -n "$ac_ct_CC"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 -$as_echo "$ac_ct_CC" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$ac_ct_CC" && break -done - - if test "x$ac_ct_CC" = x; then - CC="" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - CC=$ac_ct_CC - fi -fi - -fi - - -test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error $? "no acceptable C compiler found in \$PATH -See \`config.log' for more details" "$LINENO" 5; } - -# Provide some information about the compiler. -$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 -set X $ac_compile -ac_compiler=$2 -for ac_option in --version -v -V -qversion; do - { { ac_try="$ac_compiler $ac_option >&5" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" -$as_echo "$ac_try_echo"; } >&5 - (eval "$ac_compiler $ac_option >&5") 2>conftest.err - ac_status=$? - if test -s conftest.err; then - sed '10a\ -... rest of stderr output deleted ... - 10q' conftest.err >conftest.er1 - cat conftest.er1 >&5 - fi - rm -f conftest.er1 conftest.err - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 -$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if ${ac_cv_c_compiler_gnu+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -#ifndef __GNUC__ - choke me -#endif - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_compiler_gnu=yes -else - ac_compiler_gnu=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -ac_cv_c_compiler_gnu=$ac_compiler_gnu - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 -$as_echo "$ac_cv_c_compiler_gnu" >&6; } -if test $ac_compiler_gnu = yes; then - GCC=yes -else - GCC= -fi -ac_test_CFLAGS=${CFLAGS+set} -ac_save_CFLAGS=$CFLAGS -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 -$as_echo_n "checking whether $CC accepts -g... " >&6; } -if ${ac_cv_prog_cc_g+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_save_c_werror_flag=$ac_c_werror_flag - ac_c_werror_flag=yes - ac_cv_prog_cc_g=no - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -else - CFLAGS="" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -else - ac_c_werror_flag=$ac_save_c_werror_flag - CFLAGS="-g" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_g=yes -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - ac_c_werror_flag=$ac_save_c_werror_flag -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 -$as_echo "$ac_cv_prog_cc_g" >&6; } -if test "$ac_test_CFLAGS" = set; then - CFLAGS=$ac_save_CFLAGS -elif test $ac_cv_prog_cc_g = yes; then - if test "$GCC" = yes; then - CFLAGS="-g -O2" - else - CFLAGS="-g" - fi -else - if test "$GCC" = yes; then - CFLAGS="-O2" - else - CFLAGS= - fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 -$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if ${ac_cv_prog_cc_c89+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_cv_prog_cc_c89=no -ac_save_CC=$CC -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <stdarg.h> -#include <stdio.h> -struct stat; -/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ -struct buf { int x; }; -FILE * (*rcsopen) (struct buf *, struct stat *, int); -static char *e (p, i) - char **p; - int i; -{ - return p[i]; -} -static char *f (char * (*g) (char **, int), char **p, ...) -{ - char *s; - va_list v; - va_start (v,p); - s = g (p, va_arg (v,int)); - va_end (v); - return s; -} - -/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has - function prototypes and stuff, but not '\xHH' hex character constants. - These don't provoke an error unfortunately, instead are silently treated - as 'x'. The following induces an error, until -std is added to get - proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an - array size at least. It's necessary to write '\x00'==0 to get something - that's true only with -std. */ -int osf4_cc_array ['\x00' == 0 ? 1 : -1]; - -/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters - inside strings and character constants. */ -#define FOO(x) 'x' -int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; - -int test (int i, double x); -struct s1 {int (*f) (int a);}; -struct s2 {int (*f) (double a);}; -int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); -int argc; -char **argv; -int -main () -{ -return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; - ; - return 0; -} -_ACEOF -for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ - -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" -do - CC="$ac_save_CC $ac_arg" - if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_prog_cc_c89=$ac_arg -fi -rm -f core conftest.err conftest.$ac_objext - test "x$ac_cv_prog_cc_c89" != "xno" && break -done -rm -f conftest.$ac_ext -CC=$ac_save_CC - -fi -# AC_CACHE_VAL -case "x$ac_cv_prog_cc_c89" in - x) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 -$as_echo "none needed" >&6; } ;; - xno) - { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 -$as_echo "unsupported" >&6; } ;; - *) - CC="$CC $ac_cv_prog_cc_c89" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 -$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; -esac -if test "x$ac_cv_prog_cc_c89" != xno; then : - -fi - -ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - -depcc="$CC" am_compiler_list= - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 -$as_echo_n "checking dependency style of $depcc... " >&6; } -if ${am_cv_CC_dependencies_compiler_type+:} false; then : - $as_echo_n "(cached) " >&6 -else - if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then - # We make a subdir and do the tests there. Otherwise we can end up - # making bogus files that we don't know about and never remove. For - # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. - rm -rf conftest.dir - mkdir conftest.dir - # Copy depcomp to subdir because otherwise we won't find it if we're - # using a relative directory. - cp "$am_depcomp" conftest.dir - cd conftest.dir - # We will build objects and dependencies in a subdirectory because - # it helps to detect inapplicable dependency modes. For instance - # both Tru64's cc and ICC support -MD to output dependencies as a - # side effect of compilation, but ICC will put the dependencies in - # the current directory while Tru64 will put them in the object - # directory. - mkdir sub - - am_cv_CC_dependencies_compiler_type=none - if test "$am_compiler_list" = ""; then - am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` - fi - am__universal=false - case " $depcc " in #( - *\ -arch\ *\ -arch\ *) am__universal=true ;; - esac - - for depmode in $am_compiler_list; do - # Setup a source with many dependencies, because some compilers - # like to wrap large dependency lists on column 80 (with \), and - # we should not choose a depcomp mode which is confused by this. - # - # We need to recreate these files for each test, as the compiler may - # overwrite some of them when testing with obscure command lines. - # This happens at least with the AIX C compiler. - : > sub/conftest.c - for i in 1 2 3 4 5 6; do - echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h - done - echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - - # We check with `-c' and `-o' for the sake of the "dashmstdout" - # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs - am__obj=sub/conftest.${OBJEXT-o} - am__minus_obj="-o $am__obj" - case $depmode in - gcc) - # This depmode causes a compiler race in universal mode. - test "$am__universal" = false || continue - ;; - nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested - if test "x$enable_dependency_tracking" = xyes; then - continue - else - break - fi - ;; - msvc7 | msvc7msys | msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has - # not run yet. These depmodes are late enough in the game, and - # so weak that their functioning should not be impacted. - am__obj=conftest.${OBJEXT-o} - am__minus_obj= - ;; - none) break ;; - esac - if depmode=$depmode \ - source=sub/conftest.c object=$am__obj \ - depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ - $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ - >/dev/null 2>conftest.err && - grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && - grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && - grep $am__obj sub/conftest.Po > /dev/null 2>&1 && - ${MAKE-make} -s -f confmf > /dev/null 2>&1; then - # icc doesn't choke on unknown options, it will just issue warnings - # or remarks (even with -Werror). So we grep stderr for any message - # that says an option was ignored or not supported. - # When given -MP, icc 7.0 and 7.1 complain thusly: - # icc: Command line warning: ignoring option '-M'; no argument required - # The diagnosis changed in icc 8.0: - # icc: Command line remark: option '-MP' not supported - if (grep 'ignoring option' conftest.err || - grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode - break - fi - fi - done - - cd .. - rm -rf conftest.dir -else - am_cv_CC_dependencies_compiler_type=none -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type - - if - test "x$enable_dependency_tracking" != xno \ - && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then - am__fastdepCC_TRUE= - am__fastdepCC_FALSE='#' -else - am__fastdepCC_TRUE='#' - am__fastdepCC_FALSE= -fi - - - -am_cv_prog_cc_stdc=$ac_cv_prog_cc_stdc - if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } @@ -15552,10 +14882,6 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error $? "conditional \"am__fastdepCC\" was never defined. -Usually this means the macro was only invoked conditionally." "$LINENO" 5 -fi if test -z "${HAVE_LIBFFI_TRUE}" && test -z "${HAVE_LIBFFI_FALSE}"; then as_fn_error $? "conditional \"HAVE_LIBFFI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -15965,7 +15291,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by pygobject $as_me 3.7.3, which was +This file was extended by pygobject $as_me 3.7.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -16032,7 +15358,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -pygobject config.status 3.7.3 +pygobject config.status 3.7.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff --git a/configure.ac b/configure.ac index dd5e078..6b88bba 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ m4_define(python3_min_ver, 3.1) dnl the pygobject version number m4_define(pygobject_major_version, 3) m4_define(pygobject_minor_version, 7) -m4_define(pygobject_micro_version, 3) +m4_define(pygobject_micro_version, 4) m4_define(pygobject_version, pygobject_major_version.pygobject_minor_version.pygobject_micro_version) dnl versions of packages we require ... @@ -42,7 +42,7 @@ AC_SUBST(PYGOBJECT_MINOR_VERSION, pygobject_minor_version) AC_DEFINE(PYGOBJECT_MICRO_VERSION, pygobject_micro_version, [pygobject micro version]) AC_SUBST(PYGOBJECT_MICRO_VERSION, pygobject_micro_version) -AM_CONFIG_HEADER(config.h) +AC_CONFIG_HEADERS(config.h) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)]) AM_INIT_AUTOMAKE([1.11.1 foreign no-dist-gzip dist-xz]) @@ -80,7 +80,6 @@ LT_INIT([dlopen win32-dll disable-static]) AC_SEARCH_LIBS([strerror],[cposix]) AC_PROG_CC -AM_PROG_CC_STDC AM_PROG_CC_C_O # option to specify python interpreter to use; this just sets $PYTHON, so that diff --git a/gi/_gobject/propertyhelper.py b/gi/_gobject/propertyhelper.py index a038f1b..d5a1852 100644 --- a/gi/_gobject/propertyhelper.py +++ b/gi/_gobject/propertyhelper.py @@ -149,6 +149,8 @@ class Property(object): @keyword maximum: maximum allowed value (int, float, long only) """ + self.name = None + if type is None: type = object self.type = self._type_from_python(type) @@ -180,7 +182,9 @@ class Property(object): getter = self._default_getter setter = self._default_setter self.getter(getter) - self.setter(setter) + # do not call self.setter() here, as this defines the property name + # already + self.fset = setter if minimum is not None: if minimum < self._get_minimum(): @@ -199,8 +203,6 @@ class Property(object): maximum = self._get_maximum() self.maximum = maximum - self.name = None - self._exc = None def __repr__(self): @@ -248,6 +250,11 @@ class Property(object): def setter(self, fset): """Set the setter function to fset. For use as a decorator.""" self.fset = fset + # with a setter decorator, we must ignore the name of the method in + # install_properties, as this does not need to be a valid property name + # and does not define the property name. So set the name here. + if not self.name: + self.name = self.fget.__name__ return self def _type_from_python(self, type_): @@ -364,10 +371,18 @@ def install_properties(cls): props = [] for name, prop in cls.__dict__.items(): if isinstance(prop, Property): # not same as the built-in - if name in gproperties: - raise ValueError('Property %s was already found in __gproperties__' % name) - prop.name = name - gproperties[name] = prop.get_pspec_args() + # if a property was defined with a decorator, it may already have + # a name; if it was defined with an assignment (prop = Property(...)) + # we set the property's name to the member name + if not prop.name: + prop.name = name + # we will encounter the same property multiple times in case of + # custom setter methods + if prop.name in gproperties: + if gproperties[prop.name] == prop.get_pspec_args(): + continue + raise ValueError('Property %s was already found in __gproperties__' % prop.name) + gproperties[prop.name] = prop.get_pspec_args() props.append(prop) if not props: diff --git a/gi/_gobject/pygenum.c b/gi/_gobject/pygenum.c index 9c3c455..89e3a06 100644 --- a/gi/_gobject/pygenum.c +++ b/gi/_gobject/pygenum.c @@ -216,9 +216,9 @@ pyg_enum_add (PyObject * module, int i; g_return_val_if_fail(typename != NULL, NULL); - if (!g_type_is_a(gtype, G_TYPE_ENUM)) { - g_warning("Trying to register gtype '%s' as enum when in fact it is of type '%s'", - g_type_name(gtype), g_type_name(G_TYPE_FUNDAMENTAL(gtype))); + if (!g_type_is_a (gtype, G_TYPE_ENUM)) { + PyErr_Format (PyExc_TypeError, "Trying to register gtype '%s' as enum when in fact it is of type '%s'", + g_type_name (gtype), g_type_name (G_TYPE_FUNDAMENTAL (gtype))); return NULL; } diff --git a/gi/_gobject/pygobject.c b/gi/_gobject/pygobject.c index 3d0c819..00444bd 100644 --- a/gi/_gobject/pygobject.c +++ b/gi/_gobject/pygobject.c @@ -1872,7 +1872,7 @@ pygobject_handler_unblock(PyGObject *self, PyObject *args) static PyObject * pygobject_emit(PyGObject *self, PyObject *args) { - guint signal_id, i; + guint signal_id, i, j; Py_ssize_t len; GQuark detail; PyObject *first, *py_ret, *repr = NULL; @@ -1929,11 +1929,11 @@ pygobject_emit(PyGObject *self, PyObject *args) g_snprintf(buf, sizeof(buf), "could not convert type %s to %s required for parameter %d", Py_TYPE(item)->tp_name, - g_type_name(G_VALUE_TYPE(¶ms[i+1])), i); + G_VALUE_TYPE_NAME(¶ms[i+1]), i); PyErr_SetString(PyExc_TypeError, buf); - for (i = 0; i < query.n_params + 1; i++) - g_value_unset(¶ms[i]); + for (j = 0; j <= i; j++) + g_value_unset(¶ms[j]); g_free(params); return NULL; diff --git a/gi/_gobject/pygtype.c b/gi/_gobject/pygtype.c index 79c8387..227178f 100644 --- a/gi/_gobject/pygtype.c +++ b/gi/_gobject/pygtype.c @@ -727,6 +727,63 @@ pyg_value_array_from_pyobject(GValue *value, return 0; } +static int +pyg_array_from_pyobject(GValue *value, + PyObject *obj) +{ + int len; + GArray *array; + int i; + + len = PySequence_Length(obj); + if (len == -1) { + PyErr_Clear(); + return -1; + } + + array = g_array_new(FALSE, TRUE, sizeof(GValue)); + + for (i = 0; i < len; ++i) { + PyObject *item = PySequence_GetItem(obj, i); + GType type; + GValue item_value = { 0, }; + int status; + + if (! item) { + PyErr_Clear(); + g_array_free(array, FALSE); + return -1; + } + + if (item == Py_None) + type = G_TYPE_POINTER; /* store None as NULL */ + else { + type = pyg_type_from_object((PyObject*)Py_TYPE(item)); + if (! type) { + PyErr_Clear(); + g_array_free(array, FALSE); + Py_DECREF(item); + return -1; + } + } + + g_value_init(&item_value, type); + status = pyg_value_from_pyobject(&item_value, item); + Py_DECREF(item); + + if (status == -1) { + g_array_free(array, FALSE); + g_value_unset(&item_value); + return -1; + } + + g_array_append_val(array, item_value); + } + + g_value_take_boxed(value, array); + return 0; +} + /** * pyg_value_from_pyobject: * @value: the GValue object to store the converted value in. @@ -766,12 +823,20 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) } break; case G_TYPE_CHAR: + if (PYGLIB_PyLong_Check(obj)) { + glong val; + val = PYGLIB_PyLong_AsLong(obj); + if (val >= -128 && val <= 127) + g_value_set_schar(value, (gchar) val); + else + return -1; + } #if PY_VERSION_HEX < 0x03000000 - if (PyString_Check(obj)) { + else if (PyString_Check(obj)) { g_value_set_schar(value, PyString_AsString(obj)[0]); - } else + } #endif - if (PyUnicode_Check(obj)) { + else if (PyUnicode_Check(obj)) { tmp = PyUnicode_AsUTF8String(obj); g_value_set_schar(value, PYGLIB_PyBytes_AsString(tmp)[0]); Py_DECREF(tmp); @@ -786,7 +851,7 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) glong val; val = PYGLIB_PyLong_AsLong(obj); if (val >= 0 && val <= 255) - g_value_set_uchar(value, (guchar)PYGLIB_PyLong_AsLong (obj)); + g_value_set_uchar(value, (guchar) val); else return -1; #if PY_VERSION_HEX < 0x03000000 @@ -959,6 +1024,9 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) else if (PySequence_Check(obj) && G_VALUE_HOLDS(value, G_TYPE_VALUE_ARRAY)) return pyg_value_array_from_pyobject(value, obj, NULL); + else if (PySequence_Check(obj) && + G_VALUE_HOLDS(value, G_TYPE_ARRAY)) + return pyg_array_from_pyobject(value, obj); else if (PYGLIB_PyUnicode_Check(obj) && G_VALUE_HOLDS(value, G_TYPE_GSTRING)) { GString *string; @@ -980,7 +1048,11 @@ pyg_value_from_pyobject(GValue *value, PyObject *obj) break; } case G_TYPE_PARAM: - if (PyGParamSpec_Check(obj)) + /* we need to support both the wrapped _gobject.GParamSpec and the GI + * GObject.ParamSpec */ + if (G_IS_PARAM_SPEC (pygobject_get (obj))) + g_value_set_param(value, G_PARAM_SPEC (pygobject_get (obj))); + else if (PyGParamSpec_Check(obj)) g_value_set_param(value, PYGLIB_CPointer_GetPointer(obj, NULL)); else return -1; diff --git a/gi/gimodule.c b/gi/gimodule.c index 76530f1..bb5c306 100644 --- a/gi/gimodule.c +++ b/gi/gimodule.c @@ -62,7 +62,9 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, gint n_values; GEnumValue *g_enum_values; int i; + const gchar *namespace; const gchar *type_name; + gchar *full_name; GType g_type; if (!PyArg_ParseTupleAndKeywords (args, kwargs, @@ -79,6 +81,10 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, info = (GIEnumInfo *)py_info->info; n_values = g_enum_info_get_n_values (info); + + /* The new memory is zero filled which fulfills the registration + * function requirement that the last item is zeroed out as a terminator. + */ g_enum_values = g_new0 (GEnumValue, n_values + 1); for (i = 0; i < n_values; i++) { @@ -105,14 +111,36 @@ _wrap_pyg_enum_register_new_gtype_and_add (PyObject *self, g_base_info_unref ((GIBaseInfo *) value_info); } - g_enum_values[n_values].value = 0; - g_enum_values[n_values].value_nick = NULL; - g_enum_values[n_values].value_name = NULL; - + namespace = g_base_info_get_namespace ((GIBaseInfo *) info); type_name = g_base_info_get_name ((GIBaseInfo *) info); - type_name = g_strdup (type_name); - g_type = g_enum_register_static (type_name, g_enum_values); + full_name = g_strconcat (namespace, type_name, NULL); + + /* If enum registration fails, free all the memory allocated + * for the values array. This needs to leak when successful + * as GObject keeps a reference to the data as specified in the docs. + */ + g_type = g_enum_register_static (full_name, g_enum_values); + if (g_type == G_TYPE_INVALID) { + for (i = 0; i < n_values; i++) { + GEnumValue *enum_value = &g_enum_values[i]; + + /* Only free value_name if it is different from value_nick to avoid + * a double free. The pointer might have been is re-used in the case + * c_identifier was NULL in the above loop. + */ + if (enum_value->value_name != enum_value->value_nick) + g_free ((gchar *) enum_value->value_name); + g_free ((gchar *) enum_value->value_nick); + } + + PyErr_Format (PyExc_RuntimeError, "Unable to register enum '%s'", full_name); + + g_free (g_enum_values); + g_free (full_name); + return NULL; + } + g_free (full_name); return pyg_enum_add (NULL, g_type_name (g_type), NULL, g_type); } @@ -150,7 +178,9 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, gint n_values; GFlagsValue *g_flags_values; int i; + const gchar *namespace; const gchar *type_name; + gchar *full_name; GType g_type; if (!PyArg_ParseTupleAndKeywords (args, kwargs, @@ -167,6 +197,10 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, info = (GIEnumInfo *)py_info->info; n_values = g_enum_info_get_n_values (info); + + /* The new memory is zero filled which fulfills the registration + * function requirement that the last item is zeroed out as a terminator. + */ g_flags_values = g_new0 (GFlagsValue, n_values + 1); for (i = 0; i < n_values; i++) { @@ -193,14 +227,36 @@ _wrap_pyg_flags_register_new_gtype_and_add (PyObject *self, g_base_info_unref ((GIBaseInfo *) value_info); } - g_flags_values[n_values].value = 0; - g_flags_values[n_values].value_nick = NULL; - g_flags_values[n_values].value_name = NULL; - + namespace = g_base_info_get_namespace ((GIBaseInfo *) info); type_name = g_base_info_get_name ((GIBaseInfo *) info); - type_name = g_strdup (type_name); - g_type = g_flags_register_static (type_name, g_flags_values); + full_name = g_strconcat (namespace, type_name, NULL); + + /* If enum registration fails, free all the memory allocated + * for the values array. This needs to leak when successful + * as GObject keeps a reference to the data as specified in the docs. + */ + g_type = g_flags_register_static (full_name, g_flags_values); + if (g_type == G_TYPE_INVALID) { + for (i = 0; i < n_values; i++) { + GFlagsValue *flags_value = &g_flags_values[i]; + + /* Only free value_name if it is different from value_nick to avoid + * a double free. The pointer might have been is re-used in the case + * c_identifier was NULL in the above loop. + */ + if (flags_value->value_name != flags_value->value_nick) + g_free ((gchar *) flags_value->value_name); + g_free ((gchar *) flags_value->value_nick); + } + + PyErr_Format (PyExc_RuntimeError, "Unable to register flags '%s'", full_name); + + g_free (g_flags_values); + g_free (full_name); + return NULL; + } + g_free (full_name); return pyg_flags_add (NULL, g_type_name (g_type), NULL, g_type); } diff --git a/gi/overrides/GObject.py b/gi/overrides/GObject.py index c0198b3..41062e2 100644 --- a/gi/overrides/GObject.py +++ b/gi/overrides/GObject.py @@ -4,6 +4,7 @@ # Copyright (C) 2012 Canonical Ltd. # Author: Martin Pitt <martin.pitt@ubuntu.com> # Copyright (C) 2012 Simon Feltman <sfeltman@src.gnome.org> +# Copyright (C) 2012 Bastian Winkler <buz@netbuz.org> # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -205,10 +206,134 @@ __all__ += ['add_emission_hook', 'features', 'list_properties', class Value(GObjectModule.Value): + def __new__(cls, *args, **kwargs): + return GObjectModule.Value.__new__(cls) + + def __init__(self, value_type=None, py_value=None): + GObjectModule.Value.__init__(self) + if value_type is not None: + self.init(value_type) + if py_value is not None: + self.set_value(py_value) + def __del__(self): - if self._free_on_dealloc: + if self._free_on_dealloc and self.g_type != TYPE_INVALID: self.unset() + def set_value(self, py_value): + if self.g_type == _gobject.TYPE_INVALID: + raise TypeError("GObject.Value needs to be initialized first") + elif self.g_type == TYPE_BOOLEAN: + self.set_boolean(py_value) + elif self.g_type == TYPE_CHAR: + self.set_char(py_value) + elif self.g_type == TYPE_UCHAR: + self.set_uchar(py_value) + elif self.g_type == TYPE_INT: + self.set_int(py_value) + elif self.g_type == TYPE_UINT: + self.set_uint(py_value) + elif self.g_type == TYPE_LONG: + self.set_long(py_value) + elif self.g_type == TYPE_ULONG: + self.set_ulong(py_value) + elif self.g_type == TYPE_INT64: + self.set_int64(py_value) + elif self.g_type == TYPE_UINT64: + self.set_uint64(py_value) + elif self.g_type == TYPE_FLOAT: + self.set_float(py_value) + elif self.g_type == TYPE_DOUBLE: + self.set_double(py_value) + elif self.g_type == TYPE_STRING: + if isinstance(py_value, str): + py_value = str(py_value) + elif sys.version_info < (3, 0): + if isinstance(py_value, unicode): + py_value = py_value.encode('UTF-8') + else: + raise ValueError("Expected string or unicode but got %s%s" % + (py_value, type(py_value))) + else: + raise ValueError("Expected string but got %s%s" % + (py_value, type(py_value))) + self.set_string(py_value) + elif self.g_type == TYPE_PARAM: + self.set_param(py_value) + elif self.g_type.is_a(TYPE_ENUM): + self.set_enum(py_value) + elif self.g_type.is_a(TYPE_FLAGS): + self.set_flags(py_value) + elif self.g_type.is_a(TYPE_BOXED): + self.set_boxed(py_value) + elif self.g_type == TYPE_POINTER: + self.set_pointer(py_value) + elif self.g_type.is_a(TYPE_OBJECT): + self.set_object(py_value) + elif self.g_type == TYPE_UNICHAR: + self.set_uint(int(py_value)) + # elif self.g_type == TYPE_OVERRIDE: + # pass + elif self.g_type == TYPE_GTYPE: + self.set_gtype(py_value) + elif self.g_type == TYPE_VARIANT: + self.set_variant(py_value) + elif self.g_type == TYPE_PYOBJECT: + self.set_boxed(py_value) + else: + raise TypeError("Unknown value type %s" % self.g_type) + + def get_value(self): + if self.g_type == TYPE_BOOLEAN: + return self.get_boolean() + elif self.g_type == TYPE_CHAR: + return self.get_char() + elif self.g_type == TYPE_UCHAR: + return self.get_uchar() + elif self.g_type == TYPE_INT: + return self.get_int() + elif self.g_type == TYPE_UINT: + return self.get_uint() + elif self.g_type == TYPE_LONG: + return self.get_long() + elif self.g_type == TYPE_ULONG: + return self.get_ulong() + elif self.g_type == TYPE_INT64: + return self.get_int64() + elif self.g_type == TYPE_UINT64: + return self.get_uint64() + elif self.g_type == TYPE_FLOAT: + return self.get_float() + elif self.g_type == TYPE_DOUBLE: + return self.get_double() + elif self.g_type == TYPE_STRING: + return self.get_string() + elif self.g_type == TYPE_PARAM: + return self.get_param() + elif self.g_type.is_a(TYPE_ENUM): + return self.get_enum() + elif self.g_type.is_a(TYPE_FLAGS): + return self.get_flags() + elif self.g_type.is_a(TYPE_BOXED): + return self.get_boxed() + elif self.g_type == TYPE_POINTER: + return self.get_pointer() + elif self.g_type.is_a(TYPE_OBJECT): + return self.get_object() + elif self.g_type == TYPE_UNICHAR: + return self.get_uint() + elif self.g_type == TYPE_GTYPE: + return self.get_gtype() + elif self.g_type == TYPE_VARIANT: + return self.get_variant() + elif self.g_type == TYPE_PYOBJECT: + pass + else: + return None + + def __repr__(self): + return '<Value (%s) %s>' % (self.g_type.name, self.get_value()) + Value = override(Value) __all__.append('Value') diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py index 78bbd36..15c0ae6 100644 --- a/gi/overrides/Gtk.py +++ b/gi/overrides/Gtk.py @@ -294,7 +294,7 @@ class UIManager(Gtk.UIManager): if not isinstance(buffer, _basestring): raise TypeError('buffer must be a string') - length = len(buffer) + length = len(buffer.encode('UTF-8')) return Gtk.UIManager.add_ui_from_string(self, buffer, length) @@ -780,6 +780,12 @@ class TreeModel(Gtk.TreeModel): raise IndexError("could not find tree path '%s'" % key) return aiter + def _coerce_path(self, path): + if isinstance(path, Gtk.TreePath): + return path + else: + return TreePath(path) + def __getitem__(self, key): aiter = self._getiter(key) return TreeModelRow(self, aiter) @@ -796,9 +802,7 @@ class TreeModel(Gtk.TreeModel): return TreeModelRowIter(self, self.get_iter_first()) def get_iter(self, path): - if not isinstance(path, Gtk.TreePath): - path = TreePath(path) - + path = self._coerce_path(path) success, aiter = super(TreeModel, self).get_iter(path) if not success: raise ValueError("invalid tree path '%s'" % path) @@ -872,84 +876,11 @@ class TreeModel(Gtk.TreeModel): self.set_value(treeiter, column, value) def _convert_value(self, column, value): - if value is None: - return None + '''Convert value to a GObject.Value of the expected type''' - # we may need to convert to a basic type - type_ = self.get_column_type(column) - if type_ == GObject.TYPE_STRING: - if isinstance(value, str): - value = str(value) - elif sys.version_info < (3, 0): - if isinstance(value, unicode): - value = value.encode('UTF-8') - else: - raise ValueError('Expected string or unicode for column %i but got %s%s' % (column, value, type(value))) - else: - raise ValueError('Expected a string for column %i but got %s' % (column, type(value))) - elif type_ == GObject.TYPE_FLOAT or type_ == GObject.TYPE_DOUBLE: - if isinstance(value, float): - value = float(value) - else: - raise ValueError('Expected a float for column %i but got %s' % (column, type(value))) - elif type_ == GObject.TYPE_LONG or type_ == GObject.TYPE_INT: - if isinstance(value, int): - value = int(value) - elif sys.version_info < (3, 0): - if isinstance(value, long): - value = long(value) - else: - raise ValueError('Expected an long for column %i but got %s' % (column, type(value))) - else: - raise ValueError('Expected an integer for column %i but got %s' % (column, type(value))) - elif type_ == GObject.TYPE_BOOLEAN: - cmp_classes = [int] - if sys.version_info < (3, 0): - cmp_classes.append(long) - - if isinstance(value, tuple(cmp_classes)): - value = bool(value) - else: - raise ValueError('Expected a bool for column %i but got %s' % (column, type(value))) - else: - # use GValues directly to marshal to the correct type - # standard object checks should take care of validation - # so we don't have to do it here - value_container = GObject.Value() - value_container.init(type_) - if type_ == GObject.TYPE_CHAR: - value_container.set_char(value) - value = value_container - elif type_ == GObject.TYPE_UCHAR: - value_container.set_uchar(value) - value = value_container - elif type_ == GObject.TYPE_UNICHAR: - cmp_classes = [str] - if sys.version_info < (3, 0): - cmp_classes.append(unicode) - - if isinstance(value, tuple(cmp_classes)): - value = ord(value[0]) - - value_container.set_uint(value) - value = value_container - elif type_ == GObject.TYPE_UINT: - value_container.set_uint(value) - value = value_container - elif type_ == GObject.TYPE_ULONG: - value_container.set_ulong(value) - value = value_container - elif type_ == GObject.TYPE_INT64: - value_container.set_int64(value) - value = value_container - elif type_ == GObject.TYPE_UINT64: - value_container.set_uint64(value) - value = value_container - elif type_ == GObject.TYPE_PYOBJECT: - value_container.set_boxed(value) - value = value_container - - return value + if isinstance(value, GObject.Value): + return value + return GObject.Value(self.get_column_type(column), value) def get(self, treeiter, *columns): n_columns = self.get_n_columns() @@ -969,6 +900,27 @@ class TreeModel(Gtk.TreeModel): def filter_new(self, root=None): return super(TreeModel, self).filter_new(root) + # + # Signals supporting python iterables as tree paths + # + def row_changed(self, path, iter): + return super(TreeModel, self).row_changed(self._coerce_path(path), iter) + + def row_inserted(self, path, iter): + return super(TreeModel, self).row_inserted(self._coerce_path(path), iter) + + def row_has_child_toggled(self, path, iter): + return super(TreeModel, self).row_has_child_toggled(self._coerce_path(path), + iter) + + def row_deleted(self, path): + return super(TreeModel, self).row_deleted(self._coerce_path(path)) + + def rows_reordered(self, path, iter, new_order): + return super(TreeModel, self).rows_reordered(self._coerce_path(path), + iter, new_order) + + TreeModel = override(TreeModel) __all__.append('TreeModel') @@ -1592,6 +1544,11 @@ class TreeModelFilter(Gtk.TreeModelFilter): def set_visible_func(self, func, data=None): super(TreeModelFilter, self).set_visible_func(func, data) + def set_value(self, iter, column, value): + # Delegate to child model + iter = self.convert_iter_to_child_iter(iter) + self.get_model().set_value(iter, column, value) + TreeModelFilter = override(TreeModelFilter) __all__.append('TreeModelFilter') diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c index 4e3c464..34c4970 100644 --- a/gi/pygi-argument.c +++ b/gi/pygi-argument.c @@ -410,7 +410,8 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info, /* No check; every Python object has a truth value. */ break; case GI_TYPE_TAG_UINT8: - /* UINT8 types can be characters */ + case GI_TYPE_TAG_INT8: + /* (U)INT8 types can be characters */ if (PYGLIB_PyBytes_Check(object)) { if (PYGLIB_PyBytes_Size(object) != 1) { PyErr_Format (PyExc_TypeError, "Must be a single character"); @@ -420,7 +421,6 @@ _pygi_g_type_info_check_object (GITypeInfo *type_info, break; } - case GI_TYPE_TAG_INT8: case GI_TYPE_TAG_INT16: case GI_TYPE_TAG_UINT16: case GI_TYPE_TAG_INT32: @@ -811,22 +811,18 @@ _pygi_argument_to_array (GIArgument *arg, return g_array; } gint length_arg_pos; - GIArgInfo *length_arg_info; - GITypeInfo *length_type_info; + GIArgInfo length_arg_info; + GITypeInfo length_type_info; length_arg_pos = g_type_info_get_array_length (type_info); g_assert (length_arg_pos >= 0); g_assert (callable_info); - length_arg_info = g_callable_info_get_arg (callable_info, length_arg_pos); - length_type_info = g_arg_info_get_type (length_arg_info); - g_base_info_unref ( (GIBaseInfo *) length_arg_info); + g_callable_info_load_arg (callable_info, length_arg_pos, &length_arg_info); + g_arg_info_load_type (&length_arg_info, &length_type_info); if (!gi_argument_to_gssize (args[length_arg_pos], - g_type_info_get_tag (length_type_info), - &length)) { - g_base_info_unref ( (GIBaseInfo *) length_type_info); + g_type_info_get_tag (&length_type_info), + &length)) return NULL; - } - g_base_info_unref ( (GIBaseInfo *) length_type_info); } } diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index 2a44c02..0848ccf 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -480,6 +480,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache, child_cache = _arg_cache_alloc (); } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD || child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) { + arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array; return TRUE; } diff --git a/gi/pygi-closure.c b/gi/pygi-closure.c index 0e49c72..f2f21f0 100644 --- a/gi/pygi-closure.c +++ b/gi/pygi-closure.c @@ -154,8 +154,8 @@ static GIArgument * _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) { gint num_args, i; - GIArgInfo *arg_info; - GITypeInfo *arg_type; + GIArgInfo arg_info; + GITypeInfo arg_type; GITypeTag tag; GIDirection direction; GIArgument *g_args; @@ -164,10 +164,10 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) g_args = g_new0 (GIArgument, num_args); for (i = 0; i < num_args; i++) { - arg_info = g_callable_info_get_arg (callable_info, i); - arg_type = g_arg_info_get_type (arg_info); - tag = g_type_info_get_tag (arg_type); - direction = g_arg_info_get_direction (arg_info); + g_callable_info_load_arg (callable_info, i, &arg_info); + g_arg_info_load_type (&arg_info, &arg_type); + tag = g_type_info_get_tag (&arg_type); + direction = g_arg_info_get_direction (&arg_info); if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { g_args[i].v_pointer = * (gpointer *) args[i]; @@ -214,7 +214,7 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) GIBaseInfo *interface; GIInfoType interface_type; - interface = g_type_info_get_interface (arg_type); + interface = g_type_info_get_interface (&arg_type); interface_type = g_base_info_get_type (interface); if (interface_type == GI_INFO_TYPE_OBJECT || @@ -249,8 +249,6 @@ _pygi_closure_convert_ffi_arguments (GICallableInfo *callable_info, void **args) g_args[i].v_pointer = 0; } } - g_base_info_unref ( (GIBaseInfo *) arg_info); - g_base_info_unref ( (GIBaseInfo *) arg_type); } return g_args; } @@ -283,19 +281,21 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, if (i == user_data_arg || i == destroy_notify_arg) continue; - GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i); - GIDirection direction = g_arg_info_get_direction (arg_info); + GIArgInfo arg_info; + g_callable_info_load_arg (callable_info, i, &arg_info); + GIDirection direction = g_arg_info_get_direction (&arg_info); if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { - GITypeInfo *arg_type = g_arg_info_get_type (arg_info); - GITypeTag arg_tag = g_type_info_get_tag (arg_type); - GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); + GITypeInfo arg_type; + g_arg_info_load_type (&arg_info, &arg_type); + GITypeTag arg_tag = g_type_info_get_tag (&arg_type); + GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info); PyObject *value; GIArgument *arg; gboolean free_array = FALSE; if (direction == GI_DIRECTION_IN && arg_tag == GI_TYPE_TAG_VOID && - g_type_info_is_pointer (arg_type)) { + g_type_info_is_pointer (&arg_type)) { if (user_data == NULL) { Py_INCREF (Py_None); @@ -310,7 +310,7 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, GIBaseInfo *info; GIInfoType info_type; - info = g_type_info_get_interface (arg_type); + info = g_type_info_get_interface (&arg_type); info_type = g_base_info_get_type (info); arg = (GIArgument*) &g_args[i]; @@ -318,10 +318,10 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, if (info_type == GI_INFO_TYPE_CALLBACK) { gpointer user_data = NULL; GDestroyNotify destroy_notify = NULL; - GIScopeType scope = g_arg_info_get_scope(arg_info); + GIScopeType scope = g_arg_info_get_scope(&arg_info); - user_data_arg = g_arg_info_get_closure(arg_info); - destroy_notify_arg = g_arg_info_get_destroy(arg_info); + user_data_arg = g_arg_info_get_closure(&arg_info); + destroy_notify_arg = g_arg_info_get_destroy(&arg_info); if (user_data_arg != -1) user_data = g_args[user_data_arg].v_pointer; @@ -335,39 +335,31 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, (GIFunctionInfo *) info, destroy_notify); } else - value = _pygi_argument_to_object (arg, arg_type, transfer); + value = _pygi_argument_to_object (arg, &arg_type, transfer); g_base_info_unref (info); - if (value == NULL) { - g_base_info_unref (arg_type); - g_base_info_unref (arg_info); + if (value == NULL) goto error; - } } else { if (direction == GI_DIRECTION_IN) arg = (GIArgument*) &g_args[i]; else arg = (GIArgument*) g_args[i].v_pointer; - if (g_type_info_get_tag (arg_type) == GI_TYPE_TAG_ARRAY) + if (g_type_info_get_tag (&arg_type) == GI_TYPE_TAG_ARRAY) arg->v_pointer = _pygi_argument_to_array (arg, (GIArgument **) args, - callable_info, arg_type, &free_array); + callable_info, &arg_type, &free_array); - value = _pygi_argument_to_object (arg, arg_type, transfer); + value = _pygi_argument_to_object (arg, &arg_type, transfer); if (free_array) g_array_free (arg->v_pointer, FALSE); - if (value == NULL) { - g_base_info_unref (arg_type); - g_base_info_unref (arg_info); + if (value == NULL) goto error; - } } PyTuple_SET_ITEM (*py_args, n_in_args, value); n_in_args++; - - g_base_info_unref (arg_type); } if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { @@ -375,7 +367,6 @@ _pygi_closure_convert_arguments (GICallableInfo *callable_info, void **args, n_out_args++; } - g_base_info_unref (arg_info); } if (_PyTuple_Resize (py_args, n_in_args) == -1) @@ -399,37 +390,38 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, void *resp) { int n_args, i, i_py_retval, i_out_args; - GITypeInfo *return_type_info; + GITypeInfo return_type_info; GITypeTag return_type_tag; i_py_retval = 0; - return_type_info = g_callable_info_get_return_type (callable_info); - return_type_tag = g_type_info_get_tag (return_type_info); + g_callable_info_load_return_type (callable_info, &return_type_info); + return_type_tag = g_type_info_get_tag (&return_type_info); if (return_type_tag != GI_TYPE_TAG_VOID) { GITransfer transfer = g_callable_info_get_caller_owns (callable_info); if (PyTuple_Check (py_retval)) { PyObject *item = PyTuple_GET_ITEM (py_retval, 0); _pygi_closure_assign_pyobj_to_retval (resp, item, - return_type_info, transfer); + &return_type_info, transfer); } else { _pygi_closure_assign_pyobj_to_retval (resp, py_retval, - return_type_info, transfer); + &return_type_info, transfer); } i_py_retval++; } - g_base_info_unref (return_type_info); i_out_args = 0; n_args = g_callable_info_get_n_args (callable_info); - for (i = 1; i < n_args; i++) { - GIArgInfo *arg_info = g_callable_info_get_arg (callable_info, i); - GITypeInfo *type_info = g_arg_info_get_type (arg_info); - GIDirection direction = g_arg_info_get_direction (arg_info); + for (i = 0; i < n_args; i++) { + GIArgInfo arg_info; + g_callable_info_load_arg (callable_info, i, &arg_info); + GITypeInfo type_info; + g_arg_info_load_type (&arg_info, &type_info); + GIDirection direction = g_arg_info_get_direction (&arg_info); if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { - GITransfer transfer = g_arg_info_get_ownership_transfer (arg_info); + GITransfer transfer = g_arg_info_get_ownership_transfer (&arg_info); - if (g_type_info_get_tag (type_info) == GI_TYPE_TAG_ERROR) { + if (g_type_info_get_tag (&type_info) == GI_TYPE_TAG_ERROR) { /* TODO: check if an exception has been set and convert it to a GError */ out_args[i_out_args].v_pointer = NULL; i_out_args++; @@ -439,10 +431,10 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, if (PyTuple_Check (py_retval)) { PyObject *item = PyTuple_GET_ITEM (py_retval, i_py_retval); _pygi_closure_assign_pyobj_to_out_argument ( - out_args[i_out_args].v_pointer, item, type_info, transfer); + out_args[i_out_args].v_pointer, item, &type_info, transfer); } else if (i_py_retval == 0) { _pygi_closure_assign_pyobj_to_out_argument ( - out_args[i_out_args].v_pointer, py_retval, type_info, + out_args[i_out_args].v_pointer, py_retval, &type_info, transfer); } else g_assert_not_reached(); @@ -450,8 +442,6 @@ _pygi_closure_set_out_arguments (GICallableInfo *callable_info, i_out_args++; i_py_retval++; } - g_base_info_unref (type_info); - g_base_info_unref (arg_info); } } diff --git a/gi/pygi-info.c b/gi/pygi-info.c index e726b2d..cd3d97d 100644 --- a/gi/pygi-info.c +++ b/gi/pygi-info.c @@ -1510,7 +1510,8 @@ _wrap_g_field_info_set_value (PyGIBaseInfo *self, g_base_info_unref (info); } else if (g_type_info_is_pointer (field_type_info) - && g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID) { + && (g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_VOID + || g_type_info_get_tag (field_type_info) == GI_TYPE_TAG_UTF8)) { value = _pygi_argument_from_object (py_value, field_type_info, GI_TRANSFER_NOTHING); if (PyErr_Occurred()) { diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index dc14ca5..4ddfbb4 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -262,22 +262,30 @@ _pygi_marshal_from_py_int8 (PyGIInvokeState *state, PyObject *py_long; long long_; - if (!PyNumber_Check (py_arg)) { - PyErr_Format (PyExc_TypeError, "Must be number, not %s", - py_arg->ob_type->tp_name); - return FALSE; - } + if (PYGLIB_PyBytes_Check (py_arg)) { - py_long = PYGLIB_PyNumber_Long (py_arg); - if (!py_long) - return FALSE; + if (PYGLIB_PyBytes_Size (py_arg) != 1) { + PyErr_Format (PyExc_TypeError, "Must be a single character"); + return FALSE; + } - long_ = PYGLIB_PyLong_AsLong (py_long); - Py_DECREF (py_long); + long_ = (char)(PYGLIB_PyBytes_AsString (py_arg)[0]); + } else if (PyNumber_Check (py_arg)) { + py_long = PYGLIB_PyNumber_Long (py_arg); + if (!py_long) + return FALSE; - if (PyErr_Occurred ()) { - PyErr_Clear (); - PyErr_Format (PyExc_ValueError, "%ld not in range %d to %d", long_, -128, 127); + long_ = PYGLIB_PyLong_AsLong (py_long); + Py_DECREF (py_long); + + if (PyErr_Occurred ()) { + PyErr_Clear (); + PyErr_Format (PyExc_ValueError, "%ld not in range %d to %d", long_, -128, 127); + return FALSE; + } + } else { + PyErr_Format (PyExc_TypeError, "Must be number or single byte string, not %s", + py_arg->ob_type->tp_name); return FALSE; } @@ -1009,6 +1017,12 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state, if (from_py_cleanup) from_py_cleanup (state, item_arg_cache, item.v_pointer, TRUE); } + } else if (is_boxed && !item_iface_cache->arg_cache.is_pointer) { + /* The array elements are not expected to be pointers, but the + * elements obtained are boxed pointers themselves, so insert + * the pointed to data. + */ + g_array_insert_vals (array_, i, item.v_pointer, 1); } else { g_array_insert_val (array_, i, item); } diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c index 950895d..d5a0734 100644 --- a/gi/pygi-marshal-to-py.c +++ b/gi/pygi-marshal-to-py.c @@ -434,13 +434,14 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, item_arg.v_pointer = g_variant_ref_sink (g_array_index (array_, gpointer, i)); else item_arg.v_pointer = g_array_index (array_, gpointer, i); - } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) { + } else if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && !item_arg_cache->is_pointer) { + /* array elements are structs */ gpointer *_struct = g_malloc (item_size); memcpy (_struct, array_->data + i * item_size, item_size); item_arg.v_pointer = _struct; } else if (item_arg_cache->is_pointer) - /* this is the case for GAtom* arrays */ + /* array elements are pointers to values */ item_arg.v_pointer = g_array_index (array_, gpointer, i); else item_arg.v_pointer = array_->data + i * item_size; @@ -814,7 +815,9 @@ _pygi_marshal_to_py_interface_struct (PyGIInvokeState *state, arg->v_pointer); } else if (g_type_is_a (type, G_TYPE_BOXED)) { py_obj = _pygi_boxed_new ( (PyTypeObject *)iface_cache->py_type, arg->v_pointer, - arg_cache->transfer == GI_TRANSFER_EVERYTHING); + arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->is_caller_allocates); + if (arg_cache->is_caller_allocates) + ((PyGIBoxed *)py_obj)->slice_allocated = TRUE; } else if (g_type_is_a (type, G_TYPE_POINTER)) { if (iface_cache->py_type == NULL || !PyType_IsSubtype ( (PyTypeObject *)iface_cache->py_type, &PyGIStruct_Type)) { diff --git a/gi/pygi-property.c b/gi/pygi-property.c index 6079efc..2e32fea 100644 --- a/gi/pygi-property.c +++ b/gi/pygi-property.c @@ -217,7 +217,10 @@ pygi_get_property_value_real (PyGObject *instance, GParamSpec *pspec) break; case GI_TYPE_TAG_GLIST: case GI_TYPE_TAG_GSLIST: - arg.v_pointer = g_value_get_pointer (&value); + if (G_VALUE_HOLDS_BOXED(&value)) + arg.v_pointer = g_value_get_boxed (&value); + else + arg.v_pointer = g_value_get_pointer (&value); break; case GI_TYPE_TAG_ARRAY: { @@ -384,7 +387,10 @@ pygi_set_property_value_real (PyGObject *instance, g_value_set_boxed (&value, arg.v_pointer); break; case GI_TYPE_TAG_GLIST: - g_value_set_pointer (&value, arg.v_pointer); + if (G_VALUE_HOLDS_BOXED(&value)) + g_value_set_boxed (&value, arg.v_pointer); + else + g_value_set_pointer (&value, arg.v_pointer); break; case GI_TYPE_TAG_ARRAY: { diff --git a/tests/Makefile.am b/tests/Makefile.am index 77efd2e..1d40539 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -84,6 +84,7 @@ EXTRA_DIST = \ test-unknown.h \ te_ST@nouppera \ org.gnome.test.gschema.xml \ + test_gio.py \ test_glib.py \ test_gobject.py \ test_gtype.py \ @@ -101,7 +102,6 @@ EXTRA_DIST = \ test_gi.py \ test_gdbus.py \ test_overrides.py \ - test_overrides_gio.py \ test_overrides_glib.py \ test_overrides_pango.py \ test_overrides_gdk.py \ diff --git a/tests/Makefile.in b/tests/Makefile.in index 5aa69dc..8e4e802 100644 --- a/tests/Makefile.in +++ b/tests/Makefile.in @@ -330,6 +330,7 @@ EXTRA_DIST = \ test-unknown.h \ te_ST@nouppera \ org.gnome.test.gschema.xml \ + test_gio.py \ test_glib.py \ test_gobject.py \ test_gtype.py \ @@ -347,7 +348,6 @@ EXTRA_DIST = \ test_gi.py \ test_gdbus.py \ test_overrides.py \ - test_overrides_gio.py \ test_overrides_glib.py \ test_overrides_pango.py \ test_overrides_gdk.py \ diff --git a/tests/runtests.py b/tests/runtests.py index 9f3a7ec..1bd1be0 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -18,6 +18,13 @@ if sys.version_info[:2] == (2, 6): unittest.skipUnless = skipUnless unittest.expectedFailure = lambda obj: obj + def skipIf(condition, reason): + if condition: + sys.stderr.write('[expected failure] ') + return lambda obj: obj + + unittest.skipIf = skipUnless + def assertGreater(self, a, b, msg=None): if not a > b: self.fail('%s not greater than %s' % (repr(a), repr(b))) @@ -26,12 +33,22 @@ if sys.version_info[:2] == (2, 6): if not a >= b: self.fail('%s not greater than or equal to %s' % (repr(a), repr(b))) + def assertLess(self, a, b, msg=None): + if not a < b: + self.fail('%s not less than %s' % (repr(a), repr(b))) + + def assertLessEqual(self, a, b, msg=None): + if not a <= b: + self.fail('%s not less than or equal to %s' % (repr(a), repr(b))) + def assertIsInstance(self, obj, cls, msg=None): if not isinstance(obj, cls): self.fail('%s is not an instance of %r' % (repr(obj), cls)) unittest.TestCase.assertGreaterEqual = assertGreaterEqual unittest.TestCase.assertGreater = assertGreater + unittest.TestCase.assertLessEqual = assertLessEqual + unittest.TestCase.assertLess = assertLess unittest.TestCase.assertIsInstance = assertIsInstance if sys.version_info[:2] == (2, 7): @@ -59,6 +76,7 @@ os.environ['G_DEBUG'] = 'fatal-warnings fatal-criticals' # first. os.environ['GSETTINGS_BACKEND'] = 'memory' os.environ['GSETTINGS_SCHEMA_DIR'] = tests_builddir +os.environ['G_FILENAME_ENCODING'] = 'UTF-8' # Load tests. if 'TEST_NAMES' in os.environ: diff --git a/tests/test_everything.py b/tests/test_everything.py index f1f14b7..dcc61e8 100644 --- a/tests/test_everything.py +++ b/tests/test_everything.py @@ -675,17 +675,14 @@ class TestCallbacks(unittest.TestCase): self.assertEqual(TestCallbacks.called, 2) self.assertEqual(sys.getrefcount(callback), refcount) - # FIXME: TypeError: callback() takes 2 positional arguments but 4 were given - # does not remove the array length arguments - @unittest.expectedFailure def test_callback_scope_call_array(self): # This tests a callback that gets called multiple times from a # single scope call in python with array arguments TestCallbacks.callargs = [] - # works with: - #def callback(one, one_length, two, two_length): - def callback(one, two): + # FIXME: would be cleaner without the explicit length args: + # def callback(one, two): + def callback(one, one_length, two, two_length): TestCallbacks.callargs.append((one, two)) return len(TestCallbacks.callargs) @@ -1195,6 +1192,28 @@ class TestSignals(unittest.TestCase): obj.emit_sig_with_uint64() self.assertEqual(obj.callback_i, GObject.G_MAXUINT64) + def test_intarray_ret(self): + obj = Everything.TestObj() + + def callback(obj, i): + obj.callback_i = i + return [i, i + 1] + + obj.callback_i = None + + try: + obj.connect('sig-with-intarray-ret', callback) + except TypeError as e: + # compat with g-i 1.34.x + if 'unknown signal' in str(e): + return + raise + + rv = obj.emit('sig-with-intarray-ret', 42) + self.assertEqual(obj.callback_i, 42) + self.assertEqual(type(rv), GLib.Array) + self.assertEqual(rv.len, 2) + @unittest.skipUnless(has_cairo, 'built without cairo support') @unittest.skipUnless(Gtk, 'Gtk not available') diff --git a/tests/test_gi.py b/tests/test_gi.py index a2664f1..29a69d0 100644 --- a/tests/test_gi.py +++ b/tests/test_gi.py @@ -812,6 +812,18 @@ class TestArray(unittest.TestCase): GIMarshallingTests.array_struct_in([struct1, struct2, struct3]) + @unittest.skipUnless(hasattr(GIMarshallingTests, 'array_struct_value_in'), + 'too old gobject-introspection') + def test_array_boxed_struct_value_in(self): + struct1 = GIMarshallingTests.BoxedStruct() + struct1.long_ = 1 + struct2 = GIMarshallingTests.BoxedStruct() + struct2.long_ = 2 + struct3 = GIMarshallingTests.BoxedStruct() + struct3.long_ = 3 + + GIMarshallingTests.array_struct_value_in([struct1, struct2, struct3]) + def test_array_boxed_struct_take_in(self): struct1 = GIMarshallingTests.BoxedStruct() struct1.long_ = 1 @@ -824,13 +836,11 @@ class TestArray(unittest.TestCase): self.assertEqual(1, struct1.long_) - @unittest.expectedFailure def test_array_boxed_struct_return(self): (struct1, struct2, struct3) = GIMarshallingTests.array_zero_terminated_return_struct() self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct1)) self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct2)) self.assertEqual(GIMarshallingTests.BoxedStruct, type(struct3)) - # FIXME: gets bogus values self.assertEqual(42, struct1.long_) self.assertEqual(43, struct2.long_) self.assertEqual(44, struct3.long_) @@ -1042,8 +1052,8 @@ class TestGBytes(unittest.TestCase): self.assertFalse(b.equal(a2)) self.assertEqual(0, a1.compare(a2)) - self.assertEqual(1, a1.compare(b)) - self.assertEqual(-1, b.compare(a1)) + self.assertLess(0, a1.compare(b)) + self.assertGreater(0, b.compare(a1)) class TestGByteArray(unittest.TestCase): @@ -1213,32 +1223,24 @@ class TestGValue(unittest.TestCase): def test_gvalue_in(self): GIMarshallingTests.gvalue_in(42) - value = GObject.Value() - value.init(GObject.TYPE_INT) - value.set_int(42) + value = GObject.Value(GObject.TYPE_INT, 42) GIMarshallingTests.gvalue_in(value) def test_gvalue_int64_in(self): - value = GObject.Value() - value.init(GObject.TYPE_INT64) - value.set_int64(GObject.G_MAXINT64) + value = GObject.Value(GObject.TYPE_INT64, GObject.G_MAXINT64) GIMarshallingTests.gvalue_int64_in(value) def test_gvalue_in_with_type(self): - value = GObject.Value() - value.init(GObject.TYPE_STRING) - value.set_string('foo') + value = GObject.Value(GObject.TYPE_STRING, 'foo') GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_STRING) - value = GObject.Value() - value.init(GIMarshallingTests.Flags.__gtype__) - value.set_flags(GIMarshallingTests.Flags.VALUE1) + value = GObject.Value(GIMarshallingTests.Flags.__gtype__, + GIMarshallingTests.Flags.VALUE1) GIMarshallingTests.gvalue_in_with_type(value, GObject.TYPE_FLAGS) def test_gvalue_in_enum(self): - value = GObject.Value() - value.init(GIMarshallingTests.Enum.__gtype__) - value.set_enum(GIMarshallingTests.Enum.VALUE3) + value = GObject.Value(GIMarshallingTests.Enum.__gtype__, + GIMarshallingTests.Enum.VALUE3) GIMarshallingTests.gvalue_in_enum(value) def test_gvalue_out(self): @@ -1252,9 +1254,7 @@ class TestGValue(unittest.TestCase): def test_gvalue_inout(self): self.assertEqual('42', GIMarshallingTests.gvalue_inout(42)) - value = GObject.Value() - value.init(GObject.TYPE_INT) - value.set_int(42) + value = GObject.Value(int, 42) self.assertEqual('42', GIMarshallingTests.gvalue_inout(value)) def test_gvalue_flat_array_in(self): @@ -1367,13 +1367,11 @@ class TestCallbacks(unittest.TestCase): return 5 self.assertEqual(GIMarshallingTests.callback_return_value_only(cb), 5) - @unittest.expectedFailure def test_one_out_arg(self): def cb(): return 5.5 self.assertAlmostEqual(GIMarshallingTests.callback_one_out_parameter(cb), 5.5) - @unittest.expectedFailure def test_multiple_out_args(self): def cb(): return (5.5, 42.0) @@ -1381,7 +1379,6 @@ class TestCallbacks(unittest.TestCase): self.assertAlmostEqual(res[0], 5.5) self.assertAlmostEqual(res[1], 42.0) - @unittest.expectedFailure def test_return_and_one_out_arg(self): def cb(): return (5, 42.0) @@ -1389,7 +1386,6 @@ class TestCallbacks(unittest.TestCase): self.assertEqual(res[0], 5) self.assertAlmostEqual(res[1], 42.0) - @unittest.expectedFailure def test_return_and_multiple_out_arg(self): def cb(): return (5, 42, -1000) @@ -1477,6 +1473,26 @@ class TestEnum(unittest.TestCase): self.assertTrue(hasattr(GIMarshallingTests.Enum, "VALUE1")) self.assertRaises(AttributeError, getattr, GIMarshallingTests.SecondEnum, "VALUE1") + def test_enum_gtype_name_is_namespaced(self): + self.assertEqual(GIMarshallingTests.Enum.__gtype__.name, + 'GIMarshallingTestsEnum') + + def test_enum_double_registration_error(self): + # a warning is printed for double registration and pygobject will + # also raise a RuntimeError. + old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR) + try: + self.assertRaises(RuntimeError, + gi._gi.enum_register_new_gtype_and_add, + GIMarshallingTests.Enum.__info__) + finally: + GLib.log_set_always_fatal(old_mask) + + def test_enum_add_type_error(self): + self.assertRaises(TypeError, + gi._gi.enum_add, + GIMarshallingTests.NoTypeFlags.__gtype__) + class TestGEnum(unittest.TestCase): @@ -1609,6 +1625,21 @@ class TestNoTypeFlags(unittest.TestCase): self.assertTrue(isinstance(flags, GIMarshallingTests.NoTypeFlags)) self.assertEqual(flags, GIMarshallingTests.NoTypeFlags.VALUE1) + def test_flags_gtype_name_is_namespaced(self): + self.assertEqual(GIMarshallingTests.NoTypeFlags.__gtype__.name, + 'GIMarshallingTestsNoTypeFlags') + + def test_flags_double_registration_error(self): + # a warning is printed for double registration and pygobject will + # also raise a RuntimeError. + old_mask = GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_ERROR) + try: + self.assertRaises(RuntimeError, + gi._gi.flags_register_new_gtype_and_add, + GIMarshallingTests.NoTypeFlags.__info__) + finally: + GLib.log_set_always_fatal(old_mask) + class TestStructure(unittest.TestCase): @@ -1704,6 +1735,8 @@ class TestStructure(unittest.TestCase): del struct + @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'), + 'too old gobject-introspection') def test_boxed_struct(self): self.assertTrue(issubclass(GIMarshallingTests.BoxedStruct, GObject.GBoxed)) @@ -1711,30 +1744,44 @@ class TestStructure(unittest.TestCase): self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(0, struct.long_) + self.assertEqual(None, struct.string_) self.assertEqual([], struct.g_strv) del struct + @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'), + 'too old gobject-introspection') def test_boxed_struct_new(self): struct = GIMarshallingTests.BoxedStruct.new() self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct)) + self.assertEqual(struct.long_, 0) + self.assertEqual(struct.string_, None) del struct + @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'), + 'too old gobject-introspection') def test_boxed_struct_copy(self): struct = GIMarshallingTests.BoxedStruct() + struct.long_ = 42 + struct.string_ = 'hello' new_struct = struct.copy() self.assertTrue(isinstance(new_struct, GIMarshallingTests.BoxedStruct)) + self.assertEqual(new_struct.long_, 42) + self.assertEqual(new_struct.string_, 'hello') del new_struct del struct + @unittest.skipUnless(hasattr(GIMarshallingTests.BoxedStruct, 'string_'), + 'too old gobject-introspection') def test_boxed_struct_return(self): struct = GIMarshallingTests.boxed_struct_returnv() self.assertTrue(isinstance(struct, GIMarshallingTests.BoxedStruct)) self.assertEqual(42, struct.long_) + self.assertEqual('hello', struct.string_) self.assertEqual(['0', '1', '2'], struct.g_strv) del struct @@ -1767,6 +1814,14 @@ class TestStructure(unittest.TestCase): del in_struct del out_struct + def test_struct_field_assignment(self): + struct = GIMarshallingTests.BoxedStruct() + + struct.long_ = 42 + struct.string_ = 'hello' + self.assertEqual(struct.long_, 42) + self.assertEqual(struct.string_, 'hello') + def test_union(self): union = GIMarshallingTests.Union() @@ -2442,6 +2497,15 @@ class TestGErrorReturn(unittest.TestCase): class TestParamSpec(unittest.TestCase): + # https://bugzilla.gnome.org/show_bug.cgi?id=682355 + @unittest.skipUnless(hasattr(GIMarshallingTests, 'param_spec_in_bool'), + 'too old gobject-introspection') + @unittest.expectedFailure + def test_param_spec_in_bool(self): + ps = GObject.param_spec_boolean('mybool', 'test-bool', 'boolblurb', + True, GObject.ParamFlags.READABLE) + GIMarshallingTests.param_spec_in_bool(ps) + def test_param_spec_return(self): obj = GIMarshallingTests.param_spec_return() self.assertEqual(obj.name, 'test-param') @@ -2528,18 +2592,10 @@ class TestPropertiesObject(unittest.TestCase): obj = GIMarshallingTests.PropertiesObject(some_boolean=True) self.assertEqual(obj.props.some_boolean, True) - @unittest.expectedFailure def test_char(self): - # gobject-introspection thinks it has a guint8 type tag, which is - # wrong; this will raise an assertion critical which we need to ignore - old_mask = GLib.log_set_always_fatal( - GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_ERROR) - try: - self.assertEqual(self.obj.props.some_char, 0) - self.obj.props.some_char = GObject.G_MAXINT8 - self.assertEqual(self.obj.props.some_char, GObject.G_MAXINT8) - finally: - GLib.log_set_always_fatal(old_mask) + self.assertEqual(self.obj.props.some_char, 0) + self.obj.props.some_char = GObject.G_MAXINT8 + self.assertEqual(self.obj.props.some_char, GObject.G_MAXINT8) obj = GIMarshallingTests.PropertiesObject(some_char=-42) self.assertEqual(obj.props.some_char, -42) @@ -2686,6 +2742,27 @@ class TestPropertiesObject(unittest.TestCase): obj = GIMarshallingTests.PropertiesObject(some_boxed_struct=struct1) self.assertEqual(obj.props.some_boxed_struct.long_, 1) + @unittest.skipUnless(hasattr(GIMarshallingTests.PropertiesObject, 'some_boxed_glist'), + 'too old gobject-introspection') + def test_boxed_glist(self): + self.assertEqual(self.obj.props.some_boxed_glist, []) + + l = [GObject.G_MININT, 42, GObject.G_MAXINT] + self.obj.props.some_boxed_glist = l + self.assertEqual(self.obj.props.some_boxed_glist, l) + self.obj.props.some_boxed_glist = [] + self.assertEqual(self.obj.props.some_boxed_glist, []) + + self.assertRaises(TypeError, setattr, self.obj.props, 'some_boxed_glist', 1) + self.assertRaises(TypeError, setattr, self.obj.props, 'some_boxed_glist', 'foo') + self.assertRaises(TypeError, setattr, self.obj.props, 'some_boxed_glist', ['a']) + + @unittest.expectedFailure + def test_boxed_glist_ctor(self): + l = [GObject.G_MININT, 42, GObject.G_MAXINT] + obj = GIMarshallingTests.PropertiesObject(some_boxed_glist=l) + self.assertEqual(obj.props.some_boxed_glist, l) + @unittest.skipUnless(hasattr(GIMarshallingTests.PropertiesObject, 'some_variant'), 'too old gobject-introspection') def test_variant(self): diff --git a/tests/test_overrides_gio.py b/tests/test_gio.py index 10d634e..942ee00 100644 --- a/tests/test_overrides_gio.py +++ b/tests/test_gio.py @@ -119,3 +119,67 @@ class TestGSettings(unittest.TestCase): self.assertEqual(len(empty), 0) self.assertEqual(bool(empty), True) self.assertEqual(empty.keys(), []) + + +class TestGFile(unittest.TestCase): + def setUp(self): + self.file, self.io_stream = Gio.File.new_tmp('TestGFile.XXXXXX') + + def tearDown(self): + try: + self.file.delete(None) + # test_delete and test_delete_async already remove it + except GLib.GError: + pass + + def test_replace_contents(self): + content = b'hello\0world\x7F!' + succ, etag = self.file.replace_contents(content, None, False, + Gio.FileCreateFlags.NONE, None) + new_succ, new_content, new_etag = self.file.load_contents(None) + + self.assertTrue(succ) + self.assertTrue(new_succ) + self.assertEqual(etag, new_etag) + self.assertEqual(content, new_content) + + # https://bugzilla.gnome.org/show_bug.cgi?id=690525 + def disabled_test_replace_contents_async(self): + content = b''.join(bytes(chr(i), 'utf-8') for i in range(128)) + + def callback(f, result, d): + # Quit so in case of failed assertations loop doesn't keep running. + main_loop.quit() + succ, etag = self.file.replace_contents_finish(result) + new_succ, new_content, new_etag = self.file.load_contents(None) + d['succ'], d['etag'] = self.file.replace_contents_finish(result) + load = self.file.load_contents(None) + d['new_succ'], d['new_content'], d['new_etag'] = load + + data = {} + self.file.replace_contents_async(content, None, False, + Gio.FileCreateFlags.NONE, None, + callback, data) + main_loop = GLib.MainLoop() + main_loop.run() + self.assertTrue(data['succ']) + self.assertTrue(data['new_succ']) + self.assertEqual(data['etag'], data['new_etag']) + self.assertEqual(content, data['new_content']) + + def test_tmp_exists(self): + # A simple test to check if Gio.File.new_tmp is working correctly. + self.assertTrue(self.file.query_exists(None)) + + def test_delete(self): + self.file.delete(None) + self.assertFalse(self.file.query_exists(None)) + + def test_delete_async(self): + def callback(f, result, data): + main_loop.quit() + + self.file.delete_async(0, None, callback, None) + main_loop = GLib.MainLoop() + main_loop.run() + self.assertFalse(self.file.query_exists(None)) diff --git a/tests/test_gobject.py b/tests/test_gobject.py index 99f471b..9b4f5f7 100644 --- a/tests/test_gobject.py +++ b/tests/test_gobject.py @@ -5,7 +5,7 @@ import gc import unittest import warnings -from gi.repository import GObject +from gi.repository import GObject, GLib from gi import PyGIDeprecationWarning from gi.module import get_introspection_module from gi._gobject import _gobject @@ -491,19 +491,27 @@ class TestPropertyBindings(unittest.TestCase): self.assertEqual(self.target.int_prop, 1) def test_transform_bidirectional(self): + test_data = object() + def transform_to(binding, value, user_data=None): - self.assertEqual(user_data, 'test-data') + self.assertEqual(user_data, test_data) return value * 2 def transform_from(binding, value, user_data=None): - self.assertEqual(user_data, 'test-data') - return value / 2 + self.assertEqual(user_data, test_data) + return value // 2 + + test_data_ref_count = sys.getrefcount(test_data) + transform_to_ref_count = sys.getrefcount(transform_to) + transform_from_ref_count = sys.getrefcount(transform_from) # bidirectional bindings binding = self.source.bind_property('int_prop', self.target, 'int_prop', GObject.BindingFlags.BIDIRECTIONAL, - transform_to, transform_from, 'test-data') + transform_to, transform_from, test_data) binding = binding # PyFlakes + binding_ref_count = sys.getrefcount(binding()) + binding_gref_count = binding().__grefcount__ self.source.int_prop = 1 self.assertEqual(self.source.int_prop, 1) @@ -513,6 +521,30 @@ class TestPropertyBindings(unittest.TestCase): self.assertEqual(self.source.int_prop, 2) self.assertEqual(self.target.int_prop, 4) + self.assertEqual(sys.getrefcount(binding()), binding_ref_count) + self.assertEqual(binding().__grefcount__, binding_gref_count) + + # test_data ref count increases by 2, once for each callback. + self.assertEqual(sys.getrefcount(test_data), test_data_ref_count + 2) + self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count + 1) + self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count + 1) + + # Unbind should clear out the binding and its transforms + binding.unbind() + self.assertEqual(binding(), None) + del binding + gc.collect() + + # Setting source or target should not change the other. + self.target.int_prop = 3 + self.source.int_prop = 5 + self.assertEqual(self.target.int_prop, 3) + self.assertEqual(self.source.int_prop, 5) + + self.assertEqual(sys.getrefcount(test_data), test_data_ref_count) + self.assertEqual(sys.getrefcount(transform_to), transform_to_ref_count) + self.assertEqual(sys.getrefcount(transform_from), transform_from_ref_count) + def test_explicit_unbind_clears_connection(self): self.assertEqual(self.source.int_prop, 0) self.assertEqual(self.target.int_prop, 0) @@ -563,5 +595,50 @@ class TestPropertyBindings(unittest.TestCase): self.assertEqual(ref(), None) self.assertEqual(binding(), None) + +class TestGValue(unittest.TestCase): + def test_no_type(self): + value = GObject.Value() + self.assertEqual(value.g_type, GObject.TYPE_INVALID) + self.assertRaises(TypeError, value.set_value, 23) + self.assertEqual(value.get_value(), None) + + def test_int(self): + value = GObject.Value(GObject.TYPE_UINT) + self.assertEqual(value.g_type, GObject.TYPE_UINT) + value.set_value(23) + self.assertEqual(value.get_value(), 23) + value.set_value(42.0) + self.assertEqual(value.get_value(), 42) + + def test_string(self): + value = GObject.Value(str, 'foo_bar') + self.assertEqual(value.g_type, GObject.TYPE_STRING) + self.assertEqual(value.get_value(), 'foo_bar') + + def test_float(self): + # python float is G_TYPE_DOUBLE + value = GObject.Value(float, 23.4) + self.assertEqual(value.g_type, GObject.TYPE_DOUBLE) + + value = GObject.Value(GObject.TYPE_FLOAT, 23.4) + self.assertEqual(value.g_type, GObject.TYPE_FLOAT) + self.assertRaises(TypeError, value.set_value, 'string') + + def test_enum(self): + value = GObject.Value(GLib.FileError, GLib.FileError.FAILED) + self.assertEqual(value.get_value(), GLib.FileError.FAILED) + + def test_flags(self): + value = GObject.Value(GLib.IOFlags, GLib.IOFlags.IS_READABLE) + self.assertEqual(value.get_value(), GLib.IOFlags.IS_READABLE) + + def test_object(self): + class TestObject(GObject.Object): + pass + obj = TestObject() + value = GObject.Value(GObject.TYPE_OBJECT, obj) + self.assertEqual(value.get_value(), obj) + if __name__ == '__main__': unittest.main() diff --git a/tests/test_gtype.py b/tests/test_gtype.py index dec716e..8099101 100644 --- a/tests/test_gtype.py +++ b/tests/test_gtype.py @@ -37,15 +37,13 @@ class TestTypeModuleLevelFunctions(unittest.TestCase): self.assertRaises(TypeError, GObject.type_is_a, 1, 2) def test_type_children(self): - self.assertSequenceEqual(GObject.type_children(CustomBase), - [CustomChild.__gtype__]) + self.assertEqual(GObject.type_children(CustomBase), [CustomChild.__gtype__]) self.assertEqual(len(GObject.type_children(CustomChild)), 0) def test_type_interfaces(self): self.assertEqual(len(GObject.type_interfaces(CustomBase)), 0) self.assertEqual(len(GObject.type_interfaces(CustomChild)), 1) - self.assertSequenceEqual(GObject.type_interfaces(CustomChild), - [GIMarshallingTests.Interface.__gtype__]) + self.assertEqual(GObject.type_interfaces(CustomChild), [GIMarshallingTests.Interface.__gtype__]) def test_type_parent(self): self.assertEqual(GObject.type_parent(CustomChild), CustomBase.__gtype__) diff --git a/tests/test_overrides_gtk.py b/tests/test_overrides_gtk.py index 7ed8344..d429d4d 100644 --- a/tests/test_overrides_gtk.py +++ b/tests/test_overrides_gtk.py @@ -1,4 +1,5 @@ # -*- Mode: Python; py-indent-offset: 4 -*- +# coding: UTF-8 # vim: tabstop=4 shiftwidth=4 expandtab import unittest @@ -114,6 +115,12 @@ class TestGtk(unittest.TestCase): self.assertEqual(ag, groups[-2]) self.assertEqual(ag2, groups[-1]) + def test_uimanager_nonascii(self): + ui = Gtk.UIManager() + ui.add_ui_from_string(b'<ui><menubar name="menub\xc3\xa6r1" /></ui>'.decode('UTF-8')) + mi = ui.get_widget("/menubær1") + self.assertEqual(type(mi), Gtk.MenuBar) + def test_builder(self): self.assertEqual(Gtk.Builder, gi.overrides.Gtk.Builder) @@ -1300,7 +1307,53 @@ class TestTreeModel(unittest.TestCase): def set_row3(): model[0][:2] = ("0", 0) - self.assertRaises(ValueError, set_row3) + self.assertRaises(TypeError, set_row3) + + def test_tree_model_set_value_to_none(self): + # Tests allowing the usage of None to set an empty value on a model. + store = Gtk.ListStore(str) + row = store.append(['test']) + self.assertSequenceEqual(store[0][:], ['test']) + store.set_value(row, 0, None) + self.assertSequenceEqual(store[0][:], [None]) + + def test_signal_emission_tree_path_coerce(self): + class Model(GObject.Object, Gtk.TreeModel): + pass + + model = Model() + tree_paths = [] + + def on_any_signal(model, path, *args): + tree_paths.append(path.to_string()) + + model.connect('row-changed', on_any_signal) + model.connect('row-deleted', on_any_signal) + model.connect('row-has-child-toggled', on_any_signal) + model.connect('row-inserted', on_any_signal) + + model.row_changed('0', Gtk.TreeIter()) + self.assertEqual(tree_paths[-1], '0') + + model.row_deleted('1') + self.assertEqual(tree_paths[-1], '1') + + model.row_has_child_toggled('2', Gtk.TreeIter()) + self.assertEqual(tree_paths[-1], '2') + + model.row_inserted('3', Gtk.TreeIter()) + self.assertEqual(tree_paths[-1], '3') + + def test_tree_model_filter(self): + model = Gtk.ListStore(int, str, float) + model.append([1, "one", -0.1]) + model.append([2, "two", -0.2]) + + filtered = Gtk.TreeModelFilter(child_model=model) + + self.assertEqual(filtered[0][1], 'one') + filtered[0][1] = 'ONE' + self.assertEqual(filtered[0][1], 'ONE') @unittest.skipUnless(Gtk, 'Gtk not available') diff --git a/tests/test_properties.py b/tests/test_properties.py index fe286e2..d19970f 100644 --- a/tests/test_properties.py +++ b/tests/test_properties.py @@ -541,6 +541,24 @@ class TestProperty(unittest.TestCase): self.assertEqual(o.value, 'blah') self.assertEqual(o.props.value, 'blah') + def test_decorator_private_setter(self): + class C(GObject.GObject): + _value = 'value' + + @GObject.Property + def value(self): + return self._value + + @value.setter + def _set_value(self, value): + self._value = value + + o = C() + self.assertEqual(o.value, 'value') + o.value = 'blah' + self.assertEqual(o.value, 'blah') + self.assertEqual(o.props.value, 'blah') + def test_decorator_with_call(self): class C(GObject.GObject): _value = 1 diff --git a/tests/test_signal.py b/tests/test_signal.py index fc8c835..8f31c35 100644 --- a/tests/test_signal.py +++ b/tests/test_signal.py @@ -362,6 +362,7 @@ class CM(GObject.GObject): test_string=(GObject.SignalFlags.RUN_LAST, str, (str,)), test_object=(GObject.SignalFlags.RUN_LAST, object, (object,)), test_paramspec=(GObject.SignalFlags.RUN_LAST, GObject.ParamSpec, ()), + test_paramspec_in=(GObject.SignalFlags.RUN_LAST, GObject.ParamSpec, (GObject.ParamSpec, )), test_gvalue=(GObject.SignalFlags.RUN_LAST, GObject.Value, (GObject.Value,)), test_gvalue_ret=(GObject.SignalFlags.RUN_LAST, GObject.Value, (GObject.TYPE_GTYPE,)), ) @@ -418,6 +419,17 @@ class _TestCMarshaller: self.assertEqual(rv.name, "test-param") self.assertEqual(rv.nick, "test") + @unittest.skipUnless(hasattr(GObject, 'param_spec_boolean'), + 'too old gobject-introspection') + def test_paramspec_in(self): + rv = GObject.param_spec_boolean('mybool', 'test-bool', 'do something', + True, GObject.ParamFlags.READABLE) + + rv2 = self.obj.emit("test-paramspec-in", rv) + self.assertEqual(type(rv), type(rv2)) + self.assertEqual(rv2.name, "mybool") + self.assertEqual(rv2.nick, "test-bool") + def test_C_paramspec(self): self.notify_called = False @@ -436,9 +448,7 @@ class _TestCMarshaller: self.assertEqual(rv, 42) # explicit float - v = GObject.Value() - v.init(GObject.TYPE_FLOAT) - v.set_float(1.234) + v = GObject.Value(GObject.TYPE_FLOAT, 1.234) rv = self.obj.emit("test-gvalue", v) self.assertAlmostEqual(rv, 1.234, 4) @@ -447,9 +457,7 @@ class _TestCMarshaller: self.assertAlmostEqual(rv, 1.234, 4) # explicit int64 - v = GObject.Value() - v.init(GObject.TYPE_INT64) - v.set_int64(GObject.G_MAXINT64) + v = GObject.Value(GObject.TYPE_INT64, GObject.G_MAXINT64) rv = self.obj.emit("test-gvalue", v) self.assertEqual(rv, GObject.G_MAXINT64) @@ -459,9 +467,7 @@ class _TestCMarshaller: #self.assertEqual(rv, GObject.G_MAXINT64) # explicit uint64 - v = GObject.Value() - v.init(GObject.TYPE_UINT64) - v.set_uint64(GObject.G_MAXUINT64) + v = GObject.Value(GObject.TYPE_UINT64, GObject.G_MAXUINT64) rv = self.obj.emit("test-gvalue", v) self.assertEqual(rv, GObject.G_MAXUINT64) @@ -794,11 +800,9 @@ class TestSignalModuleLevelFunctions(unittest.TestCase): my_signal_expected_query_result = [my_signal_id, 'my-signal', C.__gtype__, 1, GObject.TYPE_NONE, (GObject.TYPE_INT,)] # signal_query(name, type) - self.assertSequenceEqual(GObject.signal_query('my-signal', C), - my_signal_expected_query_result) + self.assertEqual(list(GObject.signal_query('my-signal', C)), my_signal_expected_query_result) # signal_query(signal_id) - self.assertSequenceEqual(GObject.signal_query(my_signal_id), - my_signal_expected_query_result) + self.assertEqual(list(GObject.signal_query(my_signal_id)), my_signal_expected_query_result) # invalid query returns None instead of raising self.assertEqual(GObject.signal_query(0), None) self.assertEqual(GObject.signal_query('NOT_A_SIGNAL', C), diff --git a/tests/testhelpermodule.c b/tests/testhelpermodule.c index 16bb39e..9ca82bc 100644 --- a/tests/testhelpermodule.c +++ b/tests/testhelpermodule.c @@ -402,6 +402,15 @@ test_gvalue_ret_callback (GObject *object, GType type) return ret; } +static GParamSpec * +test_paramspec_in_callback (GObject *object, GParamSpec *p) +{ + g_return_val_if_fail (G_IS_OBJECT (object), NULL); + g_return_val_if_fail (G_IS_PARAM_SPEC (p), NULL); + + return p; +} + static void connectcallbacks (GObject *object) { @@ -460,6 +469,10 @@ connectcallbacks (GObject *object) "test_gvalue_ret", G_CALLBACK (test_gvalue_ret_callback), NULL); + g_signal_connect (G_OBJECT (object), + "test_paramspec_in", + G_CALLBACK (test_paramspec_in_callback), + NULL); } static PyObject * @@ -530,7 +543,6 @@ _wrap_test_gerror_exception(PyObject *self, PyObject *args) return NULL; } - Py_DECREF(py_method); Py_DECREF(py_args); Py_DECREF(py_ret); |