March 31, 2003
Only total nerds need bother reading this

The case of the 500-mile email

Via Chris Winters.

Posted to Funny by Simon Brunning at 04:04 PM
Driving win32 GUIs with Python, part 4

A correction...

Thomas Heller got in touch with me, and pointed out that my getMultipleWindowValues() function (see part 3) does A Very Bad Thing. It mutates a Python string. These are supposed to be immutable in Python. This didn't break anything of mine, or hasn't yet, but it certainly could. If, for example, a string being used as a key in a dictionary mutated, who knows what would happen? BANG!

Fixed code (using the array module) below. (Notice that I've also turned this function into a generator.)

def getMultipleWindowValues(hwnd, getCountMessage, getValueMessage):
bufferlength = struct.pack('i', 255)
count = win32gui.SendMessage(hwnd, getCountMessage, 0, 0)
for itemIndex in range(count):
value = array.array('c', bufferlength + str().ljust(253))
valueLength = win32gui.SendMessage(hwnd, getValueMessage, itemIndex, value)
yield value.tostring()[:valueLength]

Update: See the whole series: Driving win32 GUIs with Python, part 1, Driving win32 GUIs with Python, part 2, Driving win32 GUIs with Python, part 3, Driving win32 GUIs with Python, part 4 and 7 hours, one line of code.

Posted to Python by Simon Brunning at 01:43 PM
Game Boy Advance SP

I couldn't resist getting a Game Boy Advance SP. Cool as fuck, I tell you.

Games? I have Advance Wars, Golden Sun and Doom.

I can recommend Advance Wars. Incredible game. Golden Sun is pretty good too, if you don't mind inscrutable Japanese-style RPGs. Doom is a little on the retro side. I love it, but if you don't remember if from the first time around, it may well not do it for you.

Anyone else got a GBA? Which are the unmissable games?

Posted to Toys and games by Simon Brunning at 12:09 PM
Your Knowledge Portfolio

Steve's post makes an interesting point - if they sack us all, who'll buy anything?

My current company is in a similar situation. We are small, and everyone knows everyone. After some initial rounds of redundancy (mostly chaff, but some wheat), we have now all voluntarily gone on to 4 days weeks to avoid any more job cuts. For the moment, that is.

The only means you have to protect yourself really is to keep your own skill set up to date. In The Pragmatic Programmer, (which I recommend) Andy Hunt & David Thomas talk about your skill portfolio. They suggest that you should treat your skill set like your share portfolio - invest regularly, diversify, mix high-risk-high-return investments with low-risk-low-return investments. Good advice, I think.

Posted to Software development by Simon Brunning at 11:50 AM
Why the real Vietnam might start when the formal war has finished

Rupert Cornwell: Don't mention the V-word

Osama Bin Laden must be rubbing his hands with glee reading the news these days.

See also: Robert Fisk: Sergeant's suicidal act of war has struck fear into Allied hearts

Posted to The Big Room by Simon Brunning at 11:25 AM
March 28, 2003
I blame that Bin Laden chap...

Fire destroys Brighton's West Pier

Posted to The Big Room by Simon Brunning at 04:31 PM
Leave the poor bastards alone

The Yanks are not satisfied with bombing the Iraqis. Oh no, they want to sell them mobile phones, too.

Via Feet Up!

Posted to Apropos of nothing by Simon Brunning at 01:33 PM
March 27, 2003
You can get drunk on Guinness

OK, OK, so you can get drunk on Guinness.

Steve and I met up at the Reluctant Camel, or whatever, and started the experiment at around six. The Guinness Marketing people were there - the first round was free (These people seem to be following me - that's the 10th free Guinness that I've had over the past two or three weeks. They can follow me some more if they feel like it.) There was also a raffle for a really cool beer fridge, but being cool, I didn't win it.

Eloon pitched up for a while. Cool lady, or 'top bird', as Steve would have it. She was the control, on G&T, rather than Guinness.

Some time around half-past eight, we got a little bored of the Elusive Camel, so we concluded the experiment, and wandered down to Cubana, just down the road. We certainly didn't feel drunk at that point, but clearly we hadn't absorbed all the Guinness yet, since Steve and I were soon feeling very drunk indeed. It must have been the Guinness, since we were only drinking various fruit juices. Margaritas, Daiquiris and Mojitos, I think they were called.

Posted to by Simon Brunning at 10:28 AM
March 24, 2003
It's OK if it's in a song...

A while back, Cath was driving somewhere with the girls in the back.

For reasons which escape my comprehension, Cath likes Eminem. Or however you spell that. I'm more of a Miles Davis man myself. But I digress.

Ella gasped out "Mummy, that was a rude word!"

Big mistake coming up. Cath said, "Oh, that's OK, it's in a song."

Cath drove home to Ella singing "Happy fuckin' birthday to you, Happy fuckin' birthday to you..."

Posted to Funny by Simon Brunning at 03:48 PM
Robin Cook - an un-person?

Acording to the BBC, Robin Cook isn't in the news, and never has been. A 1984-style history change, perhaps?

Or just a case of case sensitive searching? You be the judge.

Posted to Funny by Simon Brunning at 01:47 PM
Blogging is not journalism. Bloggers are not journalists.

It seems pretty obvious, but it seems to need to be pointed out from time to time.

Russell Beattie is a tech blogger who writes about Java and mobile technology. He's got a big readership - a lot of people want to hear what he has to say.

Microsoft recently invited him to a conference (In Disneyland Paris, no less!). He turned them down. A man of principle, no less - the blogging world's answer to Robin Cook?

It seems that he caught a little flak over, amongst other things, his lack of impartiality. In his reply, Of COURSE I Hate Microsoft, he points out that he's never pretended to be anything other than biased - he hates Microsoft, doesn't trust them, and makes no bones about the fact.

He also points out that all weblogs are like this to some extent. They are by their nature personal expressions.

Nice anti-Microsoft rant, too. ;-) I agree with every syllable.

