Armed with a text editor

mu's views on program and recipe! design

May 2006

Puzzling Answers Posted 2006.05.18 07:02 PDT

So what does ''.join(chr(sum(((val >> i) & 1) << (7-i) for i in range(8))) for val in range(256)) do? If you run it on python2.4 you get an ugly string. Specifically it's a list of 256 bytes with their bits swapped in order of significance: 01 becomes 80 and so forth.

But why is this useful? Thanks to Joe's work it's now part of Mutagen, and is being used as part of a scheme to calculate the kind of CRC32 that the Ogg container (of Ogg Vorbis) requires. Why a scheme? Speed. As an interpreted language, python isn't well suited to small bit calculations on large sets of numbers. A standard reduce(lambda x, y: table[(x>>24) ^ y] ^ (x << 8), data, 0) scheme is too slow for comfort. However the table used in the existing C implementations zlib.crc32 and binascii.crc32 is from the bitwise reversed generator polynomial of the one used for Ogg.

Peter Johnson came to the rescue and figured out we could get the same effect by bitswapping each byte of the data and then bitswapping the final 32-bit result. Thanks to str.translate, we hoist most of the work into C, and the above puzzler code runs once at module import to generate the translation table.

And yes, Joe, it's good for confusing you at 1AM. :)

(0 Comments ) (0 Trackbacks) puzzle python

Puzzlers Posted 2006.05.17 06:51 PDT

What is the following useful for?

''.join(chr(sum(((val >> i) & 1) << (7-i) for i in range(8))) for val in range(256))
(1 Comments ) (0 Trackbacks) puzzle python

Summer of Code 2006 Posted 2006.05.14 09:38 PDT

I'm sure anyone reading this is aware of the Google sponsored Summer of Code, as an interesting opportunity for Free Software and Open Source Software projects to attract new contributions (and ideally contributors) through a summer stipend paid by Google. What's less well known is the process of choosing applicants.

I applied to mentor with the PSF, but now I'm torn. I think Google is doing a good thing, but the application process has me questioning my interest. Between limitations in the web site project ranking system, and dealing with unknowns (did this student submit applications to other groups, or more than one to us?) it runs like a bad interview puzzle question:

You have 30 chickens, 30 foxes, and 30 bags of corn, one canoe, and one river. You can only fit one with you in your canoe, and wish to take them all to the other side of the river. If you ever leave a chicken with corn, or a fox with a chicken, the latter will be eaten. A bandit might come by and steal up to one item per river crossing. In what order do you take items across to maximize the results of Google's sponsorship?

And I hear it's much better than last year...

(0 Comments ) (0 Trackbacks)

February 2006

Quod Libet Copyright Infringement Posted 2006.02.08 20:39 PST

I came home from work today to find I'd missed quite an afternoon. The summary is best shown as a single message from Joe with whom I develop Quod Libet: We got ripped off.

He was tipped off early this afternoon after reading Ross's post about Listen, looking at the screenshot and recognizing the appearance of the OSD. When he looked, he found in some places our copyright was still in place, untouched; in others cut and paste jobs had completely obliterated it. Apparently it's an established project that uses our code, but one without any public links or references to Quod Libet. I got back too late to see the code or the website in question, so I'm not sure what I think of this mess. Hence I'll talk about this in a general fashion, considering this case only as an example.

A lot of people are calling Joe the bad guy for cutting this off with his brusque open letter. There seems to be a belief shared by several anonymous commenters that pointing out in public that someone else did something wrong is a bad thing. I disagree: how else will anyone outside the infringer learn? Especially with a mistake as core to the Free Software community as copyright infringement, everyone needs to be aware of mistakes. More importantly they need to know how to avoid missteps and follow licensing terms correctly. I do find Joe's choice of language regrettable, but his core message is spot on.

We need to take more care of observing copyright and licensing requirements in the community. Anyone writing software and licensing it under any version of the GNU General Public License (GPL) is likely to be trying to contribute to the community so the damage from this scenario (stripping copyrights off GPLv2 and representing them as GPLv2 or later, and as your own work) is small. Assuming the infringer cleans up his mistakes, we will allow him to partake of the code as we would any new licensee.

