talideon.com

Blackout Ireland

Entries for April 2008

April 2, 2008 at 10:44AM “Taoiseach statement on departure expected”

Bertie is going! About bloody time. That’s one less gombeen in charge of the country. However, this means that the protest scheduled for the 12th of this month is probably going to be called off. I was looking forward to that...

Still, it all depends if he does his Imperious Leader schtick and give his departure date as just before the next election... [smile]

Update: Watching the speech. He’s blathering, trying to make out that he’s some kind of great statesman. I wish he’d just get to the point...

Update: Oh, he’s going on about how nasty it is that Mahon questioned his honesty and hows questions of his honesty and propriety have nothing whatsoever to do with his position as Taoiseach.

Update: May 6th? Hmmm... I think I can stick him for just over a month...

“All political careers end in failure.”

-- Enoch Powell

Update (April 3rd): You owe it to yourself to read Gavin Sheridan’s opinion piece on the resignation and his chronology of events. In particular, I thought this was worth quoting:

But I don’t see this as a victory for accountability. Ahern was dragged kicking and screaming to a resignation, when he really should have resigned a very long time ago. If, for example, PTSB had not found the documents that they did, Ahern would very likely still be clinging on to power, and brazening it for as long as possible - and to hell with standards or perceived standards in public life.

We have to ask ourselves what sort of society we want. One where the leader of our country spends an inordinate amount of time answering questions about vast sums of money in his accounts, appoints friends to State jobs, takes cash from businessmen... and all the rest... or one where politicians do all of the above - but when found out resign immediately for the good of the country.

Ireland is a very long way from a democracy which is accountable to its people, and Ahern’s games around the tribunal have only served to bring the country into disrepute and to blacken the highest political office in the country.

Ahern, Taoiseach or not, has very serious matters to answer. Tribunal matters. Cash matters. Corruption matters. Criminal matters. How we deal with those matters, and how we punish wrongdoing in public office, will define our nation.

If we fall short in that regard, we all lose.

April 4, 2008 at 10:55AM XKCD: Venting

Sorry, but this one just cracked me up:

Venting

April 4, 2008 at 7:25PM On Workmanship

Strive to do the best workmanship you can. While the user doesn’t care what the code looks like or how it’s structured, you should. While it’s tempting to, in the interests of expediency to just get something working, there’s serious problems with that attitude. A temporary hack rarely turns out to be that; something that you though would only be needed once will often end up being used repeatedly. And you, or somebody else will have to maintain it. For this reason, you should avoid software entropy. If something needs to be done quickly, then make it work, then make it right. Don’t put off this last step. For all our good intentions, we’re only human, and just like other things that are good for us like eating right and exercising, that which we put off is never done. Get it working, and then make sure that it works right.

Again, this doesn’t come out of any high-faluting sense of aesthetics. This is about proper pride in one’s work and the desire not to create substandard product. This is about making problems, where and when they occur, obvious. This is about maintaining quality.

If you want a practical example, consider your kitchen or better yet, a restaurant kitchen. Chefs have the idea of “Mise en Place”, meaning “everything in its place”. Part of that is that you clean as you go. Imagine a kitchen where none of the staff cleaned up their workareas continuously as they went about their work: detritus would pile up, dirty utensils would pile up, work would get more and more difficult. It would be tempting for an inexperienced chef to say to themselves, “well, I just need to get this done, and I can clean up some other time”. Only, that never happens because there’s always something that just needs to be done now, and their work will get harder and harder because there’s more mess getting in their way, which makes them even less inclined to clean up because more and more work keeps piling up. If they’d cleaned as they went along, however, spreading the effort of maintaining their workarea out and minimising the aggregate effort required, they can keep going at a constant pace and don’t end up worrying about their ever-mounting workload. Oh, and their customers won’t end up getting food poisoning.

The same thing applies to writing software. While it’s important to get things done, it’s equally important to keep things clean. Nobody wants to maintain a big ball of mud, Remember, the path to Oblivion is a long series of tiny, innocent steps.

April 7, 2008 at 11:48AM From my ~/bin: talideon-wallpaper

Actually, it’s now ~/.local/bin, but that’s beside the point.

With all the problems I’ve been having with GNOME and FreeBSD 7--though now I’m pretty sure the root of the problem is GnomeVFS and possibly its (currently partial) replacement, GVFS--I switched back to using ROX and gave Openbox a try as a Metacity replacement. So far, I’m quite happy.

I played around with pipemenus this weekend, wrote a wee script for wallpaper management. Sure, there’s plenty of them already, but none of them did quite what I wanted and it seemed like a decent way to experiment with Openbox.