Posted to Blogs by Simon Brunning at 01:32 PM
Bit of a quiet weekend...

Got up late, at nineish.

Tried to take the cat to the vet, but no cat box found. I'm off on Tuesday, so I'll try and get on by then. If I can't, I suppose I'll have to buy one.

Went to see The Ring. This turned out not to be about Bracknell - it wasn't that scary. Not that scary at all, in fact. Unnerving ar times, but you have to expect that from a horror flick. Interesting direction, though, I thought - lots of interesting angles. The Colour balance was very cold, too.

Book shopping - found Python in a Nutshell at last. Also The Tin Drum by Gunther Glass, and a book of Ursula K. Le Guin short stories.

Then a couple of beers, and home.

On Sunday, I went to Reading to see the girls. Ella wanted to spend her pocket money on a 'Spare Brain" - a hideous squishy rubber thing, in a transparent rubber sleeve, along with red liquid. The off to Reading Museum. I've not been here before, though the girls and I love museums. Smallish, but pretty good - A copy of the Bayeux tapestry, Roman remains, Victoriana, a bit of natural history, pretty varied really. Explaining to Freja how animals are stuffed was fun...

Then a bit of homework with Freja, and off home.

Posted to Apropos of nothing by Simon Brunning at 10:42 AM
March 21, 2003
JSR-666: Rich text identifiers

Further suggestion for JSR-666.

Previous JSR-666 recommendations:

JSR-666: Rich text identifiers

As is so often the case, Microsoft is leading the way here.

Remember back in the bad old days of DOS and Windows 3.x? 8.3 filenames? Yuck! With Win9x came long file names, and better still, embedded spaces. I don't need to tell you how useful this is.

Lets have this in Java. And why stop there? Let's go for full rich text! my button could be different from my button, and my button different again. (After all, mybutton and myButton are already different, so it's not so great a leap. my exception might be more serious than my exception.

I'm sure that there are some parsing issues to sort out, but they are (waves hand) pretty trivial, I'd imagine...

Update: See also JSR-666: i18n, misspellings and homonyms.

Also, see the wonderfully excentric colorForth. Clearly, there's no such thing as a new idea...

Posted to Java by Simon Brunning at 05:21 PM
Anyone remember Cough Candy Twists?

Fizzy Cola Bottles, Flying Saucers? Sherbet Lemons?

Check out The Old Sweet Shop, for all your online crap sweet needs.

Remember the way that sherbert lemons used to lacerate the inside of your mouth? Bliss.

Posted to Apropos of nothing by Simon Brunning at 05:03 PM
Driving win32 GUIs with Python, part 3

Some things you can do with a control once you have it.

See Driving win32 GUIs with Python, part 1 and Driving win32 GUIs with Python, part 2.

There are, of course, loads of things you can do with a control. Anything that you can do with a mouse or a keyboard can be automated. I'll just give a few simple examples, from which you should be able to extrapolate most things that you might need to do.