What if this was darker? What if amongst the code being put into a GPL project there was code that didn't offer open terms at all, much less Free terms like the GPL? What if the aggregated work was being offered as closed source pay-only? Either scenario is anathema to the Free Software community: the first because it weakens us; the second because it takes advantage of us. Should our reactions to these scenarios be so different from the reactions to Joe's letter? I say they shouldn't, but you know everyone would be rooting for the little guy for sticking it to the evil empire.

License intentions are important—it's what ties us together as a community—but carrying through and actually following the licenses is crucial for the survival of our community. I look forward to a validly attributed and licensed Listen appearing soon; let's keep that sharing part of this community working!

(1 Comments ) (0 Trackbacks) copyright quodlibet

January 2006

Free Software's underbelly (2) Posted 2006.01.31 22:23 PST

Continuing along the theme of trivial problems that go unfixed for a long time, with an occasional personal favorite, here's some problems with PyGTK.


Where I treated Mozilla Firefox as a user application, I treat PyGTK mostly as the development library/toolkit that it is. For quite a while GTK+ and GNOME were the poster children of the Free Software Movement. They handle some things really well, but there are still a lot of gaps. Here's some of the gaps I particularly want to see filled.


Real tooltips can only be single paragraphs of text. No images, no formatting, no nothing. At two and a half, and five years respectively, these strike me as a perfect example of the if we put this off until we do such-and-such (a hard thing), then this will be really easy degenerate case mentality. Since GTK+ is much more concerned about backwards compatibility than Mozilla Firefox seems to be, I can give them some kudos for avoiding ill-considered changes. However the status quo is not good enough, and any tooltip reimplementations to acquire the different capabilities ruin the point of having a widget in the first place.

TreeView: tooltips

There is no builtin way to set tooltips on a per-column, per-row, or per-cell basis (three and a half years old). This ties into the above five-year-old bug, potentially as another easy degenerate case. Well, I'm still waiting.

TreeView: dragging

Dragging is hard enough, but dragging multiple items is really hard. By default you need to start a drag on the same button-press that selects or unselects a row. I can't find a bugzilla bug on this one, but Quod Libet uses class MultiDragTreeView which implements this in a saner fashion.

TreeView: completion

There is no builtin way to show the contents of an ellipsized or otherwise truncated text cell. I also can't find a bugzilla bug on this one, but Quod Libet uses class TreeViewHints which does most of what I need. The idea is when you're hovering over an ellipsized cell in a TreeView, a tooltip-like window will show up exactly in place to show you the parts you can't see. Windows MFC has this built in, and that one even works if the contents are hidden due to scroll. TreeViewHints only handles a small subset of ellipsized cases, so I'd rather see something real implemented in C.

TreeView: columns

There's no right way to set a right-click menu on a column header. Apparently there are some hacks in C, but they are not available from PyGTK. This makes it practically impossible for us to do the user-friendly configuration of Quod Libet's column headers that we've wanted to for over a year.

(0 Comments ) (0 Trackbacks) freesoftware pygtk

Free Software's underbelly Posted 2006.01.28 16:00 PST

Free software has a major weakness. It's not one that other people can worsen or exploit, other than by working harder themselves. So this weakness doesn't spell the end of Free software. But it consistently acts as a limiting factor in the greatness of Free software. To be fair plenty of commercial software suffers from the same problem, if for different reasons, so it's not even a weakness specific to Free software. But it's a weakness I want to see addressed and mitigated.

The weakness I refer to is in small but important features: they constantly slip through the cracks. What makes it infuriating is the number of wonderful, obviously-difficult, and often polished features that are written in the same timespan. Sure it's not a straight tradeoff, so lamenting if we had time for this, certainly we had time for that doesn't help—different contributors are interested in writing different things. Official maintainers are interested in accepting different things. But the result is the same: something simple remains hard or impossible for years, and things you could do in the previous version cannot always be done in the next version.


It's not hard to find examples. I don't pick any given example to make fun of the project which lacks the feature; I do it to highlight a change which I would love to see make my life that much better. That said the more I use something, the more gaps I'm likely to notice—in that sense perhaps it's a compliment if I list a lot of gaps! Regardless it's probably best to treat this as my personal rant list. More examples coming later.

Mozilla Firefox

What makes the first two Mozilla gaps so annoying is that they've both been present in previous versions of the product. Now that's progress!

View as text

