GNOME Bugzilla – Bug 665050
Old static bindings API presented through gi API
Last modified: 2013-01-08 15:32:04 UTC
It seems that when importing GLib or GObject from gi.repository, some of the old static bindings API is still exposed, though undocumented, and inconsistent with the introspected API. This doesn't seem like it should be the case, and magically makes some code continue to work, even when it really shouldn't.
It is exposed on purpose. Much of that functionality is needed as a foundation for GI. At that low level there is some glue that introspection itself can't handle. If there is some API that you wish removed that isn't needed please file bugs for those specifically and we can start to deprecate them if possible.
Well, there are IOChannel watch conditions as GObject.IO_HUP still, though the gir API exposes these as GLib.IOCondition.HUP for example. Also, there is an io_add_watch() function exposed on both which takes an fd and wraps it in a GIOChannel internally, to signal a callback on specified conditions. This API is inconsistent with the actual GIOChannel API, which is currently marked as introspectable="0" in the gir. I came across this while working on porting Twisted reactor integration with the main loop to the gir-based APIs.
GIO API is pretty borked when it comes to introspection in some places. GObject.IO_HUP == GLib.IOCondition.HUP as far as the integer value goes so you can use them interchangeably. We could make that a property and have it throw a deprecation warning. There are a number of places where this happens. You need to use g_io_add_watch_full though I guess we should annotate that as Rename: g_io_add_watch in GLib. Please file a bug with GLib for that one. As far as getting rid of the current io_add_watch, I'm all for that though I have little time. It has to be done in a way that doesn't break ABI. Patches welcome. I'll review it if I see it.
How does one remove API and avoid breaking ABI exactly, particularly in Python, where neither standard of stability really holds true. I don't think anything would actually *link* to the C extensions directly, would they? That would be quite odd.
Well there are cases such as libpeas which link directly into pygobject to provide plugin support. So what I mean by not breaking ABI would be to make sure the API struct doesn't change positions for any of the member functions. I'm not sure if the GIO bindings fall in this trap but the main GObject methods do. What we want to avoid is having libpeas from having to be recompiled. e.g. I think something like this might be in order: - { "add_watch", (PyCFunction)py_io_channel_add_watch, METH_VARARGS|METH_KEYWORDS } + { "add_watch_DEPRECATED", (PyCFunction)py_io_channel_add_watch, METH_VARARGS|METH_KEYWORDS } but then again it doesn't look like that is public so it might not be a big deal. I think the issue is more to do with the _PyGObject_API struct. In that case just remove the API and test against a previously compiled GEdit with python plugins turned on. Also when changing annotations for GLib you need to update it in gobject-introspection also which is done to avoid circular dependency issues. Ask Colin Walters in #introspection how to do that.
These aren't GIO APIs. They are GLib APIs (GIOChannel is from way before GIO existed even). Looking at the libpeas python loader build, it doesn't look like it links directly to the _gobject.so, but rather depends on gobject being loaded via its use of Python? So I don't expect there should be any problems. The API in question isn't exposed in pygobject.h either. I'll cook up a patch for this probably tomorrow and test it with various libpeas-using things here. Thanks. I'll also file a separate bug for glib annotations soon.
The problem with ABI has to do with linking to the header file. For some reason python APIs are exposed to linking libraries in a very fragile way but as I said that has mostly to do with the _PyGObject_API struct. One thing I was thinking is if we remove the current add_watch functionality is there a way to pass a python file descriptor to a watch or do we just make people load file descriptors through glib? In that case those code paths need to be checked to make sure they are Introspectable.
Current pygobject 3.7.x removes most of the static glib bindings, and with it its exposure. It provides deprecated backwards compatibility overrides, which we will remove in a cycle or two, in particular for the things you mentioned here: (In reply to comment #2) > Well, there are IOChannel watch conditions as GObject.IO_HUP still, though the > gir API exposes these as GLib.IOCondition.HUP for example. GObject.IO_HUP is now just an alias for GLib.IOCondition.HUP (and likewise for all other constants which were previously defined in the static bindings). > Also, there is an io_add_watch() function exposed on both which takes an fd and > wraps it in a GIOChannel internally, to signal a callback on specified > conditions. This API is inconsistent with the actual GIOChannel API, which is > currently marked as introspectable="0" in the gir. pygobject 3.7.x now exposes the real API for GLib.io_add_watch() and child_watch_add(), and provides backwards compatible overrides for the old calling convention. I think this solves the issue up to the degree of providing the real GLib API and not exposing internal static binding stuff.