A great many of these actions are class specific - you can select one or many of a combo box's items, for example, but a button doesn't have items to select.

OK A nice simple one first. Let's click a button:

def click(hwnd):
win32gui.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, 0, 0)
win32gui.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, 0)

We can use this function like so:

optDialog = findTopWindow(wantedText="Options")
def findAButtonCalledOK(hwnd, windowText, windowClass): # Define a function to find our button
return windowClass == "Button" and windowText == "OK"
okButton = findControl(optDialog, findAButtonCalledOK)
click(okButton)

You could do this more tersely with a lambda, by the way:

optDialog = findTopWindow(wantedText="Options")
okButton = findControl(optDialog, lambda hwnd, windowText, windowClass : windowClass == "Button" and windowText == "OK")
click(okButton)

I prefer the first form, but that's purely subjective.

And now, for my next trick, let's get the text from an Edit control. "But wait", you'll say, "can't you use the win32gui.GetWindowText() function"? No, actually, you can't. The thing is, this works for some classes of window - you can use win32gui.GetWindowText() to get the text of a button or a label, for example. But other classes don't have the kind of text that win32gui.GetWindowText() sets. An edit control is one of these - it has lines of text rather than just text. Here's a function which will get it for you:

def getEditText(hwnd):
result = []
bufferlength = struct.pack('i', 255)
linecount = win32gui.SendMessage(hwnd, win32con.EM_GETLINECOUNT, 0, 0)
for line in range(linecount):
linetext = bufferlength + "".ljust(253)
linelength = win32gui.SendMessage(hwnd, win32con.EM_GETLINE, line, linetext)
result.append(linetext[:linelength])
return result

The only complicated bit here is the struct stuff. When sending the win32con.EM_GETLINE, you need to pass a string, into which the line of text will be inserted. The first byte of this string must contain the total length of the string. struct to the rescue! It would be nice to wrap this up into a class, implementing a file-like interface, at some point. Or perhaps it should be a generator? Anyway, as it stands, you can use it like so:

genTop = findTopWindow(wantedText="Generating the Runtime")
def editFinder(hwnd, windowText, windowClass): return windowClass == "Edit"
genEdit = findControl(genTop, editFinder)
print getEditText(genEdit)

Now, combo-boxes. (These are the ones with a little down-arrow button to the right hand side, allowing you to select one (or perhaps more) from several options.) Here is the code to get a list of the values from a combo box:

def getComboboxItems(hwnd):
result = []
bufferlength = struct.pack('i', 255)
itemCount = win32gui.SendMessage(hwnd, win32con.CB_GETCOUNT, 0, 0)
for itemIndex in range(itemCount):
linetext = bufferlength + "".ljust(253)
linelength = win32gui.SendMessage(hwnd, win32con.CB_GETLBTEXT, itemIndex, linetext)
result.append(linetext[:linelength])
return result

Looks a bit like getEditText, doesn't it? I thought so - refactored version below:

def getMultipleWindowValues(hwnd, getCountMessage, getValueMessage):
result = []
bufferlength = struct.pack('i', 255)
count = win32gui.SendMessage(hwnd, getCountMessage, 0, 0)
for itemIndex in range(count):
value = bufferlength + "".ljust(253)
valueLength = win32gui.SendMessage(hwnd, getValueMessage, itemIndex, value)
result.append(value[:valueLength])
return result

def getComboboxItems(hwnd): return getMultipleWindowValues(hwnd, getCountMessage=win32con.CB_GETCOUNT, getValueMessage=win32con.CB_GETLBTEXT)
def getEditText(hwnd): return getMultipleWindowValues(hwnd, getCountMessage=win32con.EM_GETLINECOUNT, getValueMessage=win32con.EM_GETLINE)

Last thing today - selection a combo-box item.

def selectComboboxItem(hwnd, item):
win32gui.SendMessage(hwnd, win32con.CB_SETCURSEL, item, 0)
click(hwnd)
keystroke(hwnd, win32con.VK_RETURN)

def keystroke(hwnd, key):
win32gui.SendMessage(hwnd, win32con.WM_KEYDOWN, key, 0)
win32gui.SendMessage(hwnd, win32con.WM_KEYUP, key, 0)

I had hoped that the first of these messages would be enough. Unfortunately, it was not to be - while the selected item did change in the GUI, the application that I was automating didn't respond to the change without the click, and the drop-down list didn't disappear without the keystroke. If anyone can suggest a more elegant way of doing this, I'd be pleased to hear of it.

Here I put it all together