Back in the bowels of time the first well-known web browser could view just about anything as if it were served with content-type text/plain. This was a great thing, although its importance didn't crop up until much much later. Recently web servers have started sending source code under other content types like text/x-csrc or text/x-py. Since it became reborn as Mozilla, rather than always supporting an in-browser fallback, unknown content types are only supported by external applications. This means when I go to view plain ascii text files on certain web servers I have to load up a text editor. Insanity!

And I'm far from the only one to think so. This was reported on bugzilla five years ago.

Manage folder

Firefox before version 1.5 offered a "Manage folder" option in the right click menu of each bookmark toolbar folder. In 1.5 they removed this, apparently because some people thought others might find the expand option confusing, and because some functionality didn't work right in the subfolder-only view. The result? I and others can no longer easily access and edit bookmarks in a single folder. I have way too many bookmarks to view the whole set; managing a single folder was very important to me.

Live bookmarks

When a site offers an RSS feed, you get a nice icon letting you know this. Click on the icon to subscribe (create a live bookmark). However neither in this dialog nor on a right click can you find out what the URL is for that live feed. The only way to do that is to view the original source, or to create the bookmark and view its properties. This makes it much harder to verify that you're setting up your RSS rel links correctly on a page, or to directly visit the feed in your browser. I couldn't find a bug in buzilla about this limitation.

(1 Comments ) (0 Trackbacks) freesoftware mozilla

pyxyz.require('sense') Posted 2006.01.18 20:36 PST

I'm a big fan of high level programming libraries, and of particular relevance is pygtk. Some time ago in the dark ages of GTK+ 1.x, you would merely import gtk and all was well. Then GTK+ 2.0 was released and pygtk moved to support it. In order to support side-by-side installability (like the C libraries beneath) they decided to do the following.

They created a helper package called pygtk. The purpose of this package was to manipulate the python library paths such that a subsequent import gtk pulled in the desired package. On the surface this seems like an okay idea. It lets the python continue to use the name gtk. It lets a user have applications that need pygtk 1.x and ones that need 2.x installed and running side by side.

What is lost in this trade for side-by-side support? Elegance. What is gained? Subtle bugs. First the subtle bug: skipping the pygtk helper often works. In particular if you're on a machine with only the 2.x version of the library, you get exactly what you expect when you import gtk. However, the moment you install the 1.x library, or share your code with a friend who has it, you may unexpectedly get the 1.x library and things start to fail mysteriously. This is by design - it was intended to allow a site to have a default version. I don't understand the benefit, as the percentage even of python programs that can be used with either library is minimal.

(I find it hard enough to use different versions of pygtk-2.x with the same code, but that's another story.)

What about the elegance? Here I present two options. The first is what you must currently do to successfully import gtk in all scenarios. Of special note is the string 2.0 which describes some abstract API level which is distinct from 1.2, but is shared between 2.0, 2.2, 2.6, and 2.8 so far. The second is what I would have considered a better choice.

import pygtk
import gtk

import gtk2 as gtk

This is of course the minimal case. A more realistic sample would also need to import gobject and pango; these days pangocairo, cairo and some other packages join the fray. If you apply the same trick, this changes the line ratio from 3:1 to 5:3 or 7:5, which isn't as horrid. However at this point none of those packages have 1.x versions. They could just as clearly be imported on one line.

How about supporting the mythical runs-on-both scenario? Easy:

try: import gtk2 as gtk
except ImportError: import gtk

What about system defaults? I don't see that as a realistic use case, and since it fails in the pygtk.require() case as well, I'm not worried about duplicating it.

There's one thing that the pygtk method handles: it's much harder to import both the 1.x and the 2.x library in a single program. But is this such a danger that it's worth all these other problems? The python philosophy is to trust the programmer not to do something catastrophic without reason. Can you imagine someone coding import gtk; import gtk2 without a reason?

Where are we today? Heading the wrong way. The python-gstreamer package now has a pygst module, almost a verbatim copy of Let's squash this now. It's way too late to back this out of pygtk 2.x, but let's not repeat it for 3.x. I don't know if it's too late for pygst, but if it's not, let's back it out immediately and switch to a saner approach.

[Disclaimer: I don't work on either the pygtk or pygst projects, I just use them.]

(0 Comments ) (0 Trackbacks) pygtk python

Previous entries