I haven’t checked to see what version of Python this requires, but it should be find with 2.2 or possibly even with 2.1. All you’ll need in addition is ElementTree (either the Python or C versions--it’ll try to go for the right one), and possibly hsetroot for setting the root window, which is on the fallback list. If you’ve some other preferred mechanism, you can list it in the ~/.config/talideon.com/wallpaper/setters file, which, if present, gives a list of commands to try in turn to set the wallpaper. The filename will be appended to the end of whatever command appears to be available.

Usage is simple: if you pass a directory as the first argument, it’ll generate a pipemenu for that directory; if you pass a filename as the first argument, it’ll use that as the wallpaper and record your selection; and if you pass nothing to it, it’ll use whatever the current selection is as the wallpaper.

There’s plenty of places where I think it can be improved, such as proper XDG support, but I’m quite happy with it as it is.

#!/usr/bin/env python
#
# talideon-wallpaper
# by Keith Gaughan <http://talideon.com/>
#
# A pipemenu script for Openbox for selecting and setting the current
# wallpaper.
#
# Copyright (c) Keith Gaughan, 2008.
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#  1. Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
#
#  2. Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# This license is subject to the laws and courts of the Republic of Ireland.
#

import os, sys
from os import path
from sys import argv
try:
    from xml.etree import cElementTree as et
except:
    from xml.etree import ElementTree as et


FALLBACK_SETTERS = [
    "hsetroot -center"
]
SETTINGS = path.expanduser("~/.config/talideon.com/wallpaper")
WP_LINK = path.join(SETTINGS, "current")


def which(name):
    """Finds the path of some named executable available on PATH."""
    env_path = os.environ.get('PATH')
    if env_path:
        for dirname in env_path.split(os.pathsep):
            executable = path.join(dirname, name)
            if path.isfile(executable):
                return executable
    return None


def get_setters():
    """Loads the list of all wallpaper setting commands."""
    setters = []
    setters_path = path.join(SETTINGS, 'setters')
    if path.isfile(setters_path):
        try:
            handle = open(setters_path, 'r')
            for line in handle:
                line = line.strip()
                if line != '' and line[0] != '#':
                    setters.append(line)
        finally:
            handle.close()
    setters.extend(FALLBACK_SETTERS)
    return setters


def show_wallpaper():
    """Gets a wallpaper setter to set the backdrop on the root window."""
    for setter in get_setters():
        parts = setter.split(' ', 2)
        location = which(parts[0])
        if location is not None:
            parts[0] = location
            parts.append(path.realpath(WP_LINK))
            os.spawnvpe(os.P_NOWAIT, location, parts, os.environ)
            return


def set_wallpaper(wallpaper):
    """Records the user's wallpaper selection."""
    if path.isfile(wallpaper) and wallpaper != WP_LINK:
        os.unlink(WP_LINK)
        os.symlink(wallpaper, WP_LINK)


def generate_directory_menu(dirname, tree):
    """Generates the Openbox menuitems for a given directory."""
    for name in sorted(os.listdir(dirname)):
        full_path = path.join(dirname, name)
        if path.isfile(full_path):
            tree.start('item', { 'label': name[:name.rfind('.')] })
            tree.start('action', { 'name': 'Execute' })
            tree.start('execute')
            tree.data("%s '%s'" % (argv[0], full_path))
            tree.end('execute')
            tree.end('action')
            tree.end('item')
        # Unfortunately, submenus, either as pipemenus or directly embedded
        # in a pipemenu, aren't allowed, but we'll leave this in anyway as
        # if/when it does, it'll be a nice hidden bonus feature.
        elif path.isdir(full_path):
            tree.start('menu', { 'label': name })
            generate_directory_menu(full_path, tree)
            tree.end('menu')


def generate_pipemenu(dirname):
    """Generates a pipemenu for a given directory."""
    tree = et.TreeBuilder()
    tree.start('openbox_pipe_menu')
    generate_directory_menu(dirname, tree)
    return et.tostring(tree.close(), 'UTF-8')


def bad_path():
    """
    Generates a pipemenu indicating that the path given was not a valid one.
    """
    tree = et.TreeBuilder()
    tree.start('openbox_pipe_menu')
    tree.start('item', { 'label': 'Bad path' })
    return et.tostring(tree.close(), 'UTF-8')


if __name__ == '__main__':
    if not path.exists(SETTINGS):
        os.makedirs(SETTINGS)
    if len(argv) == 1:
        # With no args, the currently selected wallpaper is rendered.
        show_wallpaper()
    elif len(argv) >= 2:
        if path.isdir(argv[1]):
            # With one arg that' a directory, a pipemenu of that directory's
            # contents is generated.
            print generate_pipemenu(argv[1])
        elif path.isfile(argv[1]):
            # With one arg that's a file, that file is make the current
            # wallpaper.
            set_wallpaper(path.realpath(argv[1]))
            show_wallpaper()
        else:
            print bad_path()
            print >> sys.stderr, "Bad path."