# Find the ACE window library selection combo
def findAceLibrarySelectionFunction(hwnd, windowText, windowClass): return windowClass == "ComboBox" and ("EVO1" in getComboboxItems(hwnd))
libCombo = findControl(findTopWindow(wantedText="ACE"), findAceLibrarySelectionFunction)

# Get a list of the combo items
items = getComboboxItems(libCombo)
print "Items: " + str(items)
import random

# Pick one at random, and select it
selectItemIndex = random.randrange(len(items))
print "Selecting: " + items[selectItemIndex]
selectComboboxItem(libCombo, selectItemIndex)

Well, that's just about it from me on this, really, though if anything else occurs to me, you'll be sure to know. ;-)

Update: See the whole series: Driving win32 GUIs with Python, part 1, Driving win32 GUIs with Python, part 2, Driving win32 GUIs with Python, part 3, Driving win32 GUIs with Python, part 4 and 7 hours, one line of code.

Posted to Python by Simon Brunning at 04:59 PM
Python: Multiple dispatch

Generalizing polymorphism with multimethods

Dive under the skin of OOP, see how it's done, and see how it can be done a little differently...

Via postneo.

Posted to Python by Simon Brunning at 12:49 PM
G.W. Bush's speech

Tonight, having grown tired of waiting for Jesus, Big Daddy and The Spook to get off their high horses, I have decided to act unilaterally to open the gates of Hell and bring about the apocalypse. I don't have to tell you how fucking "A" awesome this is. I say jump, and the Joint Chiefs of Staff cock and lock!

Hey, it's from the Whitehouse - it must be genuine!

It's well worth having a look round this site - it's hysterical. I particularly like Operation Infinite Purity: Winning the War on Masturbation, (a Democrat-created crisis), and Godly Tips on How to Punish and Beat Your Christian Child.

NB, I also like the fact that iSpell doesn't recognise 'Whitehouse', and suggested 'Whorehouse' as a correction.

Posted to Funny by Simon Brunning at 11:55 AM
No girls this weekend

Cath wants to keep them with her in Reading.

This is perfectly fair - after all, I get them most weekends. Cath needs some weekends to do stuff with them too. She has them during the week, of course, but during that time they are always rushing about, getting ready for school, or bed, or whatever. At the weekend, there is time to do stuff, and I'm lucky enough to get the lions share of that. Can't complain, can I?

But I still hate it. I never know what to do with myself at the weekend when I'm on my own.

I guess that I'll just have to get very drunk.

Posted to Apropos of nothing by Simon Brunning at 11:25 AM
The girls' boyfriends

I'm not allowed a girlfriend, but it seems that the girls are allowed boyfriends.

Freja (six) said that she did have a boyfriend, but that she "dumped him", (her exact words), because he kept "chasing" her. This doesn't refer to being too attentive, or making too many phone calls. No, he just chased her around the playground.

She says that she doesn't want a boyfriend any more - boys are "Yuck". That's my girl.

Ella (4 1/2) claims to have three boyfriends. It would be wrong of me to make any allusion to her mother at this point, so I won't.

Posted to Apropos of nothing by Simon Brunning at 09:18 AM
March 20, 2003
Driving win32 GUIs with Python, part 2

Finding the target control

See Driving win32 GUIs with Python, part 1

So, we have our list of top level windows. You'll need to choose which one to burrow into. Now, the window's text may be all you need to make this decision. Often it is. But another useful criterion can be the window's class. Whether or not you need to know a window's class now, it will certainly come in handy later.

Windows supplies a GetClassName() API, but unfortunately Mark Hammond's win32 extensions don't wrap this. So, we'll use Thomas Heller's ctypes module, instead. I'm using version 0.4.

A couple of warnings here. Once you start using stuff like ctypes and the win32 extensions, you can crash Python, hard. I mean really, really, time to re-boot, hard. After all, you are basically poking the operating system with a stick, as my colleague Dan memorably put it. This will come as no surprise to C and C++ users, but Python usually protects you from this sort of thing. Secondly, I lifted the code for class name retrieval from c.l.py, and I basically have no idea how it works. ;-)

Anyway, here is how we get a window's class name:

import ctypes

def getClassName(hwnd):
resultString = ctypes.c_string("\000" * 32)
ctypes.windll.user32.GetClassNameA(hwnd, resultString, len(resultString))
return resultString.value

We'll alter our window enumeration callback thing to get use this:

