Home
WWWWolf's LifelessJournal
Random ramblings of a random wolf
July 1st, 2008 
Sorry if this sounds like an irrational flame - perhaps it is. I'm still in the process of cooling down...

For me, Python has been a language that I really have divided opinions about. It's probably an important language, and in many ways, it's quite elegant; yet, at the times, I feel that the designers had no idea what they were doing. Perl can get ugly and P5 is pretty outdated and certainly out of fashion, but at least it's designed. Ruby is inefficient, but at least it's got a very clean syntax. Python? Sometimes it's cool, sometimes it's hell, and as with all languages, the makers of libraries may or may not know where they're heading. Well, at least it's far better than PHP. =)

A few days ago I wrote a script to replace my old shell script that fires up WLAN connection with specified settings. Whee - I learned of Python shell help() feature. Damn, that's cool. (The reason I didn't use it before was that I thought help()s are useless. if it was called interactive_documentation() I might have paid attention. =) If it can one day do something similar to Ruby's (Class or object).public_methods.grep(/whatever/).sort, I'd be in heaven. In my opinion a good language is self-documenting and browseable.

Anyway, I ported my earlier GIMP bloom script to Python-Fu. While I like some of the OO stuff, some of the stuff is pretty weird, and certainly doesn't match with the documentation I had at hand. I'd offer some random comments from the source code - censored, because the script was, after all, posted on deviantART - and I thought that now that I've slept over night, I might actually talk about the problems in a calm and collected fashion.

For some background: GIMP's promary programming interface is the Procedural Database (PDB), which is basically a standard set of calls that GIMP understands and you can call them no matter what language you are programming in - the same calls work in Scheme (Script-Fu), Perl (Perl-Fu), and Python (Python-F... excuse me, GIMP-Python.) However, Perl and Python APIs also include an object-oriented API for some internal GIMP objects, like images and layers. Obviously, you want to use the OO API as much as possible - especially in Python, the Superiour OO Programming LanguageĀ®.
Why the [censored] are the [censored] parameters in different order compared to gimp_layer_new PDB call? Just for [censored] fun? Not very funny to me, [censored]! I like to stare at PDB browser, and if the parameters are not in that order, well, [censored]!
For some obscure reason, the standard gimp_layer_new PDB call and Python gimp.Layer OO constructor take parameters different order. Same for other stuff, like channels and images and whatever. Not a biggie... I just need to keep two sets of documentation open; one for the GIMP OO API, and the PDB browser. You see, if the arguments were in same order, I could easily take whatever it says in gimp_layer_new call documentation and just stick gimp.Layer(...) there instead.
Why the [censored] do I get a [censored] type mismatch when doing the non-PDB version of the command? Exactly as said in spec! And more [censored] importantly, which [censored] argument triggers that [censored] error??? [censored] Python only says "type mismatch", yeah, as if that's going to get me [censored] anywhere.
selchn = gimp.Channel(img,"For selection",width,height,100,(0,0,0)) doesn't work. selchn = pdb.gimp_channel_new(img,width,height,"For selection",100,(0,0,0)) works perfectly. One comes from Python-Fu documentation, exactly as specced. Another comes from converting the Perl PDB call directly to Python PDB call - ugly, because Python scripts should probably use the neat API instead of raw PDB when the neat API is available... but either way it gets the job done, and it's done exactly as specified too. What's wrong with this picture?

I have no idea what causes the "type mismatch" error here. The Python API doc also says the last argument should be "...colour (one of the *_CHANNEL constants)". Er... Script-Fu and Perl-Fu want, uh, er... you know, a colour as the last argument. One that specifies the channel colour, you know. And obviously, the *_CHANNEL constants aren't listed anywhere in the spec... so a quick grep says legit values are PF_CHANNEL and PDB_CHANNEL, neither of which work. What the shit? I don't know about you, but I get a nagging feeling that maybe the spec is wrong. Very wrong.

Then a pop quiz. How do you paste stuff in Perl?
my $fs = gimp_edit_paste($selchn,1);
$fs->anchor();

Yeah, pretty simple. The script was done in Perl::Fu style, but can mix OO style in if it makes sense. Now, how do you paste shit in Python?
fs = pdb.gimp_edit_paste(selchn,1)
pdb.gimp_floating_sel_anchor(fs)
"OO is failure, OO is failure, tralla la lalla la lalla la!" Excuse me, you can't anchor a floating selection via an OO call in this allegedly Superiour OO Programming LanguageĀ®, you have to use one of those evil no-good PDB calls.
[censored] Python-Fu needs the [censored] list length, which Perl-Fu can figure out on its own. I can't [censored] believe this [censored]!
In Perl, the call is in form gimp_curves_spline($selchn,0,[127,0,254,254]); This deviates from the PDB standard, because it is missing the list length argument... which makes sense, because the list length argument isn't needed anywhere else either: the PDB idiom is always, everywhere, "list length argument followed by list itself", and Perl automagically hides this. If the PDB idiom doesn't make sense in the target language - e.g., in Perl, you certainly always know how long your lists are - there's no reason to not change it. Especially if it doesn't really change the way stuff gets called: PDB wants to know the "list length and list itself", and doggone it, Perl can provide it for you. If you are programming in some crappy language, yeah, then passing the list length makes and awful creepy much of sense.

So what does Python want? pdb.gimp_curves_spline(selchn,0,4,[127,0,254,254]) ... um, did I just see list length argument? Did I just see a bloody list length argument? This isn't some shitty language like C where you have to be super-careful about list lengths, you know! This is the Superiour OO Programming LanguageĀ®! Goddamn it.
Another [censored] type mismatch, even when the reference says you can specifically feed it None to say no channel is active... Oh well, don't blame me if this blows up!
I thought it was nice to tell GIMP that active channel is not active... in a proper OO fashion. img.active_channel = None should do the trick, right? That's what the spec says, right? Blam! Type mismatch! Cannot assign that here! The spec is looking rather weird right now!

All in all, converting the script to Python-Fu wasn't that difficult... but I still can't quite shake away the feeling that something is not really all that well designed here.
This page was loaded Dec 30th 2009, 8:53 pm GMT.