# ex:et sts=4 ts=4 sw=4:

One annoying limitation of pipemenus it that they can’t have submenus, so it’s not possible for me to, say, implement the FreeDesktop.org desktop menu specification. I might look into writing a patch for Openbox to allow it as I’ve taken a look at its source and it appears quite well-written, but that’s way at the end of my to-do list.

April 9, 2008 at 1:58PM Say hello to our new Taoiseach

Here’s a photo of Brian Cowen accepting the leadership of Fianna Fail:

Brian Cowen accepting the leadership of Fianna Fail

April 11, 2008 at 1:54PM That looks about right

Yep, another meme...

$ history | awk '{ print $2 }' | sort | uniq -c | sort -rn | head
     90 vim
     63 make
     53 ls
     49 svn
     39 whois
     35 cd
     25 fg
     22 ssh
     19 rm
     16 exit

[via Bill]

April 14, 2008 at 12:37PM Lithium 006 patches

This won’t be of any interest to anybody except those of use who use ROX and Ken Hayber’s Lithium applet. These patches are against Lithium 006, which isn’t advertised on its homepage, but which is downloadable here.

There’s four patches. The first one patches acpi.py to use modern exceptions. By modern exceptions, I mean changing NotImplemented into NotImplementedError, which as been around since Python 1.5.2, which was released nine years ago. [smile]

The second patch is more substantial. It reworks how Lithium deals with battery backends by creating a generic uniform interface to them all, altering the backends to check for their suitability to the system they’re running on, and exposing a single function that can be used to query for a suitable backend. This is much cleaner than the current system, which has battery.py (the applet itself) knowing far more about the backends than it really should. The changes in this patch made the next two patches much easier.

The third and fourth patches add two new backends. The first backend is one that uses the FreeBSD apm command to query the current battery state. The second new backend uses HAL to query the battery state in a platform independent manner.

Download Lithium 006 patches.

Update: I was chatting with Ken Hayber over email, and he told me that he’s stopped using ROX, so he’s no longer maintaining Lithium or his other ROX applets. If I’ve the time, I might take over maintainership of a couple of them. I’ve cloned the repositories, just in case.

April 17, 2008 at 11:26PM Review Board isn’t for us

I finally got around to installing Review Board on a machine here at work.

It’s not going to work for us.

Don’t get me wrong, it’s an excellent piece of software, but there’s a fundamental difference in the way that things get done at Blacknight and the way Review Board expects things to be done. Specifically, Review Board expects the review to be done pre-commit, whereas the only way a code review happens here is if somebody other than the original developer initiates it.

Now, much as I’d wish people would do pre-commit code reviews, given everybody’s personalities and sundry responsibilities, they’re never going to happen here unless they happen post-commit.

I’ve had a look around, and all the other code review software doesn’t seem to fit too well with the kind of workflow I need to account for. I’m going to keep looking, but it’s becoming increasingly likely that I’m going to have to write something myself. Suckage.

Any suggestions are welcome.

Update (May 6th): Christian Hammond, in whose blog I first stumbled across Review Board mentioned in a comment below the fold that there is indeed a way to do post-commit reviews. I’m going to take a read of it and see how things go.

April 21, 2008 at 1:28PM import soul

‘Too bad we can’t give it a soul’ ‘Sure we can... «import soul»’ ‘Oh, right. Python.’

April 23, 2008 at 1:20PM Patch: libchk symlink resolution

This patch for libchk fixes a longstanding bugbear of mine with it: it doesn’t resolve symlinked directories before scanning.

I wrote an email to Akinori Musha, the author, a while back outlining the changes made in this patch, but after resending it several times, it kept on bouncing. That’s why I’m posting it up here.

I’d forgotten to save the patch when I upgraded, so I lost it. I needed to use libchk again last night, as as I still remembered what I’d done the first time around, I made the same patch and installed a local copy of libchk rather than installing it from the ports tree. Somebody out there might find it useful.

--- libchk.orig	2008-04-22 23:51:14.000000000 +0100
+++ libchk	2008-04-22 23:48:04.000000000 +0100
@@ -33,6 +33,7 @@

 require 'optparse'
 require 'find'
+require 'pathname'

 LDCONFIG_CMD = '/sbin/ldconfig -elf'
 OBJDUMP_CMD = '/usr/bin/objdump'
@@ -335,6 +336,7 @@

 def compact_dirs!(dirs)
   normalize_dirs!(dirs)