def windowEnumerationHandler(hwnd, resultList):
'''Pass to win32gui.EnumWindows() to generate list of window handle, window text, window class tuples.'''
resultList.append((hwnd, win32gui.GetWindowText(hwnd), getClassName(hwnd)))

Now we'll get the class name in our list of windows, too.

This is the function that I use to find the top level window that I want. You may want something a little different - you may want an exact text match rather than a starts-with match, for example - but I'll leave the details to you.

def findTopWindow(wantedText=None, wantedClass=None):
topWindows = []
win32gui.EnumWindows(windowEnumerationHandler, topWindows)
for hwnd, windowText, windowClass in topWindows:
if wantedText and not windowText.startswith(wantedText):
continue
if wantedClass and not windowClass == wantedClass:
continue
return hwnd

OK, so, you can do something like findTopWindow(wantedText="ACE") to get the window handle of the required to window. Once you have this, you can burrow into its child windows using the win32gui.EnumChildWindows() function. This works pretty much the same as the win32gui.EnumWindows(), with an additional argument specifying which window's children to process. Also, for reasons obscure to me, it occasionally throws a win32gui.error exception. I think that this happens if the window is unable to have child windows (as opposed to just not actually having any, when you just get an empty list), but that's pretty much a guess really. Since I never get this exception for windows that have children that I'm interested in, it's not a problem.

The other complication is that the child windows can have children of their own, so we need to be able to to recurse through the hierarchy to find the window we want.

Here's my function for locating a control. For maximum flexibility, it takes a selection function, which should be able to spot when the required control has been found.

def findControl(topHwnd, selectionFunction):
def searchChildWindows(currentHwnd):
childWindows = []
try:
win32gui.EnumChildWindows(currentHwnd, windowEnumerationHandler, childWindows)
except win32gui.error, exception:
# This seems to mean that the control does *cannot* have child windows
return
for childHwnd, windowText, windowClass in childWindows:
# print "Found ", childHwnd, windowText, windowClass
if selectionFunction(childHwnd, windowText, windowClass):
return childHwnd
else:
descendentMatchingHwnd = searchChildWindows(childHwnd)
if descendentMatchingHwnd:
return descendentMatchingHwnd
return

return searchChildWindows(topHwnd)



And here we use it:

optDialog = findTopWindow(wantedText="Options")
print optDialog
def findAButtonCalledOK(hwnd, windowText, windowClass):
return windowClass == "Button" and windowText == "OK"
okButton = findControl(optDialog, findAButtonCalledOK)

There - so now we can find the control we want to do something with. Next, I'll actually do something to it...

Update: See the whole series: Driving win32 GUIs with Python, part 1, Driving win32 GUIs with Python, part 2, Driving win32 GUIs with Python, part 3, Driving win32 GUIs with Python, part 4 and 7 hours, one line of code.

Posted to Python by Simon Brunning at 05:03 PM
Python UK Conference 2003

The Python UK Conference 2003. See you there!

Posted to Python by Simon Brunning at 04:20 PM
A nice little toy

Sizer - resize any window to an exact, predefined size.

Well, I think it's cool, anyway.

Via Sanjay.

Posted to Software by Simon Brunning at 04:15 PM
The Guinness Experiment

Steve and I will be conducting The Conclusive Guinness Experiment this coming Wednesday.

Additional volunteers welcome - we'll be at The Elusive Camel at seven. We'll be the two tallish chaps drinking too much Guinness.

Posted to Apropos of nothing by Simon Brunning at 12:16 PM
I *did* get a paper today...

... but it had been rendered pretty much obsolete by the night's events.

Ah well, it's got the telly times in it.

Posted to Apropos of nothing by Simon Brunning at 10:03 AM
March 19, 2003
First there were Freedom Fries...

Give it back!

I think that this is a joke, but you can never be too sure these days - a small but vocal number of Americans seem to have gone insane recently.

Via Pensieri di un minore lunatic.

Update: It gets better! Rep. Ginny Brown-Waite, R-Brooksville, plans to introduce a bill today proposing that the families of the thousands of soldiers, sailors and airmen buried in France and Belgium be allowed to dig up their remains and have them shipped home.

Posted to Funny by Simon Brunning at 04:56 PM
I'm not allowed a girlfriend

That's it, it's official. I'm single forever.

I was talking to Freja, my eldest (six) at the weekend. I can't remember how we got to this part of the conversation, but she told me that I was not allowed to have a girlfriend.

"Why is it that Mummy is allowed a boyfriend," I asked her, "but I'm not allowed a girlfriend?"

