Interfaces uglier than C

I'm not to happy with what PyGTK does with my interfaces. In C, an implementation of GtkIImageTool looks like this. In Python, it looks like this:

import gobject import gtkimageview class MyTool(gobject.GObject, gtkimageview.IImageTool): def __init__(self): gobject.GObject.__init__(self) self.crosshair = gtk.gdk.Cursor(gtk.gdk.CROSSHAIR) self.cache = gtkimageview.PixbufDrawCache() def do_button_press(self, ev_button): pass def do_button_release(self, ev_button): pass def do_motion_notify(self, ev_motion): pass def do_pixbuf_changed(self, reset_fit, rect): print 'pixbuf changed' def do_paint_image(self, draw_opts, drawable): self.cache.draw(draw_opts, drawable) def do_cursor_at_point(self, x, y): return self.crosshair gobject.type_register(MyTool)

There are quite a few ugly warts here.

class MyTool(gobject.GObject, gtkimageview.IImageTool):

You have to subclass gobject.GObject, which I really would rather not. The whole point of writing programs in Python is to get rid of the stupid, annoying and complicated GObject system. Same for gtkimageview.IImageTool -- this is Python and you have duck-typing. You shouldn't need to subclass anything.

def do_cursor_at_point(self, x, y):

And why does PyGTK decide that all my interface methods should be prefixed with do_? I didn't tell it to do that. It is an extremely unpythonic convention.

gobject.type_register(MyTool)

Yet another GObject-ism. It would be plain simple to get rid of this step by making gobject.GObject a metaclass that registers the class when it is constructed. But no, PyGTK wants to remind you that you really are dealing with a C API and nothing more.

gobject.GObject.__init__(self)

As before, initialization like this shouldn't be needed for a plain Python class.

return self.crosshair

Don't try to return None, PyGTK:s code generator doesn't understand that an interface function can either return an object pointer or NULL.

But worst of all is probably that if you forget to do any of this, then IT WILL CRASH. Don't expect a nice exception, at best you'll get a cryptic GTK warning and a segfault with debug symbols.

PyGTK:s handling of GInterfaces is, as shown, currently very weak. But I expect it to be improved upon in the future. Meanwhile I'm thinking that PyGTK:s wrapping system with definition and override files isn't that good to begin with. It is fairly easy to whip something up fast, but when you want to make your binding pythonic, you run into problems.

I wonder if it wouldn't be possible to use ctypes to create more pythonic bindings with.

Fucking spam filter

GMail's spam filter seems to have gotten worse lately. Lots of "you have won!!! blaha blaha" is getting through and at the same time many non-spam mails to mailing lists are classified as spam. Why should it be so hard for GMail? They could just calculate a hash or check sum for each mail on their servers. Then if more than say 10,000 GMail users receive the exact same mail it must be spam. Problem solved, no?

Why write documentation?

This post is spurred by this blog post and Benjamin Ottes follow up. I'm not complaining on them, I just got the inspiration from their posts. A pet peeve of mine is the low quality of developer documentation available in the free software community and especially the permissive culture around it.

More than once at GUADEC did I hear someone say something along the lines

We have the implementation for our $GREAT_LIBRARY complete and we think you should use it.. But uh, sorry no documentation yet. We suck :)

You're damn right you suck! If you can't be assed to write decent enough documentation, then I can't be assed to use your code. Most often the excuse is that the source code is available so you shouldn't need so much documentation. Well, that argument is wrong for two reasons:

  1. Your code is probably not as easy to follow as you might think it is. All programmers think it is hard to read someone elses code, much harder than to write code yourself. Especially when that code lacks explanatory comments.

  2. It doesn't answer the question about how the code should behave. Here is an example:

    void some_lib_set_foo_bar (Lib *lib, FooBar *foo) { lib->foo = foo; }

    Innocent looking enough? Is foo allowed to be NULL? According to the above code it is, is that a feature or an oversight? If you only have the source code available, the only way to find out is to go through all source code and try and find code that assumes that foo is non-NULL. If you find code that assumes that foo is non-NULL, then some_lib_set_foo_bar() must not be called with a NULL foo. Otherwise NULL might be ok, but who knows?

Undocumented code that is only meant to be used by yourself is no problem, but if you write a free software library and announce it to the world, then ofcourse you want users, don't you? Users are great, they are willing beta testers of your software and are capable of providing you with great feedback and bug reports. They are doing their part by testing your code, shouldn't you do yours by providing them with documentation?

I also firmly believe that how successful your code is, is directly proportional to how well you have documented it. Documentation makes users happy, happy users use your code. Unhappy users find other tools to do their jobs.

A classical example is Subversion. Subversion is the most successful free Version Control Software (VCS) in the world. It is also the most well-documented one -- it even has a free book. But most experts in the area of VCS believe that the new Distributed Version Control Software (DVCS) basically whips Subversions butt. That is how much better software like bazaar, darcs and git is.

The catch is that their documentation isn't nowhere near as good as Subversions. So Subversion continues to be the undisputed leader of VCS until something comes up that can rival its documentation.

So please write good documentation. I know it is hard work, roughly 50% of the work in my GtkImageView project has been spent writing documentation. Of the remaining 50%, about half was spent reading about GObject internals. I still expect it to be a good investment. Documentation attracts users, users provide feedback which leads to better and more stable code.

Things have gotten better in the last years, few libraries are released without any documentation. But it still isn't as good as it can be. It truly sucks when you see a library that you know is awesome which you can't use because of incomplete documentation. Please fix it!

PyGTK on Windows

When installing PyGTK on Windows, don't forget that you must run a new cmd.exe for the changes to take effect. The PATH environment variable needs to be updated to include the path to the GTK+ libraries which by default are installed in c:/GTK/bin.

Bloggarkiv