+  dirs.map! { |dir| Pathname.new(dir).realpath().to_s }
   dirs.sort!

   prev = nil

April 25, 2008 at 3:30PM IsaacBrowser IV

[Updates since this one: Release 2, Release 3]

About a year ago, I stumbled across IsaacBrowser III, a small and rather nice gallery script.

Since then, I’ve occasionally tinkered with it to fix UI elements I though could be improved, to close a few potential exploits, and add a few extra features. It’s changed so much since then that I though it’d be worth changing the name a bit and releasing it. What triggered this release was that Paul gave me a link to where he was using IsaacBrowser III.

IsaacBrowser IV Screenshot

Features:

Note that the method used for creating the name of the cached thumbnail is different because, with my version, you can have a single shared thumbnail cache in the root of the gallery, so you’ll need to clear out the old thumbnails.

If you’re using IsaacBrowser III, give it a whirl. If you’re not, give it a whirl anyway. [smile]

[download; demo]

April 25, 2008 at 11:19PM Quote: Good Programmers vs. Bad

I will, in fact, claim that the difference between a bad programmer and a good one is whether he considers his code or his data structures more important. Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

-- Linus Torvalds

April 26, 2008 at 12:52AM Fun things to do with last.fm #1

Tag music with progressively more bizarre but still relevant tags.

April 26, 2008 at 1:06AM Richard Harris - MacArthur Park

Seriously, how can anybody not like a song with these lyrics:

Spring was never waiting for us, girl
It ran one step ahead
As we followed in the dance
Between the parted pages and were pressed
In love’s hot, fevered iron
Like a striped pair of pants

Gold, pure gold. [smile]

Somebody needs to do an extended version of the Portal end credits fading from ‘Still Alive’ into this...

April 28, 2008 at 3:30PM Patch to get the copy of IO tagged 2008.03.30 to build on FreeBSD

I’m sick as a plague hospital right now and got next to nothing done over the weekend. Let’s just say that what’s wrong with me is embarrassingly gross and seems to have to do with every part of my digestive tract south of my stomach.

I did manage to get io (download tag, though the patch also works on the master branch at the time of posting) running on my FreeBSD laptop though.

What I had to patch was somewhere where the log2() function which, annoyingly, isn’t in libm. Seeing as the code that needed it was just counting bytes, it seemed logical to substitute a function that did just that.

The patch also removes some annoying build warnings.

--- libs/iovm/source/IoNumber.c.orig	2008-04-26 15:56:13.000000000 +0100
+++ libs/iovm/source/IoNumber.c	2008-04-26 16:25:42.000000000 +0100
@@ -423,6 +423,20 @@
 	return string;
 }

+static int countBytes(long ld)
+{
+	int n = 1;
+	for (;;)
+	{
+		ld >>= 8;
+		if (ld == 0)
+		{
+			return n;
+		}
+		n++;
+	}
+}
+
 IoObject *IoNumber_asCharacter(IoNumber *self, IoObject *locals, IoMessage *m)
 {
 	/*doc Number asCharacter
@@ -441,7 +455,7 @@
 	else
 	{
 		uint32_t i = io_uint32InBigEndian((uint32_t)d);
-		int bytes = d > 0 ? log2(d) / 8 : 1;
+		int bytes = countBytes(ld);
 		IoSeq *s;

 		if (bytes == 0)
--- libs/iovm/source/IoState_exceptions.h.orig	2008-04-26 18:35:41.000000000 +0100
+++ libs/iovm/source/IoState_exceptions.h	2008-04-26 18:35:50.000000000 +0100
@@ -8,4 +8,4 @@

 IOVM_API void IoState_error_(IoState *self, IoMessage *m, const char *format, ...);

-IOVM_API IoObject *IoState_setErrorDescription_(IoState *self, const char *format, ...);
\ No newline at end of file
+IOVM_API IoObject *IoState_setErrorDescription_(IoState *self, const char *format, ...);
--- build/Project.io.orig	2008-04-26 20:00:28.000000000 +0100
+++ build/Project.io	2008-04-26 20:00:53.000000000 +0100
@@ -74,7 +74,7 @@
 		if (platform == "windows",
 			"-MD -Zi -DWIN32 -DNDEBUG -DIOBINDINGS -D_CRT_SECURE_NO_DEPRECATE"
 		,
-			"-Os -g -Wall -DSANE_POPEN -DIOBINDINGS"
+			"-Os -g -Wall -pipe -fno-strict-aliasing -DSANE_POPEN -DIOBINDINGS"
 		)
 	)

I hereby place this patch in the public domain.

[download patch]

Update (May 1st): patch committed! Yay!