"But Daddy, Mummy needs a boyfriend."

I tried to pursue this further, but Freja said "I don't want to talk about it any more", and so that was that.

Posted to Apropos of nothing by Simon Brunning at 01:59 PM
Driving win32 GUIs with Python, part 1

I'm doing a lot of this at the moment, so I thought I'd jot down some of the stuff I've learnt. Certainly, I couldn't find any of this on the 'net at the moment.

I'm not going to post everything at once - I'll do it a piece at a time.

OK, so you are trying to automate some process, and one of the applications involved doesn't want to play. No COM automation, no command line, no nothing. You are going to have to drive its GUI.

One possibility (the first that I tried) is to use something like AutoIT. This (free) automation tool can drive a lot of things, and a COM control is provided, so you can script it all in Python. Problem is, if you push it too hard, the rough edges start to show. I find I need to reset the control (using the Init() method) all the time, or it would stop recognising windows. One of the applications I'm working with doesn't play by the Windows rules, and so not everything works. Lastly, it's inherently limited - you cannot, for example, use it to get the text from an edit control. For all these reasons, I frequently have to roll my own.

To run this lot, you'll need Python, and Mark Hammond's win32 stuff. I'm using version 2.2.2 and build 152 respectively, on NT 4 service pack 6. If any of this works (or doesn't) on other versions, I'd be grateful to know.

First step - before you can do anything with a GUI component, you'll have to find it. Bit of terminology or you - every Windows GUI component is a window, whatever it is; text area, application window, scroll bar, button, whatever, they are all windows. And each of them has a window handle (often called hwnd). Windows often live in other windows, and can contain yet more windows themselves, so we will end up getting all nasty and recursive. We'll start out by getting a list of the top level windows.

First, we'll import some stuff. We'll need all these modules eventually,

import win32api
import win32con
import win32gui

We are going to use the win32gui.EnumWindows() function to get our top level window information. This is one of those nasty functions which wants a callback function passed to it (consult the docs if you are really bored). So here's one I made earlier:

def windowEnumerationHandler(hwnd, resultList):
'''Pass to win32gui.EnumWindows() to generate list of window handle, window text tuples.'''
resultList.append((hwnd, win32gui.GetWindowText(hwnd)))

We can pass this, along a list to hold the results, into win32gui.EnumWindows(), as so:

topWindows = []
win32gui.EnumWindows(windowEnumerationHandler, topWindows)

Our topWindows list now contains an entry for each of the top level windows, probably quite a lot of them. Go on print it out. Each entry has the windows handle, and the window text, which we'll use to decide which top level window we are going to dig into. Once we have this, we'll use win32gui.EnumChildWindows() to burrow down to find whichever control we want to do something with.

But that's enough for one day...

Update: See the whole series: Driving win32 GUIs with Python, part 1, Driving win32 GUIs with Python, part 2, Driving win32 GUIs with Python, part 3, Driving win32 GUIs with Python, part 4 and 7 hours, one line of code.

Posted to Python by Simon Brunning at 01:50 PM
Java Extreme Programming Cookbook

O'Reilly's Java Extreme Programming Cookbook is out. Wort a look, I reckon.

The jUnit chapter is online, and had already given me some things to think about in terms of test naming standards and multi-threaded code testing.

One of the other chapters discusses GUI testing, so that'll be worth looking at too. One of my team has had a look at jfcUnit, but hasn't feed back to the team yet. My current project is very GUI heavy, being partly a pretty front end to a dog ugly (5250) green-screen application. Our current inability to auto-test our GUIs is causing us to spend a lot of time checking stuff manually, and inevitably, problems slip through anyway.

Posted to Java by Simon Brunning at 11:01 AM
No paper today

The newsagent at the station didn't have my newspaper this morning. Doesn't happen often, but it's bloody annoying when it does.

Didn't have a Grauniad, either. I don't mind taking the Grauniad occasionally. Makes a nice change. What's more, they've poached David Aaronovitch from the Independent.

