Tips for Python Gtk2 to Gtk3

Today I’ll look at some tips for making a port of a python application using GTK+ 2 to use GTK+ 3.

The first thing you’ll want to do is read over GNOME: Live: PyGObject/IntrospectionPorting. That resource includes a link to pygi-convert.sh, which is a shell script that tries to do a bulk of the menial replacements in your code automatically.

I found that script to do a pretty good job.  It misses some things, such as import lines that include multiple modules, but the only place it made a mistake when I used it was with Gtk.Label, trying to add extra parameters unnecessarily. One thing it did miss was calls to Gtk.pack_{start,end} which now requires padding to be specified.

But this got things to a near-working state.

You’ll want to open a Python shell so you can do some manual inspection of GTK objects. For that you’ll almost definitely want something similar to:

import re
def grep(obj, string=None, insensitive=False):
    obj_dir = dir(obj)
    if string is None:
        print(obj_dir)
    else:
        if insensitive:
            expr = re.compile(string, re.IGNORECASE)
        else:
            expr = re.compile(string)
        for text in obj_dir:
            match = expr.search(text)
            if match is not None:
                print(match.string)
>>> from gi.repository import Gtk
>>> grep(Gtk, 'bar')
HScrollbar
HScrollbarClass
Scrollbar
ScrollbarClass
Statusbar
StatusbarClass
StatusbarPrivate
Toolbar
ToolbarClass
ToolbarPrivate
ToolbarSpaceStyle
ToolbarStyle
VScrollbar
VScrollbarClass
>>> grep(Gtk, 'bar', True)
HScrollbar
HScrollbarClass
InfoBar
InfoBarClass
InfoBarPrivate
MenuBar
MenuBarClass
MenuBarPrivate
ProgressBar
ProgressBarClass
ProgressBarPrivate
STYLE_CLASS_INLINE_TOOLBAR
STYLE_CLASS_MENUBAR
STYLE_CLASS_PRIMARY_TOOLBAR
STYLE_CLASS_PROGRESSBAR
STYLE_CLASS_SCROLLBAR
STYLE_CLASS_SIDEBAR
STYLE_CLASS_TOOLBAR
Scrollbar
ScrollbarClass
Statusbar
StatusbarClass
StatusbarPrivate
Toolbar
ToolbarClass
ToolbarPrivate
ToolbarSpaceStyle
ToolbarStyle
VScrollbar
VScrollbarClass

This will make your life easier, as often looking in the same object, the name of a function has changed, and it can be faster than consulting the online documentation (though you will probably still have to follow up with that, if the signature has changed).

For the online documentation, the main resource you’ll use is the GNOME Developers: GTK+ 3 Reference Manual, as Google Search and other search engines tend to have a lot of GTK+ 2 cruft sitting there to waste your time. But there’s also a promising bit of work at ReadTheDocs.org: The Python GTK+ 3 Tutorial. While it’s brief as of this writing, it’s a decent, hardworking resource, very clean, etc.

You’ll also want to do a grep -rn 'except:' [path] or possible a more sophisticated alternative to find out where in the code you are working with are exceptions being handled. This is especially useful if what you’ll find is:

try:
    foo()
except:
    pass

Those are the worst, you’re wondering why something isn’t working, when it turns out that foo() isn’t being allowed to tattle. Censorship sucks, even in code. Python needs whistleblower protection! Don’t let them silence your flaws, it will come back to bite you in the ass.

One place where things have changed and maybe are still changing that I noticed was GdkPixbuf and other graphics-related things. These are moving toward cairo. In those cases you’ll need to dig into the pycairo docs as well, but chances are you won’t have to go too deep or the component you’re working with would’ve been written calling cairo from the start.

Another thing to remember is that the way the original developers did it may have been due to earlier versions of GTK+ not supporting something it now supports. In those cases, you can save yourself some trouble if you can realize that and make the change.