GNOME Bugzilla – Bug 791443
Incorrect GIR annotation for Gtk.TextBufferSerializeFunc return value
Last modified: 2018-05-02 19:35:43 UTC
The issue is the return value of the Gtk.TextBufferSerializeFunc callback. The return value documented in the C documentation is "a newly-allocated array of guint8 which contains the serialized data, or None if an error occurred". However I found that when using the python bindings, when I return a string I get an error that indicates a single character is expected. (And when I return a single character, a segfault happens.) Digging into the "Gtk.gir" XML annotation I find this definition for the return type: <return-value transfer-ownership="none" nullable="1"> <doc xml:space="preserve">[...]</doc> <type name="guint8" c:type="guint8*"/> </return-value> For comparison I look at the return type of Gtk.Clipboard.wait_for_rich_text() which is also given as "guint8 *" in the documentation and - more importantly - should return the exact same data as the buffer serialization function if when were to do copy paste from a text buffer. <return-value transfer-ownership="full" nullable="1"> <doc xml:space="preserve">[...]</doc> <array length="2" zero-terminated="0" c:type="guint8*"> <type name="guint8" c:type="guint8"/> </array> </return-value> So my hypothesis is that in the annotation something went wrong and the return value of the TextBufferSerializeFunc incorrectly omits the "<array>" part. My naive guess is that changing it to look more like the second blob should work. The following script shows the issue: ############################## import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk mimetype = 'x-test/x-serialize' def serialize_func(rbuffer, cbuffer, start, end, user_data): return b'Test 123' textbuffer = Gtk.TextBuffer() atom = textbuffer.register_serialize_format( mimetype, serialize_func ) textbuffer.set_text('abc') data = "" textbuffer, atom, *textbuffer.get_bounds() ) print('DATA: %r' % data) ############################## what I expect: $ python3 test_serialization.py DATA: b'Test 123' what I get: $ python3 test_serialization.py TypeError: Must be a single character DATA: b'' ---- For reference: Mailing list discussion: https://mail.gnome.org/archives/python-hackers-list/2017-December/msg00000.html
Created attachment 369661 [details] [review] TextBuffer: Fix annotations for SerializeFunc TextBufferRich: Fix annotations for SerializeFunc It was not annotated as returning an array, breaking bindings. In addition, the returned container was not annotated as newly allocated, and the output parameter for its length was not annotated as output.
Created attachment 369670 [details] [review] TextBuffer: Fix annotations for SerializeFunc updated to use (transfer full) as serialize() does, and make its return nullable It was not annotated as returning an array, breaking bindings. In addition, the returned container was not annotated as newly allocated, and the output parameter for its length was not annotated as output. Also, gtk_text_buffer_serialize() did not annotate its return as nullable, but that necessarily must be possible if the SerializeFunc can return NULL. Another possible cause of NULL is if the @format is not found, but for now, I just leave that lumped under "an error occurred".
Is anyone else, who uses GI with Python anything more than trivially, able to build with this patch and ensure they test it properly? I don't know if I am. After rebuilding GTK+ with my patch, and adding the missing > textbuffer.serialize( to the test script above, I get this: > $ LD_LIBRARY_PATH=/opt/jhbuilt/gnome/lib ./test.py > TypeError: serialize_func() missing 1 required positional argument: 'user_data' > DATA: '' So my concern is that either I broke something else in the process, or we're now just revealing something else wrong with the annotations. I don't know if this means I need to build something else, set some other environment variable, or just plain got the patch wrong. So, any pointers? CCing Christoph since he is an expert in all this, and also has often spotted what I did wrong very quickly :P
The annotations change looks good to me, but I also can't get the example to work, might be a pygobject bug: import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk, Gdk mimetype = 'x-test/x-serialize' def serialize_func(*args): return b"foo" textbuffer = Gtk.TextBuffer() atom = textbuffer.register_serialize_format(mimetype, serialize_func) atom = Gdk.atom_intern(mimetype, True) textbuffer.set_text('abc') start, end = textbuffer.get_bounds() exist_atom = Gdk.atom_intern("application/x-gtk-text-buffer-rich-text", True) print(textbuffer.serialize(textbuffer, exist_atom, *textbuffer.get_bounds())) print(textbuffer.serialize(textbuffer, atom, *textbuffer.get_bounds()))
-- GitLab Migration Automatic Message -- This bug has been migrated to GNOME's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gtk/issues/992.