But no, they only had the Tory rags, with which I would not soil my hands. (Though I must admit that my hands get pretty soiled reading the Independent - the newsprint makes my hands look like a miner's by the time I get to work.)

My deepest loathing, though, is reserved for the Devils Newspaper.

Posted to Apropos of nothing by Simon Brunning at 09:20 AM
March 18, 2003
The London Men's Self-Help Pub Crawl Group

London Men's Self-Help Pub Crawl Group

Funny.

I found beer in the evening's pub crawl generator from here. Cool. That's what I call technology for the benefit of man.

How cool is Google? Its web directory includes a London pub crawl page!

Posted to Funny by Simon Brunning at 05:47 PM
Short is staying after all

Clare Short says she'll stay.

Not for long, though, I'll be bound. She'll get the chop as soon as the dust settles. Blair won't trust her in future, and she'll have lost credibility amongst backbenchers, too.

Cook went, as predicted. Good speech, too.

Posted to The Big Room by Simon Brunning at 01:10 PM
Family Tech Support

Family Tech Support. Story of my life.

Posted to Funny by Simon Brunning at 12:49 PM
You can't get drunk on Guinness

More evidence that you can't get drunk on Guinness.

Much Guinness was drunk last night. I was not.

This can't really be considered a conclusive experiment, though. The experiment's data was somewhat muddied by two complicating factors: On the one hand, I hadn't eaten. But then, you don't need to eat when drinking Guinness. Steak, egg and chips in a glass.

On the other hand, it was taking quarter of an hour or so to get served. A man can sober up in that length of time! I'm not sure if the Irish dancers had any effect one way or the other, to be honest. But I won't be going to see Riverdance, I can tell you.

All in all, I think further research is required. And I think I know just the man to help.

Posted to Apropos of nothing by Simon Brunning at 09:30 AM
March 17, 2003
It's a question of when, not if

Iraq diplomacy collapses

Emergency cabinet meeting called

We can expect that Robin Cook will go. As will Claire Short, if the has an ounce of integrity, which I think she does. Military action, what, tomorrow, Wednesday?

After that, who can say? I should imagine that the US will go through the desert quick enough - air power will see to that. But once they hit the cities, it could be really bad. If the Iraqi troops put up a real fight in the cities, the casualties will be horrendous, both military and civilian.

But will they? Obviously I hope not, but it's possible. Perhaps the Iraqi military feel that if they inflict sufficient casualties the allies will be forced to pack up and go home, a-la Vietnam. Given the lack of domestic support, this isn't totally impossible.

But I certainly hope the whole thing is over quickly. As always in modern war, it's going to be the civilians who bear the brunt of all this. It's at times like this that I wish I had someone to prey to.

Time to re-link to the classic God Angrily Clarifies 'Don't Kill' Rule.

Posted to The Big Room by Simon Brunning at 04:31 PM
Struts Action Scripting

Struts Action Scripting

Write Struts actions in your language of choice.

Via Daily Python-URL.

Posted to Python by Simon Brunning at 01:33 PM
St. Patrick's Day

A happy St. Patrick's Day (aka The Reinforcin' O' The Stereotypes) to all my imaginary readers.

My friend Steve and I once proved beyond doubt that it was impossible to get drunk on Guinness. Stella yes, Guinness no.

On the other hand, I've been finding that it's having more of an effect on me than it used to. I can only surmise that they are making it stronger these days. Anyway, time to re-test the theory, I think.

I'll be in O'Neill's in Muswell Hill, which bizarrely doesn't seem to have a web site. How 20th century! I'd buy you a pint, only you'd never recognise me.

Posted to Apropos of nothing by Simon Brunning at 12:29 PM
You'd have thought that they'd have told someone

According to CoopBlog, the HMS Belfast is 65 today, and as part of the celebration she will fire her guns at 11 a.m. and 2 p.m. (The Belfast will, that is, not CoopBlog's author.)

The Belfast is moored on the Thames on the southern edge of The City Of London, (London's financial district) where I work. Now, what with Mr. bin Laden still running around, and Mr. Blair and friends on the verge of bombing the fuck out of Iraq, we are all a little nervy around here. Surely they ought to have told a few people about this - unexpected explosions are going to scare the crap out of everyone.

Having said that, it's now twenty past eleven, and I didn't hear anything. ;-)

Posted to Apropos of nothing by Simon Brunning at 11:20 AM
March 14, 2003
GTA

Got a fat pipe? (Easy.) If so, get GTA (the original) here, for free. All 300+ MB of it.

Fab game, much better than GTA2. I've not played III or Vice City, so no comment there.

Posted to Toys and games by Simon Brunning at 04:31 PM
Have one on us!

Last night, as I was walking past my local, a sheaf of 'Have one on us' vouchers was thrust into my top pocket. I think that each punter was only supposed to get one each, but hey, I'm a regular.

Each voucher entitled you to a free pint of Guinness. I was planning on going straight home, but, well, if would have been rude, wouldn't it?

I have a headache today.

Posted to Apropos of nothing by Simon Brunning at 12:28 PM
March 13, 2003
The Standard Python Library

The effbot is putting The Standard Python Library online.

This is going to be dead handy, even for those of us who have the dead-tree edition. The latter is best for reading on the tube. Or toilet. (Sorry.) But I can't cart all my books everywhere I go. I can carry a CD easily. I have an 'essentials' CD, containing everything I wouldn't want to do without - utilities, Python, Java, IDEs, packages, tools & documentation. The Standard Python Library is going on that.

With luck, putting the electronic version online might boost sales of the dead-tree version, too. It worked for Bruce Eckel.

Posted to Python by Simon Brunning at 05:03 PM
jEdit 4.1

jEdit is my text-editor-of-choice, and the new version, 4.1, is out.

I've not come across much new in it, but it's very pretty. ;-)

Not that I use it for coding - for that I use Eclipe (2.1 RC2 out recently), and PythonWin. But there are endless other text files to hack on, and jEdit is just perfect. Its XML handling is particulary good.

Posted to Software by Simon Brunning at 02:21 PM
Paper CD case

Paper CD case

Use this website to create a PDF file which can be printed and folded to create a paper CD case. Both cool and useful. Bit of a bugger to get the hang of - I found step 5 particularly troublesome. But worth it in the end.

Via DUTCHBINT.ORG.

Posted to Apropos of nothing by Simon Brunning at 02:06 PM
Kevin Cement

Welcome to the world of blogging, Kelvin!

A few things. Firstly, get ieSpell installed ASAP. ;-)

