Summary: | switching from pygobject2 to pygi in 1.0 was an incompatible change | ||
---|---|---|---|
Product: | dbus | Reporter: | Alan <alanjas> |
Component: | python | Assignee: | Simon McVittie <smcv> |
Status: | RESOLVED FIXED | QA Contact: | John (J5) Palmieri <johnp> |
Severity: | normal | ||
Priority: | medium | CC: | barry, sklist |
Version: | 1.0.x | ||
Hardware: | x86 (IA32) | ||
OS: | Linux (All) | ||
Whiteboard: | |||
i915 platform: | i915 features: | ||
Attachments: | Log of the error |
dbus-python and PyGObject introspection are not compatible with each other. It looks like TurtleActivity needs to be ported. PyGObject Introspection has its own dbus interface. This bug should be filed on Sugar. It is not PyGObject or dbus-python bug. (In reply to comment #1) > dbus-python and PyGObject introspection are not compatible with each other. Actually... Barry Warsaw ported dbus.gobject_service from gobject (PyGObject 2) to gi.repository.GObject (PyGObject 3) so that it could support Python 3. I hadn't realised this would be an incompatible change for projects using gobject... Barry, any ideas? It is because it is two different python type systems clashing with each other over the same namespace. So you are never sure if you are getting the static gobject or the dynamicly generated gobject for a given class name. (In reply to comment #3) > It is because it is two different python type systems clashing with each other > over the same namespace. So you are never sure if you are getting the static > gobject or the dynamicly generated gobject for a given class name. The problem is the alias? (... as gobject) You will need a ported version of Sugar.Activity. I thought that was already ported and running in parallel. As long as the GObject and gobject stuff isn't running in the same python interpreter they can happily run side by side in different apps. Also to not surprise other apps using the dbus.gobject_service I would suggest changing the name so that you can keep the older apps working while you port everything over. (In reply to comment #6) > Also to not surprise other apps using the dbus.gobject_service I would suggest > changing the name so that you can keep the older apps working while you port > everything over. It's a bit late for that; there has been a release (1.0, back in January) in which d.g_s uses PyGI, so the only options seem to be: * revert it (breaking any Python 2 PyGI apps that use d.g_s in dbus-python 1.0), add a d.pygobject3_service which uses PyGI, and make d.g_s import that instead if run under Python 3 * declare that yes, it has changed incompatibly, and apps have to deal with it Opinions? I'd really like to hear Barry's thoughts on this, since he made this change in the first place. (In reply to comment #4) > The problem is the alias? (... as gobject) No, the problem is that if any module in an application imports gobject (PyGObject 2), that application must not also import gi.repository.GObject (PyGObject 3), and vice versa. In dbus-python 1.0, dbus.gobject_service changed from using gobject to using gi.repository.GObject. I didn't realise at the time that this was an incompatible change. The reason we changed was so that pygobject2 could be parallel installed with pygobject3 (for PyGTK+ support) and we could fix a slew of ref counting bugs (and others) that couldn't be fixed without breaking ABI (and breaking PyGTK+). I suggest you just port them all. If they don't rely on PyGTK+ then all you have to do is search and replace all 'import gobject' with 'from gi.repository import GObject as gobject' (though we frown on aliasing to the lower case gobject). If the app uses PyGTK+ you will have to either port it to PyGObject or remove any libs that import gi.repository.GObject On Apr 20, 2012, at 09:30 AM, bugzilla-daemon@freedesktop.org wrote: >https://bugs.freedesktop.org/show_bug.cgi?id=48904 > >--- Comment #8 from Simon McVittie <simon.mcvittie@collabora.co.uk> 2012-04-20 02:30:10 PDT --- >(In reply to comment #4) >> The problem is the alias? (... as gobject) > >No, the problem is that if any module in an application imports gobject >(PyGObject 2), that application must not also import gi.repository.GObject >(PyGObject 3), and vice versa. > >In dbus-python 1.0, dbus.gobject_service changed from using gobject to using >gi.repository.GObject. I didn't realise at the time that this was an >incompatible change. Yikes, this is an unfortunate backward incompatibility, sorry for that. There are a couple of ways I see to resolve the problem. 1) Punt and require applications using dbus-python 1.0 to port to pygi. This is the cleanest solution from dbus-python's perspective, and you can almost justify this since the change occurred in a major version bump, and from a logically "pre-release" version (i.e. 0 in the first digit) to a 1.0 version. OTOH, dbus-python 0.X has been effectively stable for ages, and it's probably not so nice to all the existing code out there. ;) 2) In dbus/gobject_service.py, check the Python version (via sys.hexversion) and in Python 2, import the real gobject instead of gi.repository.GObject (the alias is not the problem here). I haven't tested it, but I think the rest of the code in the module should work fine. In Python 3, you'd still import gi.repository.GObject as gobject. Pro: only the first import line needs to be changed. Con: I generally don't like version checks, but more importantly, this would prevent Python 2 applications from using pygi, and I think we should encourage everyone to port to pygi for both Python 2 and Python 3. 3) As Simon suggested, revert gobject_service.py and add a new module that gi applications would import instead. I'd probably call it gi_service.py instead of pyobject3_service, since it better implies that both Python 2 and Python 3 apps using pygi can benefit from this. 4) Similar to #3, leave gobject_service.py alone and reinstate the old version of the module as gobject2_service.py. This would still require existing applications to change their code to use the old service, but wouldn't penalize new code which has already adapted to dbus-python 1.0. Other thoughts I have just keep getting uglier so I'll keep them to myself. ;) My preference in order would be #1, #4, #3, #2. This possible hack occurs to me: if 'gobject' in sys.modules: import gobject else: from gi.repository import GObject as gobject or maybe a more conservative version: if 'gi.repository.GObject' in sys.modules: from gi.repository import GObject as gobject elif 'gobject' in sys.modules: import gobject else: raise ImportError('must import either gi.repository.GObject or gobject before importing dbus.gobject_service') Affected packages in Debian unstable (determined by grepping for gobject_service in packages that depend on python-dbus, so not necessarily 100% accurate): dragbox gst-qa-system kupfer sugar-browse-activity-0.84 sugar-browse-activity-0.86 sugar-presence-service-0.84 sugar-presence-service-0.86 sugar-presence-service-0.88 sugar-presence-service-0.90 (No, I don't know why we have four separate versions of the Presence Service. I'm off to file some bugs...) On Apr 20, 2012, at 05:55 PM, bugzilla-daemon@freedesktop.org wrote: >This possible hack occurs to me: > >if 'gobject' in sys.modules: > import gobject >else: > from gi.repository import GObject as gobject > >or maybe a more conservative version: > >if 'gi.repository.GObject' in sys.modules: > from gi.repository import GObject as gobject >elif 'gobject' in sys.modules: > import gobject >else: > raise ImportError('must import either gi.repository.GObject or gobject >before importing dbus.gobject_service') It's a hack, but maybe not an unreasonable one. If you go with the second approach, why not just check for 'gi' in sys.modules? The hack can probably be subverted, though I can't think of how that could be done in a naive way (i.e. you'd probably have to deliberately do something weird). >Affected packages in Debian unstable (determined by grepping for >gobject_service in packages that depend on python-dbus, so not necessarily >100% accurate): > >dragbox >gst-qa-system >kupfer >sugar-browse-activity-0.84 >sugar-browse-activity-0.86 >sugar-presence-service-0.84 >sugar-presence-service-0.86 >sugar-presence-service-0.88 >sugar-presence-service-0.90 > >(No, I don't know why we have four separate versions of the Presence Service. >I'm off to file some bugs...) So, 5 packages then. Of course that doesn't count anything that's not in Debian, but it's probably a pretty good indication that you could get away with #1 (tell them to port to pygi). On Apr 20, 2012, at 02:14 PM, Barry Warsaw wrote:
>The hack can probably be subverted, though I can't think of how that could be
>done in a naive way (i.e. you'd probably have to deliberately do something
>weird).
Heh, one easy way is to import dbus.gobject_service before you import gi or
gobject.
That hack is generally frowned upon because the error is there to say you have explicitly done something that needs fixing. Why not have the new code simply call a function at the top like sugar.enable_gi(True) or the old code - sugar.enable_gobject_deprecated(True). In fact I like the the deprecated call as it allows authors to see that they are broken and either need to fix their app or acknowledge that they have seen the error and understand what they are doing may not work in future releases. Oh and deprecated should print out a nasty warning stating that this is only a temporary fix. Also with that code you could write a script that outputs a table of apps that have yet to be ported. (In reply to comment #14) > Heh, one easy way is to import dbus.gobject_service before you import gi or > gobject. Right, that's a point in favour of the slightly more conservative version (require importing one of the others first). (In reply to comment #15) > That hack is generally frowned upon because the error is there to say you have > explicitly done something that needs fixing. Why not have the new code simply > call a function at the top like sugar.enable_gi(True) or the old code - > sugar.enable_gobject_deprecated(True). Requiring enable_gi means code that worked correctly with dbus-python 1.0 no longer works (now it has to call that function). Requiring enable_gobject_deprecated means code that worked correctly with dbus-python < 1.0 no longer works (now it has to call that function). We lose either way; if we're going to break existing code, we might as well either revert the change or keep it, rather than adding complexity. On Apr 26, 2012, at 10:29 AM, bugzilla-daemon@freedesktop.org wrote: >https://bugs.freedesktop.org/show_bug.cgi?id=48904 > >--- Comment #17 from Simon McVittie <simon.mcvittie@collabora.co.uk> 2012-04-26 03:29:25 PDT --- >(In reply to comment #14) >> Heh, one easy way is to import dbus.gobject_service before you import gi or >> gobject. > >Right, that's a point in favour of the slightly more conservative version >(require importing one of the others first). > >(In reply to comment #15) >> That hack is generally frowned upon because the error is there to say you have >> explicitly done something that needs fixing. Why not have the new code simply >> call a function at the top like sugar.enable_gi(True) or the old code - >> sugar.enable_gobject_deprecated(True). > >Requiring enable_gi means code that worked correctly with dbus-python 1.0 no >longer works (now it has to call that function). > >Requiring enable_gobject_deprecated means code that worked correctly with >dbus-python < 1.0 no longer works (now it has to call that function). > >We lose either way; if we're going to break existing code, we might as well >either revert the change or keep it, rather than adding complexity. Ultimately, it's your call. My preference would be to favor the gi+dbus1.0 code. The hack seems reasonable though to help much of the existing gobject+dbus<1.0 to get over the porting hump. Here is a proposal. I've pushed an implementation to freedesktop.org git and will release it if there are no objections. In Python 2, we continue to provide dbus.gobject_service. If you have already imported 'gi' it uses gi.repository.GObject (matching 1.0); otherwise, it uses gobject (matching 0.84). Either way, there is a deprecation warning. In Python 3, dbus.gobject_service just doesn't exist (a compatibility break between 1.0 and 1.1, but an acceptable one, IMO). In both Python 2 and 3, we provide dbus.gi_service which is like Barry's version of gobject_service in 1.0, is not deprecated, and uses gi.repository.GObject. ---- From a quick look at the source code of the affected Debian packages (in Debian and, in most cases, upstream), none of them expect to use g-i, so using 1.0 breaks them all immediately, and mostly reverting to 0.84's behaviour seems wisest. On May 02, 2012, at 10:14 AM, bugzilla-daemon@freedesktop.org wrote: >Here is a proposal. I've pushed an implementation to freedesktop.org git and >will release it if there are no objections. > >In Python 2, we continue to provide dbus.gobject_service. If you have already >imported 'gi' it uses gi.repository.GObject (matching 1.0); otherwise, it uses >gobject (matching 0.84). Either way, there is a deprecation warning. > >In Python 3, dbus.gobject_service just doesn't exist (a compatibility break >between 1.0 and 1.1, but an acceptable one, IMO). > >In both Python 2 and 3, we provide dbus.gi_service which is like Barry's >version of gobject_service in 1.0, is not deprecated, and uses >gi.repository.GObject. > >---- > >From a quick look at the source code of the affected Debian packages (in >Debian and, in most cases, upstream), none of them expect to use g-i, so >using 1.0 breaks them all immediately, and mostly reverting to 0.84's >behaviour seems wisest. +1 We'll just have to deal with any breakages from 1.0 to 1.1 as they come. A couple of thoughts from reading over the bug... From comment 9: "The reason we changed was so ... we could fix a slew of ref counting bugs (and others) that couldn't be fixed without breaking ABI (and breaking PyGTK+)" From comment 10: "If they don't rely on PyGTK+ then all you have to do is search and replace all 'import gobject' with 'from gi.repository import GObject as gobject'" Did anyone check if the handful of applications this affects rely on PyGTK+? If they don't then it seems like keeping the current incompatible change provides a technically better solution and it's better to do the trivial porting that's needed (I'd be glad to help with that in Debian). (In reply to comment #21) > Did anyone check if the handful of applications this affects rely on PyGTK+? Dragbox, Kupfer and Browse do. (In reply to comment #21) > If they don't then it seems like keeping the current incompatible change > provides a technically better solution and it's better to do the trivial > porting that's needed (I'd be glad to help with that in Debian). dbus.gobject_service is going to be marked as deprecated in 1.1; when I've released that, you're welcome to port stuff to dbus.gi_service (same API, but not deprecated, and with gi.repository.GObject instead of gobject). OK. Thanks. I guess that takes the easy and move forward option off the table. This was fixed in 1.1.0. |
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.
Created attachment 60290 [details] Log of the error When I use sugar-emulator, activities that uses Dbus give errors like this: Traceback (most recent call last): File "/usr/bin/sugar-activity", line 21, in <module> main.main() File "/usr/lib/python2.7/dist-packages/sugar/activity/main.py", line 121, in main module = __import__(module_name) File "/home/alan/Activities/TurtleBots.activity/TurtleArtActivity.py", line 68, in <module> from TurtleArt.tacollaboration import Collaboration File "/home/alan/Activities/TurtleBots.activity/TurtleArt/tacollaboration.py", line 23, in <module> from dbus.gobject_service import ExportedGObject File "/usr/lib/python2.7/dist-packages/dbus/gobject_service.py", line 27, in <module> from gi.repository import GObject as gobject File "/usr/lib/python2.7/dist-packages/gi/__init__.py", line 23, in <module> from ._gi import _API, Repository ImportError: could not import gobject (error was: ImportError('When using gi.repository you must not import static modules like "gobject". Please change all occurrences of "import gobject" to "from gi.repository import GObject".',))