Secondly, you don't seem to have set yourself up a blog title - look at IE's title bar, and you'll see what I mean.

Lastly, since Mike Bruce is one of the nicest people I've had the privilege to work with, I can only assume that there was some lapse in communication somewhere along the line. My theory is that the recruitment consultant saw the, uh, the name of our erstwhile employer on your CV, and sent it off to Mike on this basis despite that fact that the job was wrong for you. Rather than admit to this, the recruitment consultant laid the blame at Mike's door. Recruitment consultants are lying bastards, you know.

The one consolation of the shocking state of the IT job market at the moment is that the recruitment consultants have it worse than we do. ;-)

Good luck with the Milton Kenyes thing, by the way.

Posted to Blogs by Simon Brunning at 01:59 PM
SVoC out of order...

A couple of days ago, the Movable Type instance that I'm running this blog on started throwing lots of nasty Perl-type error messages whenever I tried to do anything. I had assumed that something was corrupted somewhere.

But today, it sprang into life again. Perhaps my host, 1&1, were mucking about with their Perl installation, or something.

Any road up, now that SVoC is back up again, I'm in much less of a hurry to move away from Movable Type than I was over the last couple of days, but I still think I will. Why? A couple of reasons. Partly, I've been unable to to donate, and I feel a little guilty about using it without paying for it. Only a little, 'cos I've tried to pay for it, but still.

The other reason is that If I use a Python-written OSS blogger, I'll be able to add any functionality that I want, and perhaps fix it if it goes wrong.

Vellum looks nice.

Posted to Blogs by Simon Brunning at 01:40 PM
March 10, 2003
Which AD&D character class am I?

I Am A: Neutral Good Elf Bard Mage


Alignment:
Neutral Good characters believe in the power of good above all else. They will work to make the world a better place, and will do whatever is necessary to bring that about, whether it goes for or against whatever is considered 'normal'.


Race:
Elves are the eldest of all races, although they are generally a bit smaller than humans. They are generally well-cultured, artistic, easy-going, and because of their long lives, unconcerned with day-to-day activities that other races frequently concern themselves with. Elves are, effectively, immortal, although they can be killed. After a thousand years or so, they simply pass on to the next plane of existance.


Primary Class:
Bards are the entertainers. They sing, dance, and play instruments to make other people happy, and, frequently, make money. They also tend to dabble in magic a bit.


Secondary Class:
Mages harness the magical energies for their own use. Spells, spell books, and long hours in the library are their loves. While often not physically strong, their mental talents can make up for this.


Find out What D&D Character Are You?, courtesy ofNeppyMan (e-mail)

How nerdy can you get? Excellent!

Posted to Funny by Simon Brunning at 02:36 PM
I'm back

I'l write about my time in Madrid later. Just right now, I have about a million emails in my inbox to read.

Later.

Posted to Apropos of nothing by Simon Brunning at 01:31 PM