October 08, 2008
London Python meetup today

It's the London Python meetup this evening. See you there!

Posted by Simon Brunning at 01:18 PM | Permalink | Comments (4)
September 12, 2008
Off to PyCon UK

See you there.

I might even see one or two people at my talk, if I'm lucky. Though since I'm clashing with Simon Willison, I don't expect many.

BTW, we still need more session chairs. Don't be shy!

Slides here.

Posted by Simon Brunning at 04:58 PM | Permalink | Comments (2)
September 04, 2008
Django 1.0

Congratulations to everyone involved in getting Django 1.0 out of the door. Great job.

Posted by Simon Brunning at 03:40 PM | Permalink | Comments (2)
Apress eBooks

Buy a book from Apress (such as the superb Definitive Guide to Django) and you can get the PDF version for a fiver, so you can keep a copy on your laptop when you are on the road.

What a great idea. I don't want only the PDF - I much prefer to read the dead tree edition. But you can't carry dozens of chunky tech books around with you, so I want the PDF too. Clearly I shouldn't have to pay full whack twice, but the fiver that Apress is asking seems fair.

I wish O'Reilly did this.

Posted by Simon Brunning at 03:29 PM | Permalink | Comments (5)
My Work Here is Done

I was just called over by Ken and Grant to help them with a problem that they were having with the unittest/Mox test suite that they were putting together, written ahead of the functional code. I feel so proud.

Posted by Simon Brunning at 03:15 PM | Permalink | Comments (1)
August 22, 2008
Welcome, Simon!

Welcome to the Guardian, Simon! I only wish I'd still be there when you started, but I'll be gone by then. :-(

Posted by Simon Brunning at 06:03 PM | Permalink | Comments (2)
August 19, 2008
London Python meetup, September the 2nd.

Time for another London Python meetup, pre-PyCon UK 2008.

PyCon UK 2008, at which I find myself the "Session Chair Team Captain", God help them. Given how rubbish I am at organizing London Python, I do hope I can pick my game up a bit.

Posted by Simon Brunning at 11:08 PM | Permalink | Comments (1)
Python Mock Frameworks

Given that I'm speaking on Python mocking shortly, I thought I'd better dig through my accumulated bookmarks and see what I'm missing.

PyMock is what I've been using up till now. It's heavily inspired by EasyMock, a mocking style I'm used to. It's pretty good, really. The docs really could be better, and the failure messages are not very helpful, but it does the job.

But then I found Mox. Superficially, it's very similar to PyMock. It's also based on EasyMock. But wherever Mox does differ from PyMock, it's better.

It's much better documented than PyDoc, and has more meaningful, helpful failure messages. I think it's has more functionality, too, with some nice comparators, side effects and callbacks. StubOutWithMock() is nice too. But it's possible that PyMock has all of this - given the documentation, it's hard to tell.

Mox will warn you if you call a method on a mock that the mocked class doesn't have, which is handy. It can get confused if your mocked class uses delegation, but you can always fall back to MockAnything(). The mailing list is small but helpful.

On the downside, Mox isn't in PyPI, which is a shame. And they missed a trick not calling the documentation MoxDox. ;-)

There are many other Python mocking packages out there, too - notably pMock, a jMock style mocking library, Mock and minimock, a mocking library for the doctest unit test library.

In early development there's Mockito For Python, a port of Mockito, which will be worth keeping an eye on if Szczepan ever gets the hang of Python. ;-)

As an aside - I think we need Spamcrest!

Update: Seems there's already a Hamcrest for Python - source here.

Also - I forgot one other problem with Mox - the naming standards. One of my biggest early stumbling blocks was that my brain refused to see the the initial capital on the AndReturn() method, and I couldn't get anything working. It's Google's internal naming standard, I gather. Yuck. I feel a patch with PEP 8 style synonyms coming on.

Posted by Simon Brunning at 08:59 PM | Permalink | Comments (2)
July 30, 2008
Also Scary

My PyCon UK talk hass been accepted. It's even considered notable!. ;-)

Posted by Simon Brunning at 10:38 AM | Permalink | Comments (2)
July 18, 2008
Code Swarm

code_swarm - Python from Michael Ogawa on Vimeo.

I so want to run this over my current project.

Posted by Simon Brunning at 10:08 AM | Permalink | Comments (2)
June 10, 2008
Adrian Holovaty at the Guardian

I was well aware that Adrian Holovaty is a very big name in the Python world. He's one of the two original developers of Django (my personal favorite web-app development framework) about which he's written the book. He's since used it to power some very cool mashups; chicagocrime.org and everyblock.com, amongst others.

What I didn't know is that he's also well known and regarded by forward-looking journalists. Emily Bell's introduction to his talk at the Guardian set me straight.

Adrian's talk was inspiring, both to the few techies in attendance and to most of the journalists, who made up the bulk of the audience. His central idea is that we should ensure that the information that the journalists have collected is stored in a structured way wherever possible. It's hard, skilled work gathering that valuable information, but full use is not being made of it. If it were stored in a structured fashion (rather than just in the text of a story; in a "blob" as Adrian put it) it could be made use of in many different ways.

A great example of this is Faces of the Fallen. The information here is gathered by the journalists, but it can be explored in many different ways; by age, birthplace, all sorts of things.

Another interesting strand to Adrian's talk was the automated collection of data. The Washington Post runs a congressional voting record site, almost all the data for which is collected automatically. everyblock.com is another example of this kind of thing.

Explorability is crucial. Think how often you get stuck in the Wikipedia, 'cos there are just so many interesting links to follow. You go in to read one article, and find yourself with half a dozen tabs open all containing apparently unrelated corners of the 'pedia that you've stumbled upon, all of which you want to read. Don't you want your site to be like that?

Jemima Kiss has written up Adrian's talk better than I ever could here: Future of Journalism: Adrian Holovaty's vision for data-friendly journalists. Well, she is a pro.

Then, after work, Adrian, Julia and I headed off to Le QuecumBar for some disappointingly inauthentic Gypsy Jazz.

Posted by Simon Brunning at 02:32 PM | Permalink | Comments (0)
May 28, 2008
Mock the Weak

I seem to find myself signed up to talk at PyCon UK on Mock Testing with Python. Eeeek!

Luckily, this evening I'll be at London Geek Night: Mocking with Java, so I should be able to pick up some tips.

Posted by Simon Brunning at 04:10 PM | Permalink | Comments (2)
May 06, 2008
Python Meetup Tonight!

Python Meetup in London tonight. See you there!

Posted by Simon Brunning at 07:22 AM | Permalink | Comments (1)
April 21, 2008
import soul

Python has a module for everything.

Posted by Simon Brunning at 10:56 AM | Permalink | Comments (1)
April 15, 2008
A new role...

Looks like I've been outed.

Posted by Simon Brunning at 09:49 AM | Permalink | Comments (7)
April 09, 2008
Google App Engine Roundup

Loads of stuff in the blogsphere about the Google App Engine, unsurprisingly, some of it even worth reading.

So, it's looking good, though I'm still concerned about lock-in. It's not just the Datastore API which locks you in - that's probably fairly east to emulate - but also the Authentication and Authorization API, which looks much trickier.

Update: As Ade says, you certainly don't have to lock yourself in to GAE's Users API.

Posted by Simon Brunning at 01:00 PM | Permalink | Comments (4)
April 08, 2008
Google App Engine

The Python blogsphere has been exploding with the news of the Google App Engine today. And fascinating it is too - free hosting for Python web apps, Django included. With the might of Google behind it, this will push Python big style. Take that, Rails hype!

I'm a bit uneasy about the datastore, though. Not only does this gut any existing Django app, it also any means that any app that you write that persists data (read - non-toy) will be bound to the GAE API. What's wrong with a real database?

Naturally, I've signed up already. ;-)

Posted by Simon Brunning at 03:33 PM | Permalink | Comments (3)
February 18, 2008
Top-and-tailing log files

Some of our log files are huge - I have a 10 GB file on my HDD right now. These files are unwieldy to say the least, and you usually have a good idea as to the time in which a particular problem occurred, so it's often handy to be able to chop out a specified time range. I keep forgetting how to do this, and re-inventing the process. So, here for my own benefit at a couple of methods.

The hard way

From the bash shell:

wc -l your.log

This will count the lines in your file.

grep -n 12:00: your.log | head -n 1

This will give you the line number of the 1st line containing "12:00:" - in this example, I want log entries starting at midday, so this is the first line that I want.

grep -n 12:10: your.log | tail -n 1

This will give you the line number of the 1st line containing "12:10:" - in this example, I want log entries up to ten past twelve, so this is the last line that I want.

tail -n $[total-first] your.log | head -n $[total-last] > your_focused.log

Replace first, last and total with the values you got above, and you'll end up with a file containing only the time range that you wanted. (If you only want to look at the file once, you can just pipe into less or whatever rather than piping into an output file.)

The easy way

python -c "import itertools, sys; sys.stdout.writelines(itertools.takewhile(lambda item: not '12:10:' in item, itertools.dropwhile(lambda item: not '12:00:' in item, open('your.log'))))" > your_focused.log

Same thing, only this will read through the file just once.

Now, I'm fully expecting someone to come and tell me the real easy way. ;-)

Posted by Simon Brunning at 12:25 PM | Permalink | Comments (16)
January 01, 2008
Bitter at all?

Thanks to Jay for pointing out this rant, via reddit.

Now, I'm sorry they guy can't get a job, but if this is his attitude, I can't say I'm surprised. He's burned his bridges with ThoughtWorks, for a start. ;-)

Disclaimer - I work for ThoughtWorks. But I can say that with perfect honestly that his impression of TW doesn't mesh with mine. Thing is, he seems to think that what TW sells is platform expertise. It's not. We primarily sell smart people. (Oh, and me, too.) A smart person will pick up a new platform quickly. If that's not possible with Rails, that that's Rail's problem - not that I believe that to be the case. Yes, you do need a cadre of people with platform experience for a project to succeed, but not the whole team. (Perhaps he'd have better luck job hunting if he didn't restrict himself exclusively to Rails?)

He says that TW leaves bad code bases behind. Again, in my limited experience, that's not true at all. TWers seem to care deeply about what they do. Anyone else out there who doesn't work for TW who has any experiences they'd care to hare?

Also, his dismissal of TDD and agile practices such as pair programming suggests to me that he's not really tried them. We at TW have a lot of experience in these areas, and it all works just fine for us. If he claims to have improved productivity by dropping them, then he's clearly not comparing like-for-like. Done properly, I fervently believe that these practices improve productivity in the long term (if not in the short term).

I do wish we used more Django and less Rails, though. ;-)

Posted by Simon Brunning at 05:58 PM | Permalink | Comments (8)
December 05, 2007
Programming is fun again!

You're flying? How? Python.

I so need this as a tee-shirt.

And what timing!

Creative Commons License

This work is licensed under a Creative Commons Attribution-NonCommercial 2.5 License.

This means you're free to copy and share these comics (but not to sell them). More details.

Posted by Simon Brunning at 09:43 AM | Permalink | Comments (2)
December 04, 2007
Beer and Geeks

Busy week - XTC today and London Python tomorrow.

Posted by Simon Brunning at 09:55 AM | Permalink | Comments (3)
November 30, 2007
Orrible Strikes Again

I wasted a good couple of hours today trying to get cx_Oracle running on my Mac. I didn't have any luck - Oracle's Mac client is PPC only. You can still run it in an Intel Mac due to the magic of Rosetta, but you don't seem to be able to compile against it, so these instructions don't work for me.

Anyone got a binary I can snarf?

Posted by Simon Brunning at 04:24 PM | Permalink | Comments (3)
November 26, 2007
Agile in the Large

What if powerful languages and idioms only work for small teams? (via Small teams and big jobs) is interesting. We are running a really large Agile project here at GU; what, 60 odd people? Mention any of the road bumps you hit, and people tell you your team's too large.

That's no good. The team, and the project, are the size they need to be. Splitting them arbitrarily might be possible, but it would carry huge costs of its own. The challenge is to make agile work with a big team. And on the whole, I think we are.

Interestingly, despite the fact that we've made agile methodologies scale up, some people here are still nervous about whether agile languages can do the same. Plus ca change...

Posted by Simon Brunning at 09:49 AM | Permalink | Comments (14)
November 21, 2007
Subversion Log Filtering

So, Annabel was complaining that she couldn't see a log of just her Subversion revisions along with details of the files that have changed from the command line. Shock horror - something you can do from Tortoise that you can't easily do from the shell!

(If you don't care about seeing a list of the files that have been changed, you can just do svn log | grep -A2 sbrunning | less, but adding the -v option turns the output to gibberish.)

Clearly I wasn't going to to let that stand, so I knocked up a very quick script. Then proceeded to over-engineer the snot out of it. (In my own time I must add.)

You can filter by author or by checkin message, with regexps. You can also reverse the output and see the latest checkin last, which is handy if you are only want to see the most recent checkins and don't want to pipe the output to less.

Get it here: svnlog (syntax highlighed - loving that Django TextMate theme) or svnlog (text). Requires Python 2.5. Works on Mac & Linux, probably on Windows too if you give it a .py suffix.

Posted by Simon Brunning at 06:05 PM | Permalink | Comments (4)
Return Triumphant, Or Not At All

Returning None is Evil. I agree. I've always subscribed to the Samurai Principle myself. If you allow nulls to float around you inevitably end up with NPEs. These can be hard to diagnose properly; not only do you not know if null is actually invalid, but if it is, it's often non-trivial to work out where it came from.

Posted by Simon Brunning at 10:28 AM | Permalink | Comments (3)
November 20, 2007
Mocks and Stubs and Fakes, Oh My!

Fuzzyman has a new mocking library for Python, which he presents in Mocking, Patching, Stubbing: all that Stuff.

Michael takes issue with Martin Fowler's Mocks Aren't Stubs; specifically where he defines mocks as objects pre-programmed with expectations which form a specification of the calls they are expected to receive. Michael's mocks are not pre-programmed with expectations - his expectations are defined after the test execution.

Now, to me, this is a trivial distinction - the important difference between a stub and a mock is in the existence of expectations. Whether the expectations are defined before or after the text execution is not crucial - it's still a mock.

It does matter in terms or usability, of course. It feels more natural to Michael to define his expectations after the test object is exercised, along with his assertions. For me, I have to say that defining the mock object's behaviors all in one place makes sense, so both the expected method calls and any return values should defined together - and the return values have to be pre-defined. We are using EasyMock here at GU (along with the Hamcrest constraints library) and I like it just fine. But that's more a matter of taste than anything else.

Posted by Simon Brunning at 03:26 PM | Permalink | Comments (2)
November 13, 2007
London Python meetup, Wednesday, December the 5th

ThoughtWorks have given me the go-ahead to organise another Python meetup at the London office. Thanks, guys!

Details here - London Python meetup, Wednesday, December the 5th.

Posted by Simon Brunning at 02:29 PM | Permalink | Comments (0)
November 01, 2007
Coverage Tools

Julian and I have been asked to put together some unit and functional test coverage figures. We've not actually been given any time in which to do it, though, so I wouldn't hold your breath.

Looks like some work was put into using Emma to provide these figures, but it's not finished.

Over in the Python world, there's been some discussion over on c.l.py about Ned Batchelder's coverage.py, which looks like a fairly nifty module.

OTOH, I think you have to be a bit careful with metrics such as those provided by these coverage tools. Ned himself points out many of the problems with taking your coverage figures at face value (though Emma's block-level approach fixes some of them).

I'd add one more issue - gaming. People can start to see good coverage figures as an end in and of themselves. If the coverage isn't at, oh, say 80%, the tests must be crap. If they are at 100%, they must be great. It's not just that the figures can be meaningless, they can actually lead people astray.

Now, for an approach to coverage testing that actually makes sure you are testing that your code does the right thing, check out Jester & Pester.

Posted by Simon Brunning at 06:26 PM | Permalink | Comments (3)

I've never been too intimidated by driving Subversion from the command line, so I've always maintained my branches by hand, keeping note of what had been merged in the check-in messages. But today Graham Tackley recommended I take a look at svnmerge. I must say, I didn't know what I was missing.

It keeps track of merges for you, ensuring that you'll never try to merge the same revision more than once, or miss any out by accident. Makes it easy to block revisions that you don't want to merge, too. Give it a try.

Don't forget - you'll need a decent merge tool, too

Posted by Simon Brunning at 12:39 PM | Permalink | Comments (3)
October 31, 2007
The Leopard and The Snake

Java may not be getting much Apple love, at least not for the moment, but the better language sure is. ;-)

Also Leopard has built-in Subversion, including Python bindings, and ssh key management too. Sweet.

Just as soon as they get Java up to spec, looks like I'll be jumping.

Update: And perhaps Java on Leopard isn't looking so bad after all.

Posted by Simon Brunning at 06:19 PM | Permalink | Comments (4)
October 16, 2007
Jython 2.2.1

Jython 2.2.1 is out. It's fabulous to see Jython really making strides again. I used Jython 2.1 for years, and it worked just fine, but somehow if people don't see an OSS project making regular releases they somehow assume that they should steer clear, regardless of the quality of the existing software.

And I must say that while the missing new Python features were never a show stopper, it'll be nice to have them.

Posted by Simon Brunning at 02:09 PM | Permalink | Comments (1)
October 11, 2007
London Python last night

London Python went well last night - more here.

Posted by Simon Brunning at 02:59 PM | Permalink | Comments (0)
October 09, 2007
London Python meetup tomorrow

I've arranged a London Python meetup tomorrow evening. See some of you there!

Posted by Simon Brunning at 01:41 PM | Permalink | Comments (3)
February 27, 2007
London Java meetup tonight

I'll be at Jez's London Java meetup this evening. I've not been to one for ages - not since September - so I'm really looking forward to it.

Provided, that is, that they won't talk about bloody Groovy all night. I've still yet to be convinced that Groovy has anything that Jython didn't have nearly ten years ago. Apart from closures and inelegant syntax, that is. ;-)

A new venue this time - it's at The Crown Tavern, EC1R 0EG.

Update: Seems Jython was around exactly ten years ago.

Posted by Simon Brunning at 10:10 AM | Permalink | Comments (6)
February 21, 2007
London Python meetup tonight

Don't forget the London Python meetup tonight. The bloody football's on again (does it never end?) so it'll be heaving. But then, so will everywhere else.

Update: Right, I'm off.

Posted by Simon Brunning at 01:29 PM | Permalink | Comments (1)
February 06, 2007
PyCamp UK

Oooh, exciting, Michael Sparks (of Kamaelia fame) is thinking about organising a UK PyCamp. If the dates are right, I'm there.

Posted by Simon Brunning at 04:40 PM | Permalink | Comments (3)
February 01, 2007
Python meetup, Wednesday the 21st of February

I've arranged another Python meetup for Wednesday the 21st of February at The Porterhouse, Covent Garden. See London Python Announce for details. Err, not that there are any more details than I've just given you. ;-)

We had around thirty people last time, so fingers crossed for another good one.

Posted by Simon Brunning at 05:26 PM | Permalink | Comments (6)
November 15, 2006
I'm off

Right; I'm off to the London Python meetup. See you there.

Posted by Simon Brunning at 05:09 PM | Permalink | Comments (2)
London Python Announce

Sam recently set up the London 2.0 Community Portal. It occurred to me that we London Pythonistas could really do with a site of our own, and since Menno had already set up Planet London Python, with hosting and domain provided by Remi at Web Faction, so I thought I'd ask if it could be hosted there.

So, here's London Python Announce, the London Python event portal.

By the way, I'd seen the screencast of Web Faction's control panel before - but everything looks good in a demo. ;-) Now I've tried the real thing, and it's almost too easy. El Presidente watched over my shoulder, and he thinks that even he could set it up.

Posted by Simon Brunning at 01:44 PM | Permalink | Comments (2)
November 06, 2006
London 2.0 RC 9

Right, I'm off to London 2.0, via a spot of CD and book shopping. I'll see a few of you there, no doubt.

Posted by Simon Brunning at 04:54 PM | Permalink | Comments (1)
London Python Meetup next week

Time to select a venue for next week's London Python meetup on Wednesday (the 15th). I was thinking of trying The Porterhouse in Covent Garden for a change. The place is vast, so there should be no problem getting a table or two so long as I get there reasonably early, and it's pretty central. Worth giving it a go, I reckon.

All welcome, from Python gurus to the merely curious. Please leave a comment if you are thinking of coming.

BTW, to be reminded of this and any other London Python meetup, try this:

Posted by Simon Brunning at 12:10 PM | Permalink | Comments (12)
October 13, 2006
Merge tools

If you are going to be doing a lot of merging working with Subversion (or, I'd imagine, CVS), you are going to need good a good merge tool. And believe me, you are going to be doing a lot of merging.

Subversion itself doesn't provide a merge tool - and nor should it. It's a cross-platform command line driven tool, and besides, I suspect that most developers have their own favourite - or need to find one quickly.

If you are working on Windows, you'll probably have Tortoise installed, 'cos it's really good for simple stuff. Tortoise does come with a merge tool, but it's horrid, really nasty. Aside from just how damn ugly the thing is, it's also almost totally incomprehensible. All those colours - what do they mean?

But that's OK. There are alternatives, and they are easy enough to integrate into Tortoise. The first thing I came across was WinMerge. WinMerge is very good for showing diffs, but it doesn't (as yet) do three way merging - so that's out. Another, more powerful alternative is KDiff3. By the time I came across this, I'd already made my happy move to the Mac, so I've not used it myself, but my Windows-victim colleagues report that it works fine.

So the trick is to use the tool with diff in the name for merging, and the tool with merge in the name for diffing. ;-)

Tortoise also provides tools for making and applying patches, but they seem to use fully-qualified path names, so you can't apply patches from one machine to another unless it happens to keep everything in the same place. So, it's best to use Subversion to make your patches with svn patch > whatever.patch to make your patches (or svn st | awk '/^\s?[MAD]/ { print $NF } ' | xargs svn diff > whatever.patch if you've made the same externals mistake that I did), and to use unxutils' patch to apply them.

In the Mac, there's a natural solution - FileMerge, part of the XCode suite. It's very nice to use, if not perfect. (A few more keyboard shortcuts would be nice, for example, Apple, Just 'cos it's GUIfied and beautiful doesn't mean I should be reaching for the mouse all the time.) Integrating it with command line Subversion would be non-trivial but for Bruno De Fraine's lovely Using FileMerge as a diff command for Subversion - he's done all the hard work for you. Thanks for that, Bruno.

Oh, SubClipse also provides a merging tool, but I've never really used it. It's nice to have SubClipse around - the fact that it decorates all your files showing you their status against the repository is nice, and I often use it to add files - quicker than an svd add if you are in the IDE already. But IDE/version control integration is far less crucial than it used to be in the bad old VSS days when you couldn't edit a file without checking it out, so I do most of my Subversion tasks from the command line.

I'd be interested to know what all you *nix types use - especially anything console based.

Have I missed anything cool?

Posted by Simon Brunning at 08:27 PM | Permalink | Comments (16)
October 09, 2006
November London Python meetup

There were some people who weren't able to make it to last week's restrained and dignified London Python meetup, 'cos it hadn't been arranged sufficiently far in advance, so I'm planning the next one now. It'll be on Wednesday the 15th of November.

I'll announce a venue a bit nearer the time. The Stage Door is a very nice pub, but it's a bit small, and sometimes very noisy, so I'm looking for somewhere a but more suitable for a techie meetup. Any suggestions? (No, not the bloody Bank of England.)

If it were to be a good distance from anywhere that's open 'till the small hours selling cocktails and containing femme fatale redheads, that would be an advantage.

Please add a comment if you think you might be coming.

Posted by Simon Brunning at 05:16 PM | Permalink | Comments (12)
Planet London Python

A big thank you to Menno Smits and Remi Delon for setting up and hosting Planet London Python! Now we'll have even more to natter about at the next London Python meetup.

I've sent Menno a bunch of URLs - at the moment, it seems to be mostly my blatherings up there, and no body wants that.

Update: Blimey, that was quick. Menno had the new feeds up in seconds flat.

Further update: There's a new URL for this: http://londonpython.org.uk/.

Posted by Simon Brunning at 02:57 PM | Permalink | Comments (1)
October 05, 2006
The joy of os.walk()

One thing that came up yesterday was that people still aren't feeling comfortable with os.walk(). Which is a shame - I love it. I mentioned that I'd used it only that day, in a nice little script that locates malformed XML in a directory tree, and Simon suggested that I post it. So, here it is:

for path, dirs, files in os.walk(os.getcwd()):
    for xml in [os.path.abspath(os.path.join(path, filename)) for filename in files if fnmatch.fnmatch(filename, '*.xml')]:
        except (SyntaxError, ExpatError):
            print xml, "\tBADLY FORMED!"

Syntax highlighted version, with imports: find_dodgy_xml.py.

Notice that it takes more code to import ElementTree than it does to do the actual work! It'll be nice what we can rely on version 2.5 being available, but that's a while away.

Hmm, actually, this is such a common pattern that it's probably worth a helper function:

def locate(pattern, root=os.getcwd()):
    for path, dirs, files in os.walk(root):
        for filename in [os.path.abspath(os.path.join(path, filename)) for filename in files if fnmatch.fnmatch(filename, pattern)]:
            yield filename

Syntax highlighted version: locate.py.

This simplifies the main loop to:

for xml in locate("*.xml"):
    except (SyntaxError, ExpatError):
        print xml, "\tBADLY FORMED!"

Worth a cookbook recipe, or is it too simple?

Posted by Simon Brunning at 04:20 PM | Permalink | Comments (13)
Yesterday's Python booze-up

A good Python booze-up last night. No Steve Holden, but a very good crowd, including Simon Willison, Tim Couper, Remi Delon, Chris Miles, Fuzzyman with a couple of his colleagues, Menno Smits, Ben Sanders, Ryan someone-or-other and loads of other people, some of whose names I might even remember at some point. Topics of conversation included XML libraries, Steve Irwin, DVD piracy (theoretical and applied), the Python job market, JavaScript, os.walk and the path module, some Web 2.0 malarkey that I only caught the tail end of and didn't understand a word of, the Python, Ruby and Perl communities compared and contrasted, PyCon and EuroPython, and embarrassing drinking events - I'm sure that more will come back to me later.

As per usual, Chris made us all go to Cubana after the pub closed for several jugs of daiquiris and mojitos, and some very odd shooters.

We also bumped into a girl who was a dead ringer for the lovely Geraldine Somerville. I was convinced it was actually her, but alcohol may have been a factor there.

I felt fine this morning, strangely enough, though I did sleep through my alarm. I'm just too old for this two in the morning business these days.

Photos forthcoming, when Chris recovers from his hangover and emails them to me.

If you were there, please identify yourself!

Posted by Simon Brunning at 03:08 PM | Permalink | Comments (4)
Python in a Nutshell

I picked up the 2nd edition of Python in a Nutshell by Alex Martelli, Python's very own Umberto Eco. (I donated my 1st edition to my Padawan, Dan.) As expected, there's not that much changed - a few new string methods there, a new module or two there.

But one thing I was hoping for was some ElementTree coverage. The 2nd edition only covers Python 2.4 rather than 2.5, and ElementTree wasn't yet part of the standard library at that point, but ElementTree has been a hugely popular library for a while, so it's a pity it wasn't included. It's my XML API of choice, and chatting to Simon and others at last night's Python booze-up, I'm far from alone. (Tim prefers 4suite, though. To each his own, I suppose.)

Still, all in all, a must-have book. I'm not sure I'd say an upgrade is essential, though, if you have the 1st edition.

Posted by Simon Brunning at 01:28 PM | Permalink | Comments (2)
October 04, 2006
Off to the London Python meetup

Right, I'm off to the London Python Meetup. It's at The Stage Door, but Cubana is nearby, Chris Miles is going, and he's such a bad infuence. So, wish me luck...

Posted by Simon Brunning at 04:57 PM | Permalink | Comments (0)
Emacs and me

There's a discussion going on at the moment concerning refactoring dynamic languages. For whatever reason, its protagonists don't seem to be aware of Phil Dawes' excellent Bicycle Repair Man.

I'd love to give Bicycle Repair Man a go; it looks fab when Phil demos it. but there's one hurdle to get over first - Emacs. And it's a big one.

I've given Emacs a go a couple of times (most recently Aquamacs), and it seems to make sense to me. It's not totally horrid like that nasty vi thing that just beeps at me all the bloody time. No, it's just that the learning curve is steep, and I have real work to do, work that I can accomplish far more easily at the moment using jEdit.

There are loads of tasks that I can achieve really easily using jEdit that I wouldn't even know where to start looking for in Emacs - line sorting, search and replace across a filtered set of files throughout a directory sub-tree, opening files in archives or FTP repositories, HTMlifying, XML re-indenting. I know Emacs can do all this stuff, but I really don't know where to look for it all, and I need to get stuff done.

There are a couple of other jEdit features that I really like and would miss, too. The File System Browser (which I keep docked and open at all times) is a fabulous tool. I like a mouse driven interface for navigating around the file system, and jEdit's is a very powerful one. Also, the combination of the search bar and the hypersearch panel (which I leave on by default and dock at the bottom respectively) is really powerful too. Are there Emacs analogs of these tools?

Oh yes, and I like buffer tabs too.

And before Andy comes in and starts accusing me of being a weak-minded GUI lover, I'm not. I'm getting on fine with bash on the Mac. I'm starting to use awk and sed to do stuff on the command line that are totally impossible via a GUI. (Oh, and thanks for the help on that, Andy.)

So, should I stick with what I know? After all, it's not like I'm using Notepad here - jEdit's very good. Or should I take the pain and try to switch to Emacs? I'd be able to use Bicycle Repair Man!

Posted by Simon Brunning at 12:34 PM | Permalink | Comments (15)
October 03, 2006
London Python Meetup tomorrow

Tap, tap. Is this thing on?

Now, blackmail is an ugly word, but I can't think of any other word for it - Simon Willison tells me that he'll come to tomorrow evening's London Python Meetup (at The Stage Door near Waterloo) if, and only if, I start blogging again. So, I don't really have a lot of choice, do I? Let's see if I can manage a post or two a day...

It would be beneath me to get my revenge by mentioning that at one point last night (at Sam Newman's London 2.0 meetup) Simon referred to Jack Davenport as "the hot one from Pirates of the Caribbean", don't you think? ;-)

Anyway, do try and get along tomorrow evening, all you London based Pythonistas. I think there will be a good crowd, including Steve Holden, Simon Willison, Tim Couper, Remi Delon and many other equally nice but not quite so famous chaps. (Yes, probably all chaps.) So, get practising.

Posted by Simon Brunning at 01:45 PM | Permalink | Comments (11)
March 07, 2006
What a load of CRUD

I'm taking the opportunity of all the waiting around time to write some great Python stuff. I'm away from the office for at least two weeks, which is far too great a strech of time to be away from our subversion repository for me to feel that I'll be able to merge stuff back into the trunk if I were to make any big changes, so I can't work on my main project - but I have roadkill with me, and a locker to leave it in while I'm in court, so I have a little side project on the go.

We are finding that we have to write huge swathes of Java code for each new business entity (policy, claim, broker, that kind of thing) that we want to make available for our users - domain objects implementing soft coded rules (in Jython!), data access objects, model view controller classes and the JSPs to go with them, web services and clients, plus interfaces and unit tests for them all, and a ton of config files - it just goes on and on. It's at least couple of days work just to get the basics in place, and it's the worst kind of work - repetitive and boring without being easy.

But it occured to be that 90% of this stuff could be automatically generated from the information in the Hibernate mapping document that we write for each of these entities - more given the fact that Hibernate helpfully allows you to add your own meta tags to your mappings, so I can add stuff to the mappings specifying which fields get shown in which places, for example.

I've not done any serious work in Python for a while - it's been all Java. So it comes as a surprise, once again, how powerful Python is. And how much fun! Nice to be reminded.

Aside from Python itself, there's a wierd kind of synergistic effect you get when you combine various well (Pythonically) designed modules. For example - I'm using classses inheriting from a new-style-class variation on Alex Martellini's Bunch class to store data about the entities in question, and their properties, and I'm using ElementTree to parse the mapping file. (I'm using ElementTree for its elegance here, not for its performance. The mapping files are tiny.) The fact that ElementTree spits out a node's attributes as a dictionary made the data just fall into my objects, so my parser has an obscenely small amount of code considering how much it does, it's still very readable.

Then I use Cheetah to generate the Java code, and again, the fact that Cheetah can be driven by my objects as they are means that the only code that I have to add to them is for derived values (which I'm implementing as properties) - no dross, only real domain logic.

I've pretty much finished the Python code now, I think. :-( Just the rest of the templates to build.

Posted by Simon Brunning at 08:02 PM | Permalink | Comments (3)
February 21, 2006
London 2.0rc3

Sam is organising London 2.0rc3, the latest of the combined Python/Django/TurboGears/CherryPy/Ruby/Rails/Java/Spring/Hibernate/the million other things you need to build a Java web app these days/Groovy meetup for Monday the 13th of March. He's not mentioned a venue, but the last few have been at The Old Bank of England, Fleet Street, so I shouldn't be too surprised if this one is there also. Keep an eye on his blog for confirmation.

I'll try to get along, but I can't guarantee anything this time. I'm on Jury Service at the time, and I have little idea what to expect.

Posted by Simon Brunning at 02:24 PM | Permalink | Comments (2)
January 10, 2006
London 2.0 rc2 tonight!

London 2.0 rc2 is on for tonight. I hope to see a bunch of you there.

We didn't get a room, I'm afraid. It's all my fault - Sam didn't book a room because he though I would have done so. I didn't book a room 'cos I had been thinking of another venue, so when Sam's post mentioned The Bank of England, I assumed that he'd booked the room. Sigh. Sorry about that. Piss up in a brewery, anyone?

Anyway, I'm hoping for a bunch of nerds of many colours - Python, Ruby, Java, Django, Turbogears, Rails, you know the kind of thing.

What I'm not expecting is many women. One or two - Katherine and perhaps Sarah - but London tech meetups suffer from the same malaise as the IT industry in general; a woeful gender imbalance. I'm not sure what, if anything, can be done about it, but Sarah is having a go by organising the Geek Girl Dinners. Do get along if the rules allow - and pass on the news to the nerdy women of your acqainance.

Posted by Simon Brunning at 01:26 PM | Permalink | Comments (1)
January 05, 2006
London 2.0rc2

This Month's London Python meetup on Tuesday will once again be just a part of a pan-nerd event, I'm glad to say - London 2.0rc2. And don't forget - the multi-talented Python celebrity Steve Holden is hoping to get along, as is Django co-author Simon Willison, and Python's answer to Max Clifford, Dr. Tim Couper, so don't miss it.

As last time, it's at The Old Bank of England, Fleet Street, any time after work. I'll see some of you there, I trust. I hope I get home a little earlier this time...

Posted by Simon Brunning at 06:58 PM | Permalink | Comments (7)
January 04, 2006
Busy busy busy

Back at work, and straight back into the thick of it. Meetings all day for the past two days.

Anyway, it'll be less frenetic tomorrow, I hope. Still got 2000 Bloglines entries and 500 email threads to get through. In the meantime, a Happy New Year to all of you, and yes, the Python meet is still on for the 10th. ;-)

Posted by Simon Brunning at 05:14 PM | Permalink | Comments (6)
December 14, 2005
London 2.0rc1

I was off yesterday. I was feeling a little under the weather. Can't think why. Perhaps I had a dirty glass on Monday night.

I met a lot of nice, interesting people, some for the first time, many not - more on that later.

The night ended with Chris, Edward and I at the Roadhouse. What a flea pit! I was home at four...

Posted by Simon Brunning at 10:32 AM | Permalink | Comments (1)
December 12, 2005
London 2.0rc1 Tonight

Right - I'm off to The Old Bank of England, Fleet Street, for London 2.0rc1. See you all there.

Posted by Simon Brunning at 04:35 PM | Permalink | Comments (2)
December 09, 2005
Don't forget London 2.0rc1!

Don't forget, London based nerds of whatever stripe, Monday night is London 2.0rc1. I hope to see a whole bunch of you there.

Posted by Simon Brunning at 07:58 PM | Permalink | Comments (1)
December 08, 2005
Brunning's 1st Law of System Hassle

All IT systems have roughly equal hassle rates. Should you improve the quality of your software (by means of thorough automated testing and so forth), other components of the system (such as the RDBMS, or the hardware) will take up the slack by failing more frequently.

Posted by Simon Brunning at 01:39 PM | Permalink | Comments (8)
December 05, 2005
London Python meetup, January 2006

We have a special guest for January's London Python Meetup; c.l.py regular Steve Holden, perhaps best known for the terribly good Python Web Programming.

The date will be Tuesday the 10th of January (see, a Tuesday - I do listen!), and the venue will be announced nearer the time, though it will certainly be somewhere in central London. It will depend in part upon whether we'll be teaming up with other groups à la London 2.0 or going it alone. I've not yet heard back from Sam and Jez on that. I'll update nearer the time.

In the meantime, make a note in your diaries. And as ever, please leave a comment if you plan on coming.

Posted by Simon Brunning at 04:54 PM | Permalink | Comments (6)
November 25, 2005

There goes our crowd for London 2.0.

Update: Just to be clear - London 2.0 isn't off by any means. It's just that I'm concerned that many of our potential attendees will go the the Backstage meetup.

Posted by Simon Brunning at 05:04 PM | Permalink | Comments (2)
November 23, 2005
London 2.0rc1

This is getting out of hand. December the 12th now appears to be a combined Python/Django/TurboGears/Ruby/Rails/Java/Spring/Hibernate/the million other things you need to build a Java web app these days/Perl/Catalyst/Maypole/Groovy/Grails Christmas party, and Jez is trying to get the Geek Girls on board too. Though that may be just wishful thinking on his part. ;-)

So, we really need another name. Jez suggested London 2.0, which is just so zeitgeist. Me, I'm more London 0.9, but I'll go with it...

Let's just hope the Perl guys don't have a punch up.

Posted by Simon Brunning at 01:14 PM | Permalink | Comments (10)
November 22, 2005
London Web Framework Night

Speaking of the London Web Framework Night - I never did write that up, did I?

OK, so, first up, Catalyst. What can I say? Catalyst may or may not be a great web framework, but since I didn't understand a word of the presentation, I'm not in any position to judge. It seemed mainly to consist of a list of CPAN modules that are either part of Catalyst, or can be plugged into it. No code, no working system, no screenshots, no inkling of what's in it for me. Nothing. Awkward, opaque, and unfriendly to all but insiders - much like I imagine Perl to be. (It must be said, the Perl mongers are aware of the problem - see this post, and this one. Message for Simon Wistow re your "Show Leon's Catalyst based web debugger. I'm willing to bet that it would be largely impossible in either of the other two" comment - I give you Ajaxy Exception Catching.)

Next up came Simon's Django presentation. I may have put The Fear into Simon about presenting to so many people, but perhaps I did him a favour - despite his admitted inexperience as a presenter, it was a cracking show. Compelling, funny, enthusiastic, and giving a very good idea as to what Django does, and how it does it. Using it will be pretty much a no-brainer when it comes to putting together a CMS style site. Whether it's the right platform for database driven sites like the kind of thing that I do for my day job is another matter. There's a clear front end/back end division with Django, with editors using its spectacular "magic" admin interface, and users mainly viewing content - though you do get community features like commenting pretty much for free. Perfect for a lot of sites, but would it suit enterprise database apps like banks and insurance houses need - and I write?

Simon demonstrated both the front and back ends of Django using lawrence.com - one of the sites for which Django was developed in the first place. Though the God of Demos made an apprearance at one point giving Simon an SQL exception, he also had a number of "oooh"s, and outright applause at least twice.

Last up was Matt Biddulph giving us a flavour of Rails. Struggling manfully through a stinking cold, Matt gave us the phiosophy of Rails in a very punchy manner. It looks very much a case of "do it our way", but that's often the right approach. Not enough code on show to tempt me away from a Python platform, though. ;-)

Without a doubt, the highlight here was Matt's demo of BBC Programme Catalogue. I have no words for how cool this project is. None.

I missed out on the booze up afterwards - I was feeling a bit fragile after several heavy sessions on the trot - so I'm sorry if I missed any of you. It was a good night nevertheless - a big thank you to Dean Wilson for organising it all.

Me? I'm looking at TurboGears. ;-) I like the concept of tying together best-of-breed components. Getting it running on my Mac was trivial, and the 20 minute Wiki is a superb demo. As soon as I locate some of that copious free time of mine, I'll try throwing together a simple site or two to see how it hangs together.

Posted by Simon Brunning at 06:46 PM | Permalink | Comments (8)
London Python/Django/Ruby/Rails/Java Christmas party

Not content with a Python/Django/Ruby/Rails meetup, Sam, Jez and I have teamed up to throw a Python/Django/Ruby/Rails/Java Christmas party this year. (For "party", read "bunch of nerdy blokes, many with beards, standing around drinking beer and chatting about computers".) It's at The Old Bank of England, Fleet Street on the evening of December the 12th.

Do leave a comment if you fancy coming - we have a room booked, and but we can change it to a bigger one if we need to. I anticipate a lot of interest, what with combining the Java crowd with the dynamic language people, and possible extra interest due to last week's London Web Frameworks Night.

Anyone want to demo TurboGears? ;-)

Update: Thanks to Dave and Dave, it's now a Python/Django/TurboGears/Ruby/Rails/Java/Perl/Catalyst/Maypole Christmas party. That has to be every web nerd in London, right?

Son of Update - This Time it's Personal: See London 2.0rc1.

Posted by Simon Brunning at 12:36 PM | Permalink | Comments (27)
November 07, 2005
London Python Meetup Tonight

Not that I'll be listening to Aerial much tonight - I'm off to the London Python/Django/Ruby/Rails meetup, with Alex, my Technical Director. I hope to see some of you there. No Sam, though; he's malingering. Or whatever.

Posted by Simon Brunning at 05:17 PM | Permalink | Comments (1)
November 01, 2005
Busy Month

It's going to be a busy month for nerdy stuff.

Firstly, there's Jez's London Java meetup on Thursday. Always a good night.

Then, next Monday, we have the London Python/Django/Ruby/Rails meetup. It's looking like we might get a good turnout for that - including my Technical Director! Gulp - I'd better be on my best behavior.

Then again, naaah.

On the 17th, there's the London Web Frameworks Night. Looks fascinating - demos of many of the happening web app frameworks back to back. Given the noise and drunkeness I don't tend to take much detail in during the Python/Django/Ruby/Rails meetups, so it'll be interesting to see more formal demos. Let's hope I'm quick enough to book a seat...

And lastly, there's the Einstein vs. Newton debate at the Royal Society on the 23rd. A different kind of nerdy, but nerdy nevertheless. Not to be missed.

Update: If you want to go to the London Web Frameworks Night, sign up now.

Posted by Simon Brunning at 10:28 AM | Permalink | Comments (2)
October 24, 2005
London Python Meetup

One for your diaries, London based nerds; The next London Python/Django/Ruby/Rails meetup will be on Monday 7th of November at The Old Bank of England, Fleet Street. Sam has booked us a back room, so there might be some chance of hearing any demos that might go on this time. Until I get pissed and start singing, that is.

If you fancy coming, do leave a comment. People like to be sure that they won't be the only ones there. ;-)

Posted by Simon Brunning at 05:10 PM | Permalink | Comments (13)
October 12, 2005

We've not automated our functional tests in the past - I know, I know - but we are really trying to pick up our game in our currenty project, so manual functional testing is another of our bad habits that we are consigning to the dustbin of history. With a bit of a steer from Sam, I looked at a number of functional test tools, but Selenium really stood out from the rest. It's just powerful enough, it's really simple, and it runs in your browser, so you can test browser compatability. Take a look at the demos to see how simple it all is.

In essence, your test script is just an HTML table, each line of which is either an action or an assertion. There's even a tool to record your actions to give you a hand building regression tests.

Now I just need to work out how to integrate it all with Cruise Control. Anyone done this?

Oh yes, and I need to find a way of testing our web services, too. Is there no end to the array of tools that you need to build a web application these days?

Posted by Simon Brunning at 04:59 PM | Permalink | Comments (4)
October 10, 2005
Python/Ruby Meetup tonight

Don't forget the London Python/Django/Ruby/Rails/Kamaelia meetup this evening...

Posted by Simon Brunning at 03:12 PM | Permalink | Comments (1)
September 29, 2005
Privacy and the Snake

There's rather an interesting thread going on over on c.l.py about private attributes and Python. It gave me the opportunity to post a link to one of my favourite c.l.py posts of all time, the Martellibot's wonderful essay decrying the "principle of least privilege". It should, as Steven D'Aprano says, be required reading for all developers, regardless of platform.

Also in the thread, the effbot comes to my defense on the subject of the rationale behind Python's name mangling feature, and links to a facinating thread from depths of Python's history in which the feature is originally discussed, and which contains this from Guido:"Python is an experiment in how much freedom programmers need. Too much freedom and nobody can read another's code; too little and expressiveness is endangered". Poetry.

BTW, do any Java-heads out there know whether or not cglib allows you to bypass private and protected?

Posted by Simon Brunning at 03:42 PM | Permalink | Comments (6)
September 06, 2005
London Python Meetup

I've not organised a London Python Meetup since April's, partly due to meetup.com's demise, partly due to my personal finances (I spent £100 last time!), but mostly due to pure sloth. Last night, though, at Sam's Django vs. Rails bash, considerable interest was shown in Python meetups.

So, Sam and I have decided to combine the two. On October the 10th, please come along to Smith's of Smithfield for nerdy chat about Python, Django, Rails, or anything at all really. Say, sixish 'till late.

Last night's Django vs. Rails thing was great fun. Funny thing - almost no one who came along had actually made use of either package. We were all there to hear from the experts, but there don't seem to be any of those just yet.

Well, except for Simon Willison, that is. Simon (1st page blogging for 'Simon', damn him!) is one of the three guys who built Django. Sadly, he hadn't brought a demo along either. :-( I did confirm that Django was named after the great Django Reinhart, though.

There were plenty of other interesting people around, some I knew already (Hi, Edward) and some I didn't (Hi, Torchbox people), and most of who's names I'd forgotten within seconds of having been being introduced. I'd blame the beer, but that would be lying, 'cos I'm always like that.

Tonight, to Jez's Java meetup with El Presidente and Tulna. Should be in interesting...

If you are coming along, do leave a comment...

Posted by Simon Brunning at 02:51 PM | Permalink | Comments (8)
September 01, 2005
Only on comp.lang.python

Only on comp.lang.python would this post have recieved helpful responses. ;-)

Posted by Simon Brunning at 01:35 PM | Permalink | Comments (4)
August 31, 2005

I've been getting on fairly well with Roadkill, my nice new Powerbook, but it's been a bit of a learning curve. The pretty Mac front end stuff is a piece of cake on the whole, with one major exception - undo, cut, copy and paste are Apple-z, x, c, and v respectivly, instead of Ctrl-z, x, c, and v as they are on Windows. I've been using those shortcuts for so long now that they are embedded in muscle memory. I've hit the wrong shortcut before my brain (such as it is) has had a chance to overrule them. Getting over that is going to take a while.

Getting some of the command line driven stuff - Ant, Subversion and Tomcat - working was a bit more of a challenge. Easy once you know how, but you keep being tripped up by things that I didn't know about.

I had installed Java 1.5, but the installer didn't tell me where it had been put, so I had to go and look for it. I found it in /System/Library/Frameworks/JavaVM.framework/Versions/1.5/ in the end.

There was already a version of Ant installed in /Developer/Java/Ant, probably as part of the XCode tools install, but it was the wrong version, and in any case I wasn't able to add 3rd party tasks to it, so I needed to use my own version.

Both of these problems involved setting environment variables, and I gather that it's recommended that you don't muck about with global environment variables, so I set up some shell scripts to start and stop tomcat and to run ant scripts with the environment variables set correctly. I was even smart enough to put the shebang line at the top (though finding the bloody '#' key took a while) and to mark them as executable wwith chmod. But I still couldn't run the bloody scripts. The shell was claiming that tey wen't there, though I could see them with ls.

It turns out that your current working directory isn't on your path by default. Arrrgh! That one took me hours, literally. Prefixing the script names with ./ does the trick there.

I still can't resolve any of the other boxes on my network by name, only by IP address. Irritating, but no show stopper. I can always add them to /etc/hosts, but for the moment I'm just using the IP addresses.

Still, I managed to get past all that, and my current web application is building and running on Roadkill happily enough now, after fixing a couple of minor Windows-isms in our build file. ;-)

Next on my list; installing PostgreSQL, and getting my app to work with it, and working out this whole multiple Python versions on one machine thing, and working out where the insert and delete keys are...

One other thing - what do you, uh, we Mac users use to read Usenet? Entourage seems to have trouble getting at Gmane - this fix, uh, doesn't.

Posted by Simon Brunning at 01:52 PM | Permalink | Comments (17)
Java Meetup next week

Pop along to next week's London Java Meetup on Tuesday the 6th. I'll be there - and I'm bringing Tulna and El Presidente with me this time. Perhaps Steve, too.

This month's topic is Spring, but as usual, off topic nerdyness of any kind seems to be welcome. For instance, I happen to know that Tulna (nerd in denial) will be interrogating Darren about shooting RAW, since she has a shiny new Nikon D70s.

I've dropped the ball a little recently with the Python meetups, but I'll probably organise one for October. I can't afford one this month - I spent over £100 last time!

First post from roadkill!

Posted by Simon Brunning at 01:05 PM | Permalink | Comments (4)
August 25, 2005
Freedom Languages

Kevin Barnes' Freedom languages (via Smalltalk Tidbits, Industry Rants) is very interesting. Read it. ;-)

Posted by Simon Brunning at 01:49 PM | Permalink | Comments (0)
August 17, 2005
All Quiet

I seem to have left my iPod playing when I got home last night, 'cos it was dead this morning. I hate commuting without music. (It's happy enough now though - it was just the battery.)

Besides which, being the nerd I am, I had to knock this up to make sure that my metadata is still correct:

import win32com.client
def main():
    iTunes = win32com.client.gencache.EnsureDispatch("iTunes.Application")
    quiet_tracks_playlist = iTunes.LibrarySource.Playlists.ItemByName('Reduce Played Count')
    for track in quiet_tracks_playlist.Tracks:
        print 'reducing played count for', track.Artist, '-', track.Album, '-', track.Name, 'from', track.PlayedCount,
        track.PlayedCount -= 1       
        print 'to', track.PlayedCount
if __name__ == '__main__':

How sad is that?

(I suppose that I'll be learning how to script iTunes all over again once I've got my new Mac.)

Why do I care about re-setting the played count? 'Cos I want this to be right:

import datetime
import time
import win32com.client
def main():
    iTunes = win32com.client.gencache.EnsureDispatch("iTunes.Application")
    total_time = datetime.timedelta(0)
    for track in iTunes.LibraryPlaylist.Tracks:
            track_time = time.strptime(track.Time, '%M:%S')
        except ValueError:
            track_time = time.strptime(track.Time, '%H:%M:%S')
        track_length = datetime.timedelta(hours=track_time.tm_hour,
        track_time = track_length * track.PlayedCount
        total_time += track_time
    print 'Total iPod time:', total_time
if __name__ == '__main__':
    raw_input('Hit enter to continue...')

And how sad is that?

Posted by Simon Brunning at 05:08 PM | Permalink | Comments (2)
August 12, 2005
Python 2.4, Windows and MSVC7

Ever since Python 2.4.0, the Python for Windows binaries have been build with MSVC7, as opposed to version 6. The main reason for this, IIRC, was that VC6 was no longer available to buy, and was increasingly difficult to get hold of. (See the bottom of the python-dev Summary for 2003-05-01 through 2003-05-15 for more.) Microsoft sweetened the deal by giving free copies of VC7 to several key Python developers, and pointing out that free (as in beer) versions of the compilers are available for download.

All C coded Python extensions distributed as Windows binaries need to be compiled by the same version of VC as core Python, so this required all extension builders to get VC7. But then, most probably already had it, and given that VC6 was no longer available at all, this probably made things better rather than worse on the whole. It was the right decision.

Update: Phillip J. Eby correctly points out that an extension builder doesn't need VC7 - only the core developers need that. An extension builder can use the free Microsoft compiler, GCC, or MinGW.

On the other hand, being Microsoft, there was bound to be a price to pay - and it turns out to be a big one. Software compiled with VC7 requires a dll, msvcr71.dll, at runtime. Owners of a full version of VC7 are free to distribute this, but no one else is.

This isn't a problem for the standard Python distribution, since the core Python developers have donated copies of VC7. It's not a problem for Python C extension builders and users, either, because the extensions can be compiled using the free compiler, and use the version of msvcr71.dll distributed with the standard Python distribution at runtime.

So, why is msvcr71.dll a problem? Py2exe, that's why. It's no longer possible to use py2exe to build a working stand-alone executable from a Python script and distribute it to people who don't have Python already installed. The exe built by py2exe needs msvcr71.dll to run, and you can't legally distribute that unless you own VC7.

Was this a deliberate trap? Probably not. I'm not that paranoid about The Great Satan, err, I mean Microsoft. I doubt anyone realised in advance that there'd be a problem. But it does underline the need to avoid proprietary software in general, and Microsoft software in particular, if any reminder were needed.

In fact, there's at least one other problem that I've come across caused by the move to VC7. There are Python bindings available for Subversion, (which rocks, by the way) and you need these to run Trac. But the Python Subversions bindings aren't available for Python version 2.4, and won't be in the foreseeable future; Apache is still compiled using VC6, so Subversion is built using it too.

I don't really have much in the way of a suggestion as to a solution to this, I'm afraid. It would, of course, be lovely if Python for Windows was built with a free compiler such as GCC or MinGW, but there would be a huge amount of effort involved in making the move, for which I'm in no position to volunteer.

Posted by Simon Brunning at 03:34 PM | Permalink | Comments (20)
July 05, 2005
Listing shell windows

Having read Raymond Chen's Using script to query information from Internet Explorer windows, well, how could I resist?

import win32com.client
shell = win32com.client.gencache.EnsureDispatch("Shell.Application")
windows = shell.Windows()
for window in (windows.Item(index) for index in range(1, windows.Count+1)):
    if window:
        print window.LocationName, '=', window.LocationURL

Quite pointless, but there you are.

There are other fun things you can do with the shell interfact, too, like opening exporer windows pointing to the directory of your choice - shell.Explore(r'C:\projects\morph') - or opening up control panel items - shell.ControlPanelItem('timedate.cpl') - but they are mostly pretty pointless too. I can think of uses for some things, I suppose - shell.IsServiceRunning('Tomcat5') might come in handy, along with ServiceStop and ServiceStart.

You can find some of this stuff documented in MSDN - Shell Object and IShellDispatch2 Object.

Posted by Simon Brunning at 04:03 PM | Permalink | Comments (6)
June 23, 2005
Instant Messaging

Mum is looking to do a spot of Instant Messaging with her Amida Buddhism chums. (My, look at all those blogs! All down to Mum's example.)

I've been looking at IRC recently, and it's really nice for techies. I've been using Bersirc as a client and Freenode as a server, and it's dead good. I've had some really useful help with Spring on #spring, and #python is cool too. (Say "Hi" if you are around there - I'm on as "small_values".)

But is it good for non-techies? If not, what should I recommend to her instead? Trillian? Miranda? Using what protocol? ICQ? (Anyone mentioning MSN can bugger off. These people are Buddhists, and need to keep their souls pure.)

Posted by Simon Brunning at 01:03 PM | Permalink | Comments (16)
June 09, 2005
Signing off

I'm off to CenterParcs with the kids, and my Mum, sister, brother in law and nieces next week, so Small Values will be even quieter than usual.

Blogging has been sporadic at best recently 'cos I've been so busy, mainly with a new Java web-app that we've been working on, using Spring and Hibernate running over a legacy database. It's been hard work, but I think we are over the hump now.

The other thing that's been keeping be busy is doing the Python URL. It's hard work - but it seems to be going down well. If there's one next week, though, it probably won't come from me...

Anyway, have a good week all. I might possibly post next week if there's a 'net café around, but don't count on it. I should have loads of photos by the 20th.

Posted by Simon Brunning at 01:24 PM | Permalink | Comments (5)
April 22, 2005
Windows system tray icons with Python

Two or three years ago, I put together a little Python app that provided shortcuts to useful places in our gruesome internal timesheet system. (The URLs aren't static, so I needed a script.) I used PyWin32 to enable you to launch these from the Windows systems tray, based on demo code by Mark Hammond. My script was a bit of a bodge, though; the UI code and the logic code were all mixed up. I always intended to go back and separate everything out, but I never got around to it...

Until now. I had a couple of changes that needed making, so I grasped the nettle and put together a general purpose module; SysTrayIcon.py. It still needs documentation, but you can see basically how to use it from the demo code at the bottom.

There is one problem with it, though - on XP, if you set up a menu item with an icon, the menu item text overlaps the icon image by a few pixels, and I can't work out how to fix it. Any pointers?

Oh, and yes, yes, I know it's not called the system tray really. But that's what everyone calls it anyway.

Posted by Simon Brunning at 01:16 PM | Permalink | Comments (13)
April 14, 2005
Last night's London Python meetup

Home at two this time. Too hungover to blog. Gallery here.

Update: More pictures, courtesy of Edward.

Posted by Simon Brunning at 03:13 PM | Permalink | Comments (12)
April 13, 2005
A rather unfortunate decision

Tonight's London Python Meetup at The Stage Door will be the last one organised via meetup.com, due to a rather unfortunate decision of theirs. If you want to be informed of future London Python meetings, you'll need to join the Python UK mailing list - or just subscribe to this blog.

It occurs to me that a moin page would do everything that we need - new events could be entered there, and people could subscribe to the page to be kept up to date. Perhaps I'll install a moin instance here on SVoC - or perhaps I could just add a page to the Python Wiki?

Oh, and don't forget the London Java meetup on April the 20th. I'll be there!

Posted by Simon Brunning at 11:02 AM | Permalink | Comments (4)
April 12, 2005
London Python meetup tomorrow

Don't forget the London Python meetup tomorrow night at The Stage Door near Waterloo. If it's anything like as much fun as the last one, it'll be great.

Tonight, Samba. Wish me luck.

Posted by Simon Brunning at 01:51 PM | Permalink | Comments (4)
April 05, 2005
Dr. Dobb's Python-URL!

My first stab at the Dr. Dobb's Python-URL! is out. What do you think? Did I miss anything?

Oh, and Freja is famous, too!

Posted by Simon Brunning at 11:40 AM | Permalink | Comments (5)
April 01, 2005
Freja coding

While Freja and I were playing with some Python last week, it occurred to me that the biggest problem that she (and presumably other kids) was having was how unforgiving computer languages are. For instance, after changing the name in the 'you_smell.py' script, she decided that she wanted to have it react to "daddy" or "ella" in certain ways. Without prompting, she tried:

if your_name.lower() == "daddy or ella":

Now, that doesn't actually work, but it's not a bad stab, I reckon. But you get no positive feedback for getting close - stuff just doesn't work. And many of the changes she made were plain syntax errors.

This wasn't a problem - I was with her, and I didn't allow her to become frustrated. But I doubt that you could leave a child of her age on her own to play with this stuff, really.

Posted by Simon Brunning at 04:27 PM | Permalink | Comments (3)
March 31, 2005
Python Cookbook

I recieved my copy of the 2nd edition of The Python Cookbook yesterday, too. Nice to see my name in print, however miniscule my contribution. Nice to get a free copy, too. ;-)

I've not had much chace to look through it yet, but it looks interesting. The new chapters on generators, descriptors and metaclasses look particularly useful. More later.

Posted by Simon Brunning at 05:02 PM | Permalink | Comments (2)
March 26, 2005

My post to the Python for Kids thread is something I've been meaning to get around to with Freja for a while. She's only eight, but the's confident with and facinated by computers, so I thought that giving her a go wouldn't do any harm if I didn't push her.

So far, she's having a blast. At first, she just drove the turtle around, changing its colour on the way. But towards the end, I suggested that she make a square, and she managed that easily enough. I'll have a bash at loops with her soon, but I really don't want to overload her.

There was another script that I knocked up for her that she had fun with, first just running it, then making simple modifications:

your_name = raw_input("What's your name? ")
if your_name.lower() == "freja":
    print "You're very stinky,", your_name
    print "You smell lovely, ", your_name

She worked out for herself how to replace 'freja' with 'daddy'. Ah, simple pleasures. ;-)

Note to self: Check out PyLogo.

Posted by Simon Brunning at 04:25 PM | Permalink | Comments (12)
March 24, 2005
Code limerick

Michael Spencer's code limerick is, well, I don't think that superb is too strong a word. It's not just that it's a limerick itself, it's what it outputs that makes it so cool.

Yes, I know; I really need to get out more.

Posted by Simon Brunning at 01:36 PM | Permalink | Comments (5)
March 22, 2005
The Power of Open Source

Four days the lists have been up, and already people are helping one another out on them. Nice.

Posted by Simon Brunning at 02:38 PM | Permalink | Comments (1)
Lambda revisited

There's me saying that I'd be happy to see the back of lambda, and the effbot goes and posts ElementPlist, a beautiful use for them. Nothing there you couldn't do without lambda, but not so elegantly.

He only does it to make me look stupid, you know. ;-)

Posted by Simon Brunning at 02:06 PM | Permalink | Comments (8)
March 18, 2005
Attention all WATSUP users

Tim and I are getting a steadily increasing number of emails regarding WATSUP and winGuiAuto.py, so we thought that now would be the time to set up a mailing list or two.

Now if someone can just help Tim to put the files up on Sourceforge, we'll be in motion. ;-)

Posted by Simon Brunning at 04:31 PM | Permalink | Comments (0)
Jolt 2005 awards

Congratulations to the Jolt 2005 award winners (PDF). I've read, used or will use a number of the winners:

But where's Spring?

Posted by Simon Brunning at 09:39 AM | Permalink | Comments (1)
Google Code

Check out Google Code. Google is open sourcing some cool stuff. First featured project: PyGoogle, a Python wrapper for the Google Web APIs. There are RSS feeds, too, so you can keep up to date with what they are up to.

As EP said over on c.l.py, this is great PR for Python.

Posted by Simon Brunning at 09:02 AM | Permalink | Comments (2)
March 17, 2005
Python meetup at The Stage Door, Waterloo on the 13th of April

The last meetup went very well, from what little I can remember. I'm organising another for April the 13th, again at The Stage Door. Pythonistas (or is that Pythoneers?) and the Python curious all welcome.

Posted by Simon Brunning at 04:21 PM | Permalink | Comments (6)
March 11, 2005
De-functionalising Python

Guido's thinking about ditching lambda, reduce(), filter() and map(). I don't use any of them, so I'd be quite happy to see them go, and the proposed product(), any() and all() functions look really good.

I'm with Peter, though - they shoudn't be builtins. We have enough of those already. I seem to remember the martellibot proposing a reductions module at some point. That would be a much better place for them - and for sum(), for that matter. Not only would that avoid bloating the builtins, it would also help to avoid the problem of people already having objects named 'any' or 'all'.

Posted by Simon Brunning at 01:36 PM | Permalink | Comments (8)
March 10, 2005
Life isn't fair

Bizarre. Wherever I go, I seem to develop the same undeserved reputation. This is a wholly unfair accusation; in many of the photos, I'm drinking a Mojito.

Posted by Simon Brunning at 02:17 PM | Permalink | Comments (4)
Latin Python

Last night's Python meetup was a blast. I still haven't sobered up. We had nine people at one point, which was pretty good. It ended up with Edward, Chris and I drinking Mojitos until stupid o'clock at Cubana, watching a couple of rather cute girls playing some rather good salsa.

Update: Thanks to Edward for this photo gallery.

I didn't get home until half past two. :-)

If you were there, please leave a comment so I know who you all were...

Posted by Simon Brunning at 10:08 AM | Permalink | Comments (7)
March 09, 2005
Wittgenstein was a beery swine

Right, I'm off for a slimming beer or two at The Stage Door with the London Pythonistas.

I might give the traditional kebab on the way home a miss, though...

Posted by Simon Brunning at 04:52 PM | Permalink | Comments (2)
Incrementing strings

While I'm posting silly little Python scripts, here's one I prepared earlier.

def inc_string(string, allowGrowth=True):
    '''Increment a string.'''
                   Bunch(from_char=48, to_char=57),  # digits
                   Bunch(from_char=65, to_char=90),  # upper case
                   Bunch(from_char=97, to_char=122), # lower case
    string_chars = list(string)
    string_chars[-1] = chr(ord(string_chars[-1]) + 1)
    for index in range(-1, -len(string_chars), -1):
        for char_range in CHAR_RANGES:
            if ord(string_chars[index]) == char_range.to_char + 1:
                string_chars[index] = chr(char_range.from_char)
                string_chars[index-1] = chr(ord(string_chars[index-1]) + 1)
    for char_range in CHAR_RANGES:
        if ord(string_chars[0]) == char_range.to_char + 1:
            if allowGrowth:
                string_chars[0] = chr(char_range.from_char)
                string_chars.insert(0, chr(char_range.from_char))
                raise ValueError, string + " cannot be incremented."
    return ''.join(string_chars)

Requires the martellibot's Bunch class.

The story behind this one is that I was building a database conversion utility, converting both schema and data from one database engine to another. Thing was, the target database only allows 10 characters in its table and column names. (OK, actually, it doesn't - but it's a whole lot easier to access if you stick to 10 characters.) I stripped down the longer entity names by removing whitespace and spacing characters, then non-leading vowels, and at the last resort, I truncated.

This worked on the whole, and the column and table names were not a great deal less readable than an RPG programmer is used to anyway. ;-) But I was getting the occasional duplicate, so I came up with this.

(inc_string.py formatted, with unit tests)

Posted by Simon Brunning at 02:59 PM | Permalink | Comments (4)
Picking random items from an iterator

The shuffle the lines of a large file thread on c.l.py reminded me of Richard Papworth's superb Cookbook recipe, Retrieving a line at random from a file of unknown size. The wonderful thing about this recipe is that the file only needs to be read once, and it doesn't need to be kept in memory, but every line in the file has an equal chance of being selected.

I came up with a quick hack that allows the selection of multiple lines, but it soon occurred to me that this approach is far too pretty to be restricted to files - you can do the same with any iterator:

def random_items(iterator, items_wanted=1):
    selected_items = [None] * items_wanted

    for item_index, item in enumerate(iterator):
        for selected_item_index in xrange(items_wanted):
            if not random.randint(0, item_index):
                selected_items[selected_item_index] = item

    return selected_items

You can run this over a file; random_items(open(file_name)), but you can also run it over any other kind of iterator.

This is in Python of course, but I don't see any reason why you couldn't implement this in any language that has iterators.

Fuller version with kind-of-unit-tests: random_items.py

BTW, how do you unit test something that gives random results properly?

Update 10th March: Faster initial allocation of selected_items

Posted by Simon Brunning at 01:00 PM | Permalink | Comments (7)
March 08, 2005
London Python meetup tomorrow

The London Python Meetup is tomorrow evening at The Stage Door, near Waterloo, 6:30 'till late. Ish.

I'll be the one with the tin of Spam. See you there...

Posted by Simon Brunning at 12:15 PM | Permalink | Comments (0)
February 23, 2005
Online lyric database

Anyone know of an online lyric database that I can get to pragmatically? I'm not above a bit of scraping if need be, but I'd prefer something cleaner - and I want somewhere that explicitly states that programmatic access is OK. I don't want to rub anybody up the wrong way.

I'm thinking of putting together something to display the lyrics of whatever I'm listening to in iTunes. Catching the events that tells me what's playing seems to work OK. Here's my proof of concept - show_playing_track.py. The next stage will be to actually retrieve the lyrics from somewhere.

I did look at EvilLyrics, but that seems to bugger iTunes up on my PC. Besides, it's more fun to write my own. ;-)

BTW, I've cleaned up convert_tracks.py a little, and made it a little more robust. It doesn't choke on read-only files now. Is there a cleaner way to write enable files in Windows than os.chmod(filepath, 0777)? That 0777 is nasty.

(See Batch iTunes track conversion with Python and COM for more about convert_tracks.py.)

Posted by Simon Brunning at 01:17 PM | Permalink | Comments (15)
The real problem with Java

I've realised what the real problem with Java is, for me. It's not the fact that my productivity is much lower with Java than it is with Python. After all, it's my management that decide that I should be using Java, and if they want to make me less productive than I could be, it's their prerogative.

And it's not the vast raft of tools, libraries and frameworks that a modern Java application uses that bothers me. It's a problem for a lot of people - c.f. Bruce Tate's superb Better, Faster, Lighter Java (on which more later), but I like learning new stuff, so I'm happy.

No, the problem is that Java coding is just no fun...

Posted by Simon Brunning at 12:54 PM | Permalink | Comments (33)
February 10, 2005
Python meetup at The Stage Door, Waterloo on the 9th

I've had a promising response to my suggested London Python meetup. If even half of them turn up, I'll call it a success.

BTW, the London Java meetup is on the 28th. I probably can't make it, :-(, but don't let that stop you.

Posted by Simon Brunning at 01:24 PM | Permalink | Comments (3)
February 08, 2005
The London Python Meetup Group

I'm having a bash at breathing some life into the London Python Meetup Group. If you are London based and fancy meeting up with some fellow Pythoneers for a beer and a war-story or two, please sign up.

If there's a reasonable amount of interest, I'll get something organised.

I've not had much luck keeping these going in the past, but Jez's huge sucess with the London Java Meetups has inspired me.

Posted by Simon Brunning at 11:55 AM | Permalink | Comments (5)
February 04, 2005
Batch iTunes track conversion with Python and COM

I think that I see now why Apple has kept the iTunes interface simple. It's a simple app that does simple stuff, and it just works. Once you get it into your head that you can do whatever you like, where do you stop? I see that I'm not alone in getting a bit carried away - Garth and Chris have also been having a play with driving iTunes with Python and COM, too.

Anyway, on to my latest folly, batch conversion. I initially ripped all my CDs to MP3 at 192 kbps. I've since discovered that I'm quite happy with plain old 128 kbps, especially for the more raucous stuff in my collection. And I'm running out of room. So I want to convert a bunch of track to a lower bitrate. (And before you tell me, yes, I know that converting from 192 kbps to 128 kbps will give me a somewhat lower quality that I'd have had I ripped to 128 in the first place. I'll probably re-rip at my leisure.)

Now, you can convert from one format and bit rate to another in iTunes, but the process leaves a lot to be desired. For a start off, you end up with both the original and the new track, and you have to remove the original track yourself, which is fiddly - you have to make sure that you get the right one for a start. Also, there's a lot if metadata that doesn't get copied across to the converted track - the rating that you've given the track, the last-played date, that kind of thing. Lastly, if you've put the track into any manual playlists, the newly converted track won't be in them.

So, I came up with a script to do the conversion for me - convert_tracks.py. You just bung the tracks that you want converted into a playlist (called "To Convert" by default), set the conversion rate that you want to use in your iTunes' preferences, and away you go.

This script works OK, but there are a couple of problems with it. Firstly, though you can set the encoder to be used, I can't find any way of programatically setting the bitrate. You have to do it manually via the iTunes preferences dialog. A bit of a shame, but no biggie.

More seriously, you have to be very careful to leave iTunes alone to its thing. If iTunes shows any dialog box, your iTunes COM connection will fail if you make any calls to it. I could just trap the exceptions, but that would be The Wrong Thing. Instead, I think that I need to register for OnCOMCallsDisabledEvent()s. When I get one of these events, I should hold fire on COM calls until I get a OnCOMCallsEnabledEvent(). I've had a bit of a play with registering for iTunes events - see show_playing_track.py - but it's early days, and I've been too busy this week to look at it.

(Also, it would be nice if it were to be driven by command line arguments, a cinfuguration file or even a GUI rather than by hard-coded constants - but since it's pretty much a one-off script, I really can't be bothered.)

Anyway, I hope this is of some use to somebody. (All code runs with iTunes 4.7.1 Python 2.4 and Python for Windows build 202, and may work with earlier versions.)

Posted by Simon Brunning at 05:05 PM | Permalink | Comments (4)
A quick look at ElementTree

Lumigent Log Explorer is a potential life saver, as I've said before, but there are some oddities with it. All the data is there, but we've had trouble getting exactly what we want from it in exactly the way that we want it.

No matter - it has a facility to export all your raw transactions to XML. Sorted! (Well, we had to fix a couple of very minor issues before the XML was well formed - & characters were not escaped to &, and we needed to add add encoding declaration. Still, not far off.)

I've not processed much XML, and not done any at all for a while. I was never really comfortable with the Python XML libraries that I'd played with, so I thought I'd give the effbot's ElementTree module a try.

The API is lovely. After no more than five or ten minutes, I felt like I knew what I was doing.

An example. A radically truncated version of the XML output from Log Explorer might look like this - oh-bugger-its-all-gone-a-bit-pete-tong-lets-hope-i-can-recover-the-data-from-this.xml. (The real thing was over seventy MB in size.) Code to loop through all the records, pull out the relevant details (including all the row's data from a sub-element) is as simple as this:

import cElementTree as ElementTree

# Parse XML...
tree = ElementTree.parse("oh-bugger-its-all-gone-a-bit-pete-tong-lets-hope-i-can-recover-the-data-from-this.xml")
root = tree.getroot()

for record in root:
    # Pull out tags
    timestamp = record.findtext('DATETIME')
    opcode = record.findtext('OPCODETXT')
    table = record.findtext('TABLENAME')
    rowdata = dict((column.tag, column.text or '') for column in (record.find('ROWDATA') or []))

    # Complex stuff here...
    print timestamp, opcode, table, rowdata

Nice, eh?

Clearly my code did something a bit more complex that just printing out the data, but you get the idea. In fact, I'm rather pleased with the script on the whole. It does an awful lot with not much code - Python's dictionaries, lists and string interpolation do most of the work.

Performance? Now, I'm rather wary of venturing into benchmarking territory, so I'll just say that cElementTree goes like stink, and leave it at that.

Frankly, I'm almost always totally uninterested by benchmarks in any case. Software only has two speeds - fast enough, and not fast enough. cElementTree is comfortably in the fast enough range. Beyond that, I honestly couldn't care less.

Posted by Simon Brunning at 12:14 PM | Permalink | Comments (11)
January 28, 2005
Putting it all together

Tell me what to do, please.

I've most often come across this issue building Java web applications. There are just so many pieces to stitch together, and to find places to put; your your build script, your business objects, your tests, your JSPs (or whatever), all your 3rd party JARs, your persistence stuff, your MVC stuff, your IoC stuff, about a gazillion configuration files to make all this lot work together, it just goes on and on. It takes a while, and if you get it wrong, well, everything still works, mostly, but you'll have maintenance nightmares for life.

In fact, it got so out of control that Matt Raible came up with the wonderful AppFuse. Appfuse is great - it builds a project structure for you, using your choice of frameworks, so you can hit the ground running. I only hope that Matt learns to slow down a little!

Perhaps that's what Python needs - not Rails, but AppFuse.

Update: Matt's site seems to be down at the moment. But do try later - AppFuse really is worth a look

Posted by Simon Brunning at 02:24 PM | Permalink | Comments (9)
We only let you drink it when it's ready

Last night's Einstein Legacy lecture was good. It was a helter-skelter overview of cosmology, and I didn't actually learn anything - but it was a privilege to hear Sir Martin Rees speak, and there were plenty of pretty pictures.

It was also nice to see Jez. The Java Meetups are great, but you don't usually get to have an extended chat with one person.

We chatted about Groovy mostly. There's been a Groovy is dead or dying meme sweeping the blogsphere recently, so it was interesting to speak to someone on the inside.

According to Jez, work is continuing on Groovy and progress is being made, but it's slow. Groovy is in its early days, and it's taking a while to mature.

I think that that might be a major part of the Groovy's problem - it got big quickly, and it's not had time to mature. It's really still at the stage where it ought to be developed (and used) by a few dozen people. Instead, it's all over the blogsphere, it's got a JSR, and everyone is clamouring "where is it?" Well, it's just not ready yet.

For me, the major problem that I have with Groovy is that I really still don't see the point in it in the first place. James was looking for something better than Java, but he dismissed Python without looking at it very deeply. There were a couple of fairly trivial syntax issues that he didn't like, so bang, off he goes and writes his own. Wheel-reinvention is all to common, and this looks to me to be a prime case of it.

What does Groovy deliver that Jython doesn't? Little or nothing, so far as I can see. Groovy's syntax is a bit more Java-like, but that's about it.

Also, Groovy is heading in a Perl-like include everything direction, rather than in a keep it spare and simple Python-like direction, so I'm really not too tempted by it.

Ironically, James has given Python a much more thorough going over since the Sun summit, and he likes it now! He still likes Groovy better, of course, but got can't get in the way of cognitive dissonance!

The real tragedy is that Jython could really use some help. It's progressing now, but getting over the 2.1 to 2.2 hump has proved a real stalling point, and had James and the Groovy team put as much effort into Jython as they have into Groovy, I think real progress could have been made.

Posted by Simon Brunning at 12:32 PM | Permalink | Comments (1)
January 21, 2005
"Mostly Python. with ample helpings of C++"

If it's good enough for Google...

Posted by Simon Brunning at 04:48 PM | Permalink | Comments (2)
January 20, 2005
Zope at Lastminute.com

Another interesting snippet from last night - Lastminute.com are running their system on Zope! Well done to Seb at Jamkit for getting this gig!

Posted by Simon Brunning at 02:43 PM | Permalink | Comments (1)
Special Cases

Very interesting London Java Meetup last night. It was nice to see Darren and Steve along for the first time, and I had a very interesting chat with James about Sun's new interest in dynamic languages, and Groovy, his baby. (Jez is also working hard on Groovy at the moment.)

It's interesting to see the differences and similarities between the philosophies of Groovy and Python. One thing that James and (channelling) Guido agree on is that simplicity is good. They disagree on what constitutes simplicity, though.

Take functions for a moment. In both Python and Groovy, functions and methods are 'first class', which means that they are objects in their own right, and can be passed around like any other object. They differ in how that's done, though.

In Python, a function is called by putting parenthesises after its name:

>>> def spam():
...  print "spam's been called!"
>>> spam()
spam's been called!

If you want to refer the function object, you just leave the parenthesises off:

>>> spam
<function spam at 0x0117CDB0>

This makes it easy to pass the function around:

>>> eggs = spam
>>> eggs()
spam's been called!
>>> def chips(a_function):
...  a_function()
>>> chips(spam)
spam's been called!

To me, that's nice and simple. No special cases. As Tim put it, "special cases aren't special enough to break the rules". A function is an object, names are bound to objects, using the base name refers to the bound object.

"Ah!", says James, "but 99% of the time when a newbie leaves the parenthesises off, it's a mistake. That want to call the function." This is probably true. So in Groovy, if the function takes no arguments, you can call it without parenthesises. If you want to refer to the function object, there's a special syntax for that. (Perhaps James or Jez would care to give an example here?) The 'normal' case gets the normal syntax, and the unusual case gets the special syntax. So, is this simpler?

Another example - self. Python requires all methods to take an explicit self argument. After all, a method is just a function belonging to an instance really, and it's simpler to pass that instance explicitly. No black magic, and it makes injecting new methods into classes and instances at runtime simpler. But you always need a reference to the instance, though, so in Groovy it's is available implicitly. It's not like you need to dynamically add methods that often, is it?

To me, having all this implicit stuff is more complex than doing everything explicitly. But to James, keeping the common case simple to write is simpler. Who's right? Who knows. I like Python's approach myself, but it's not obvious to me that James is wrong.

I'm also sad to say that James is starting to understand what it must be like to be Guido, attacked every time you propose a change. Bloody nice chaps, both of them, so this is a real shame.

Oh and where were you, Sam?

Posted by Simon Brunning at 01:52 PM | Permalink | Comments (13)
January 11, 2005
Python in Computer Weekly

Clarity, not speed, makes Python an ideal language for beginners, according to Computer Weekly.

This is far from the worst Python-for-pointy-haireds that I've seen, and it's far better than nothing. Computer Weekly is very well read in the UK - I'd say that more IT pros read it than not.

It's not the first article I've seen that implies that Python is slow to run, though. In practise, everything that I write is I/O-bound (either network or disk), and Python is at least as fast as any other language in this case. It can be a bit slower than compiled languages when it comes to number-crunching and tight loops, it's true, but that doesn't bother me at all.

Also, they do bang on about Python being a good language for beginners, which it is, but they mention only in passing that it's just as good for advanced programmers.

Posted by Simon Brunning at 01:46 PM | Permalink | Comments (4)
January 05, 2005
Outputting dates in RFC822 and ISO8601 formats in Python

I'm not feeing terribly inspired at the moment, so it's time for a spot of meme-jumping. You've seen it in Java, you've seen it in Perl; now here it is in Python - Outputting dates in RFC822 and ISO8601 formats in Python.

Odd thing there - when you ask Python for the current (or default) locale, it gives it to you with an underscore, like so: 'en_GB'. But when you set the locale, you need to provide it with a dash - 'en-GB'. I'm sure that there's a good reson for this, even if I'm too stupid to work out what it is.

Posted by Simon Brunning at 12:29 PM | Permalink | Comments (7)
December 23, 2004
Time for a new phone...

Python for Series 60.

Posted by Simon Brunning at 01:11 PM | Permalink | Comments (3)
Static Typing in Python

Guido's mulling static typing in Python, and Andy isn't impressed.

It's optional type checking that's being considered, Andy, so this really isn't that bad. I can see using it for two reasons:

Firstly, on those rare occasions when you do want to insist that an argument has a certain type, you might get a better message this way. (It won't actually pick up more errors - if the type does matter, my unit tests will pick up the problem PDQ. And if they don't, well, clearly the type doesn't matter after all, does it? ;-) It's only the error message which might be improved. Is this worth it? Debatable. I probably won't use type checking for this, even if it is introduced.)

Secondly, I can see that it might help with optimisation - cf Psyco. If this were the case, I might use static typing from time to time, but only where I was actually having a problem with performance, and only after profiling to see which functions were candidates for optimisation.

For me, the big problem with this is that the whole concept of a type in Python is a bit nebulous. Usually, so long as the object you have implements the correct protocol, you don't care that its actual type is, and I'd be loath to lose that. Perhaps progress needs to be made with PEP 245, Python Interface Syntax, and PEP 246, Object Adaptation, before static typing makes sense in Python. Or would this interfere with the optimisation benefit?

Posted by Simon Brunning at 12:48 PM | Permalink | Comments (5)
December 17, 2004
A Python Meetup at last!

And I'm invited.

Unfortunately, it's in Sydney. :-(

Ah well, never mind. Have fun, guys, and have a pint for me. Or a schooner, or whatever it is that you antipodean chaps drink.

I wouldn't have been able to go even if I were in Sydney - I'm never drinking again.

Posted by Simon Brunning at 02:11 PM | Permalink | Comments (5)
December 16, 2004
Ugly Python

Python encourages readable code, but clearly it can't mandate it. First we had WyPy, now down to 11 lines, and now (via Slashdot) we have TinyP2P. Don't try this at home, kids.

Posted by Simon Brunning at 10:43 AM | Permalink | Comments (2)
December 15, 2004
Static vs. Dynamic

Ian Bicking: Because Unanswered Problems Are Always Hard. This really is the single best article pointing out the advantages of dynamic typing that I've ever seen. Quotations:

"Back to reliability: one way to decrease bugs is testing, but another way is to decrease the amount of code. Code deleted is code debugged. Static typing can decrease the number of bugs, but decreasing the amount of code is a much, much more effective way to decrease bugs. If you can have both -- short code and static typing -- then more power to you. I just haven't seen it myself."

"Now forgotten, at one time there were languages that were both weakly typed and dynamically typed; things like assembly and Forth. Ouch. There were two paths from there: one to make runtime values intrinsically typed (Lisp), and one to make the source code intrinsically typed (C). But just because assembly sucked a lot doesn't mean all languages afterward must approach the problem in terms of its suckage. And just because there was that split, doesn't mean joining both worlds (a language with both intrinsically typed values and source, i.e. Java) is better."

"Static type defenders complain about the combinatorial type interactions in dynamically typed languages -- how can you test all the code paths, given all the possible types? But their languages lead to combinatorial code, which is far worse: for many classes of hard problems, they can't solve them once, they have to solve them everytime they are encountered. Ouch."

This has gone around the Python blogsphere like wildfire, naturally. I'm posting here for the Java types who visit from time to time.

Of course, words are cheap, even words as eloquent as Ian's. I know that dynamic languages are just as reliable and much more productive that statically typed languages are through real experience. If you've only tried one approach, give the other a go. You'll learn.

If you don't know what Ian's banging on about, read How Python's Datatypes Compare to Other Programming Languages. If that doesn't make sense, you're either not a programmer, or shouldn't be. ;-)

Posted by Simon Brunning at 02:22 PM | Permalink | Comments (5)
December 09, 2004
Dynamic Languages Summit at Sun

Dynamic Languages Summit at Sun, involving Guido, Samuele Pedroni, Larry Wall and James Strachan, to name but a few. Cool!

Jez was telling me about this at last night's Java Meet, but he asked me to keep it under my hat. But I suppose that if Tim Bray is blogging it, it's pretty squarely in the public domain!

Update: Ted Leung - Dynamic language support on the JVM - cross your fingers!

Posted by Simon Brunning at 12:05 PM | Permalink | Comments (2)
November 30, 2004
Python 2.4 final

Python 2.4 final is out. A big thank you to Guido and the Python-dev team.

(See also my comments on Python 2.4 release candidate 1).

One with Python 2.4 is one I only discovered after having a go with release candidate 1 - extensions.

Python is build using Visual Studio on Windows. Python 2.3 and prior versions (at least as far back as Python 1.5.2) were build using Visual C++ version 6, so I was able to use distutils to build all my extensions. Python 2.4 is build with Visual C++ version 7.1, which I don't have, so it's not quite so easy. (Since I'm the one telling everyone around the office that we shouldn't go near .NET, I'm hardly in a position to ask for a copy!)

It is possible to build Python 2.4 extension using free (as in beer) tools from Microsoft - see Python 2.4 Extensions w/ the MS Toolkit Compiler - but I've not had the time to download (at least 380 MB!) and install everything that's required as yet. In particular, I can't find anywhere to download the .NET Runtime.

Still, I'm sure pre-built binaries will be available soon enough.

Posted by Simon Brunning at 12:52 PM | Permalink | Comments (8)
November 23, 2004
More Pointless iTunes fun with Python

iTunes isn't too great at working with selected and de-selected tracks. You can't sort by selection, for instance - you can't sort your library so as to show all de-selected tracks then all selected tracks. Nor can you build smart playlists based on whether a tune is selected or not.

Well, not without getting your hands dirty, that is. ;-)

Since my iPod is now rather full, I've de-selected some albums, and some individual tracks. Now, I'd like to burn the albums that I've de-selected onto CD, and remove them from iTunes altogether. My hard disk is getting a bit full, too. ;-) But, I only want to do this with whole albums - individual de-selected tracks should be left alone.

My library isn't that big. Any normal person would just scroll down through the library, and manually set up a playlist of stuff to remove. Not me, oh no, I'd much rather spend several times the time writing a script to do it all for me. Plonker. Anyway, here it is - create_deselected_albums_playlist.py. I hope someone finds it handy - it would be nice if I hadn't wasted my time entirely.

See also Driving iTunes from Python on Windows.

Posted by Simon Brunning at 04:55 PM | Permalink | Comments (4)
November 19, 2004
Python 2.4

Python 2.4 release candidate 1 is out.

As usual, Andy Kuchling's What's New in Python document is the best place to start. Highlights for me are Generator Expressions and the Decimal Data Type. I've blogged about the first of these before - see my Generator Expressions post. And I've mentioned the need for a decimal type before, too. Great stuff.

Congratulations and thanks to Guido and the Python-dev team.

As to the controversial Decorators for Functions and Methods, the jury's still out. The syntax still looks a little odd to me, but the same could have been said of the syntax for Slicing and List Comprehensions at first, to name but two things. Time has taught me that these syntaxes are actually really good. Guido knows what he's doing. And there's no doubt that decorators can be useful - see Decorator for BindingConstants at compile time and Memoize Decorator with Timeout for examples.

Update November 30th: Python 2.4 final is out.

Posted by Simon Brunning at 10:19 AM | Permalink | Comments (8)
November 05, 2004
Driving iTunes from Python on Windows

Inspired by David Janes' pytunes, I've been having a play with driving iTunes with Python.

The first thing that I've discovered is that running EnsureDispatch over iTunes utterly screws up pytunes. The lesson here is to always use EnsureDispatch. If you don't, your code might break as soon as somebody else's code does. This applies to COM scripting with Python in general, I think.

It's all pretty easy. If you're familiar with COM scripting with Python, then you already know almost everything you'll need to know. Grab the iTunes COM for Windows SDK, and off you go! Fun, if utterly useless, is driving iTunes from a Python interpreter:

>>> import win32com.client
>>> iTunes = win32com.client.gencache.EnsureDispatch("iTunes.Application")
>>> iTunes.LibrarySource.Playlists.ItemByName('Party Shuffle').PlayFirstTrack()
>>> iTunes.Pause()
>>> iTunes.Play()
>>> iTunes.PreviousTrack()
>>> iTunes.NextTrack()
>>> iTunes.CurrentTrack.Name
u'Would Not Come'
>>> iTunes.SoundVolume
>>> iTunes.SoundVolume = 25
>>> iTunes.SoundVolume
>>> iTunes.SoundVolume = 50
>>> iTunes.Windows.Item(1).Minimized = True

Perhaps slightly more usefully, you can also edit your tracks' metadata. For example, here's a mickey-mouse script that I used to clean up some dodgy quote marks in my library - quote_clean.py.

Update: This one is actually marginally useful - find tracks that have no images, or more than one, with wrong_image_count.py. Anyone know where I can find cover art for "River Station" by Jimmy Giuffre & André Jaume? Google doesn't know it exists. Perhaps it doesn't...

Update: See also See also More Pointless iTunes fun with Python.

Posted by Simon Brunning at 02:05 PM | Permalink | Comments (9)
October 14, 2004
Scripting Civ IV

Amazing news from the forty-second parallel - Civilization IV will use Python as its scripting language!

My favourite game and my favourite language, together at last. This is just so cool...

Posted by Simon Brunning at 04:39 PM | Permalink | Comments (6)
October 12, 2004

Check out pytunes - a Python interface to iTunes.

Apparently, Apple have exposed a COM interface to iTunes. If I'd known that, I might have written this myself. Unfortunately, the exposed interface is incomplete. You can't read all of the track meta data - 'My Rating', 'Play Count' and 'Last Played' are missing, for example. And you can't set anything - all the attributes are read only. This is a real shame, 'cos it means that I can't use the COM interface to do what I really want to do - transferring my iTunes library's meta data from one PC to another.

There are a number of ways of transferring the tracks themselves. I use iPod Agent. But this doesn't set all the meta data. 'My Rating', 'Play Count' and 'Last Played' don't get set, for example, and since some of my smart playlists are driven by these values, I really want this all transferred too.

Time to dust off winGuiAuto, perhaps, and its new big brother WATSUP?

Update: David has pointed out the iTunes COM for Windows SDK. The C header files in there seem to refer to the ability to read and set all the meta data that I need, so perhaps I can read and set everything I need to. I'll keep looking...

Posted by Simon Brunning at 01:53 PM | Permalink | Comments (10)
October 05, 2004

Dr. Tim Couper has built a very slick looking unit test framework for Windows GUI sytems - WATSUP - Windows Application Test System Using Python.

It makes use of winGuiAuto, my rather rough and ready Windows GUI automation utility. Nice to see that I've contributed to something useful to someone other than me! winGuiAuto is just a small corner of WATSUP, though...

Tim will be putting this up as a Sourceforge soon, I gather.

Update October the 8th: WATSUP is on Sourceforge now.

Posted by Simon Brunning at 04:24 PM | Permalink | Comments (4)
September 03, 2004
Mad Hungarian

One for Mark: Hungarian notation: an outdated concept. See, Mark, there's almost nobody left who still thinks that Hungarian doesn't suck.

Posted by Simon Brunning at 01:48 PM | Permalink | Comments (5)
August 16, 2004
The Python Paradox

The Python Paradox: "I didn't mean by this that Java programmers are dumb. I meant that Python programmers are smart. It's a lot of work to learn a new programming language. And people don't learn Python because it will get them a job; they learn it because they genuinely like to program and aren't satisfied with the languages they already know. Which makes them exactly the kind of programmers companies should want to hire."

There are, of course, many very very bright Java programmers out there. But there are also a huge number of "I learnt it 'cos my company made me, only in it for the money" types using Java. Burger flippers don't only use VB! Whereas Python programmers are on average of an enormously high standard indeed. (After all, even I can't drag the average down that far; I'm only one man.)

Posted by Simon Brunning at 01:03 PM | Permalink | Comments (5)
August 09, 2004
Python Decorators

Python-land seems to have descended into chaos while I've been away. I suppose I'd better leave someone in charge next time I go on holiday. ;-)

The source of the problem is function decoration, which offers a way to mutate a function or method. The cardinal example of a function decorator might be staticmethod(), Python's way of building static methods. Currently, you have to declare and code the function, then call staticmethod() passing your function as an argument:

class MyClass:
    def my_method(arg1, arg2, ...):
    my_method = staticmethod(my_method)

This is bad for two reasons; firstly, the code which defines my_method as static is not in the same place as the definition of the function itself - it may be a long way away in the case of long methods, and secondly there's the non-critical but irritating fact that you need to enter the method's name three times, violating the DRY principal.

Enter function decorators. The current implementation spells decoration like this:

class MyClass:
    def my_method(arg1, arg2, ...):

Now, I dislike this for two reasons. Firstly, it's ugly. This matters. Secondly, it's not in the function - it doesn't really look like part of it. I'm not alone in disliking this syntax.

I prefer Phillip J. Eby's list-after-def proposal:

class MyClass:
    def my_method(arg1, arg2, ...) [staticmethod]:

Much nicer, at least in simple cases. Things get more complicated where you have multiple decorators, and/or the decorators take arguments themselves, but I don't believe that these will come up too often - especially not the second.

Anyway, that's enough from me; this discussion has generated over six hundred emails to python-dev over the last week, and I don't have anything new to add. I'm sure that whatever Guido ends up deciding on, it'll be OK in the end. He knows what he's doing.

I've not even started reading last week's c.l.py. ;-)

Posted by Simon Brunning at 01:43 PM | Permalink | Comments (19)
July 08, 2004
Jython and Groovy

Groovy is still getting all the hype at the moment, but Jython is still very much in the picture. In fact, I hope and expect that they'll both succeed. Both get a flattering mention in Extend your Java Application with Embedded Languages.

On the Jython side, the Jython site is now indicating a major Summer release, just as Samuele said in April. Also, I hear from Jez that the Sun boys are planning to make some changes to the JVM to make continuations easier to implement in Groovy. Might this make generators easier to implement in Jython? Perhaps Samuele should get in touch with James...

Also, IBM's developerWorks is running a new series, alt.lang.jre, covering alternate JVM languages. The first article, Get to know Jython, in a nice little intro into, uh, well, I suppose you can work out what it's about for yourself. ;-) I wouldn't be surprised if a Groovy article isn't to far behind.

Posted by Simon Brunning at 01:33 PM | Permalink | Comments (3)
July 05, 2004
Fail Fast

This one's for the team: Null is bad.

Null is bad because it allows errors to float around the system for quite some time before you get any symptoms (like bloody logging code falling over), and well behaved code fails fast, near the source of the problem. Mike gives some other nice examples of fail-fast code, like building stub test cases containing a single Assert.fail("Test not yet implemeted."), so you can't forget to build the test case, and having unimplemented methods in your mock objects throw runtime exceptions, so it's obvious if they get called.

Posted by Simon Brunning at 03:21 PM | Permalink | Comments (3)
June 28, 2004
A Groovey Java meetup

London Java Meetup - 12 July 2004. This meetup's topic is Groovy, James Strachan's dynamic language for the JVM. I've had my say on this before - what does it have that Jython doesn't have? The main answer seems to be that Groovy has a Java-like syntax. Since I prefer Python's syntax, this isn't a big win for me. ;-)

Groovy's other big plus points are either shared with Jython (transparent access to the Java API, ability to create real Java classes) or pretty minor (Groovy has closures).

Python offers me the advantage that I can use (pretty much) the same language for COM scripting, Windows API madness, you name it. Can't do these with Groovy!

Anyway, as I said last time, I like the people, and we never manage to stay on-topic anyway, so I'll be there.

Oh, and a big thanks to Jez for organising these.

Posted by Simon Brunning at 10:50 AM | Permalink | Comments (3)
June 24, 2004
All my favorite toys

Python development with Eclipse and Ant.

Python is my all time favorite tool, and Eclipse isn't far behind, so this has got to be good.

Via Erik.

Posted by Simon Brunning at 09:18 AM | Permalink | Comments (4)
June 23, 2004
Generator expressions are go!

Woohoo! I love Generator expressions, and they are in!

Posted by Simon Brunning at 01:49 PM | Permalink | Comments (0)
June 09, 2004
Jython Development Plugin for Eclipse

Red Robin - Jython


Posted by Simon Brunning at 06:03 PM | Permalink | Comments (2)

There's a new kid on the Java/Python integration block - JPype.

What can you do with this that you can't do with Jython? Well, for some reason I seem to spend a lot of my Python time poking at the Windows API, and Jython doesn't have win32all or ctypes!

Via Erik.

Posted by Simon Brunning at 01:57 PM | Permalink | Comments (0)
May 28, 2004
Log it all! Mwahahahahahaha!

The artful logger.

Logging settings changes? What a good idea! When it comes to logging, less is not more; less is, in fact, less - more is more.

We use log4j to log everything in sight, with a DailyRollingFileAppender to keep from taking up too much space. We do get some pretty hefty log files, though, so we use Tail for Windows to keep an eye on them in real-time, or Python (what else!) to trawl through them if we are looking for something in particular.

Via Joe Grossberg.

Posted by Simon Brunning at 12:30 PM | Permalink | Comments (3)
May 27, 2004
Python 2.3.4

Python 2.3.4 is out.

This is good, but not terribly exciting; Python 2.3.3 worked just fine for me, as did Python 2.3.2, Python 2.3.1, Python 2.3 and, come to think of it, every other final Python release I've ever installed.

Posted by Simon Brunning at 12:48 PM | Permalink | Comments (1)
Cross Platform Open Source more successful?

Cross Platform Open Source more successful? "Python is another language that runs nicely on many platforms and does a great job of making life easy for Windows users. ... Perl, by contrast, seems to have reached it's ceiling in terms of uptake. Outside of ActivePerl think it's fair to say Perl puts *Nix first - perhaps that's the problem."

Me, I'm stuck with Windows, so naturally I'm only interested in software which runs on the cheap whore as well as on the psychotic ex.

Posted by Simon Brunning at 11:48 AM | Permalink | Comments (1)
May 20, 2004
There Can Be Only One

Why separate bin and src distributions?

Good point - but I don't want the docs in a seperate download, either. How about having a batteries-included download with all three; binaries, source, and documentation? That's what I want.

If this ends up being really big, you could have a light binary-only download available too.

Posted by Simon Brunning at 01:44 PM | Permalink | Comments (2)
May 19, 2004
Software Patents

Oh, shit: EU votes through software patent changes. This is bad.

Update 21st May: The Computer Weekly coverage is good: European Council approves 'controversial' software patent draft directive.

Via perfect.

Posted by Simon Brunning at 04:02 PM | Permalink | Comments (10)
A Rose By Any Other Name

A rose by any other name might well be bloody confusing. Naming is important. Sam writes about this in The importance of naming. I thought I'd point out Hacknot's fabulous Naming Classes - Do It Once And Do It Right.

Posted by Simon Brunning at 02:04 PM | Permalink | Comments (3)
May 18, 2004
Jez and Python

Jez is having a play with Python.

He's not getting on with Dive Into Python. Well, I learned from Instant Python, and from the Python Tutorial which comes with the distribution. The first is a very quick overview, and the second is as in-depth as you could ask. Give these a bash, Jez, and see how you get on.

I liked the look of Dive Into Python, I must say, but when I used it as the basis for teaching some Python in-house, I found that it didn't really fit my brain. It introduced things in what seemed a strange order to me - list comprehensions before loops, for example. Maybe that's just me, though - I have no history with functional programming.

Other good resources - well, never forget comp.lang.python, also available as the Python-list. The Python community is one of its major assets. Also, the Python Cookbook is a great source of examples and snippets.

If you find you like it (and you will) and you want some dead tree material, I'd recommend Python in a Nutshell as a reference, and the book version of the Python Cookbook to get a bit of Python Zen.

Speaking of which - try import this from a Python interpretor.

There, that's more than enough to get you started...

Posted by Simon Brunning at 01:34 PM | Permalink | Comments (6)

The Virtues of Chitchat - A modest proposal for using blogs to keep IT teams and management up-to-date on implementation.

We did this three years back, running Squish on Zope. But The Powers That Be made me take it down - we were collecting lots of useful data on software they didn't trust, and they were afraid it might all got lost. So, instead, we just used email for everything. And it all got lost.

I've never got Zope Zen, but installing Zope and wacking Squish, ZWiki, Plone and the like on it are a piece of piss.

Via Slashdot.

Posted by Simon Brunning at 01:06 PM | Permalink | Comments (7)
May 17, 2004
Goto Considered Harmful

Did I call PyOne nasty? I didn't know the half of it!

One problem - this module's come from statement doesn't support arbitrary targets; you can only come from a label. This would be much more deadly useful if you could come from anywhere - though I haven't a clue what the syntax for this might look like. comefrom line number?

Additional reading: Go To Statement Considered Harmful, the "first salvo in the structured programming wars", and Goto Considered Harmful - "Twenty rats in a control group were fed a normal diet, while twenty other rats were forced to program in Apple BASIC".

Posted by Simon Brunning at 12:48 PM | Permalink | Comments (2)
May 12, 2004
Python for Series 60

"Python for Series 60 supports all native Series 60 user interface elements; access to the file system; sockets; and Bluetooth connectivity." Tick, tick, tick. Cool.

Posted by Simon Brunning at 04:36 PM | Permalink | Comments (4)

PyOne - oooh, nasty. In a good way.

Also new (to me, at least) and cool (to me, at least) in the world of Python - EasyDialogs and Win32 Screensaver.

Posted by Simon Brunning at 01:18 PM | Permalink | Comments (1)
May 11, 2004
Just a Little Better Every Day

For some reason, I seem recently to have needed to code a number of functions which take a list of strings as an argument:

setText(aWindow, ['a line', 'another line'])

You often need to pass only one string in, though, and I coded my functions such that you could do this in a 'natural' way:

setText(aWindow, 'just one line this time')

I coded this as follows:

def setText(window, text, append=False):
    # Ensure that text is a list
        text + ''
        text = [text]
    except TypeError:

    # Rest of funtion, which can assume that 'text' is a list of strings

Robin Munn suggested an improvement to this:

        text + ''
    except TypeError:
        test = [text]

Nice. In my version, I'd have a problem in the (unlikely, but not impossible) case of test = [text] throwing a TypeError.

It's not a huge improvement, true, but I like it. A day in which I learn to improve is a day not wasted.

Posted by Simon Brunning at 01:01 PM | Permalink | Comments (16)
May 04, 2004
Data Structures and Algorithms in Python

Data Structures and Algorithms with Object-Oriented Design Patterns in Python.

Via Joey deVilla.

Java, C# and C++ versions also available.

Posted by Simon Brunning at 02:20 PM | Permalink | Comments (1)
Bray on Jython

Groovy is, uh, groovy, but I still don't see what it brings to the game that Jython doesn't already have. Except, that is, for the Java-like syntax - and since I prefer Python's syntax to Java's, that's not really an advantage. ;-)

I must admit that I was a little concerned that Groovy, flavour of the month that it is, might totally eclipse Jython. Well, I'm glad to see that this isn't happening. If anything, Groovy has refocused people's attention on dynamic languages in general, to Jython's benefit. There've been lots of new high profile Jython articles recently, and now we find Tim Bray, Sun's most famous new employee, bigging up Jython, too.

Alan picked out a good summary: "It’s faster to write software in dynamic languages, and the (real) benefits you get from an anally type-sensitive compiler can be had more cheaply with modern testing disciplines. But the theory doesn’t matter, because the action is in the practice, and a whole lot of programmers out there have noticed that, in practice, they can get the job done quicker in Perl or Python or Ruby or whatever". This is pretty much exactly what Bruce Eckel has said already: Eckel on typing Java and Python.

But Bray does add "The best thing for the Java ecosystem would be for both Jython and Groovy to move along, grow and prosper; there’s plenty of room in here". Quite right.

Posted by Simon Brunning at 01:55 PM | Permalink | Comments (6)
April 29, 2004
Don't Return References to Mutable Objects

Don't Return References to Mutable Objects, says Adam Kolawa.

Absolutely right - but for the wrong reason, I think. The security concerns he cites are not the real problem - as Ted Neward points out, if somebody's running code in your VM, you are already dead. No, the problem with returning references to mutable objects is that it's a pistol. It's all to easy for someone else to hose your object by accident. What's more, if this happens, it's a really hard problem to diagnose. You can look at your classes code all day, and put as many breakpoints in there as you want to, and you'll never see where it goes wrong.

Trust me, I know. ;-)

See also Joshua Bloch's Effective Java (which I can't recommend too highly) and Java Practices: Immutable objects.

This is as pertinant to Python as it is to Java, BTW, as is much of Effective Java.

Posted by Simon Brunning at 01:07 PM | Permalink | Comments (5)
April 28, 2004
PyCon DC 2004

Mike Orr has written a nice report: PyCon DC 2004. He covers many talks in detail.

Which reminds me; I must get around to looking at Twisted at some point. Well, I've recently picked up Game Programming With Python, and it's covered there...

More Python related stuff: Alex Martelli's Tightening Python's Grip in Enterprise and How Python Tightens Its Enterprise Grip offer a good introduction to Python for Win32, Java and .NET developers.

Posted by Simon Brunning at 01:15 PM | Permalink | Comments (0)
April 26, 2004
Quote of the day

Why Python is better than Java: What it comes down to is not just that Java places too high a cognitive load on the programmer... it's that Java's just a pain in the ass.

You try RPG, mate. ;-)

Posted by Simon Brunning at 04:23 PM | Permalink | Comments (5)
April 23, 2004
UK Open Source trade association

Open Sourcerers get UK trade body. "The association will promote open source in general, and Zope, Plone and Python technolgies in particular." Cool! Good job, Andy and Seb.

Visit the association at Zope UK.

Posted by Simon Brunning at 03:17 PM | Permalink | Comments (0)
Python for Nokia Series 60

Looks like it's really happening: Amaretto: Nokia's Python for Series 60.

Update: There's a nice write up on this in the Grauniad: Ben Hammersley's Let's get personal.

If this becomes generally available, it'll mean the end of cheapo pay-as-you-go phones for me.

Posted by Simon Brunning at 03:02 PM | Permalink | Comments (3)
April 21, 2004
Command line parsing

I mentioned Michele Simionato's lovely command line parser the other day. The nice thing about this is that it takes the command line option definitions from a human readable definition in the module's docstring.

David Boddie commented on this recipe, pointing out his lovely command line parser. The nice thing about this one is that it can throw up an automatically generated GUI form allowing the options to be specified in addition to accepting the options from the command line. (There's nothing new in the world - this is similar in concept to the way the iSeries' commands work.) But the syntax that David's parser uses isn't too user friendly.

So, what I'd really like would be a combination of the two approaches; David's GUI generating parser, but driven from a human readable docstring. Well, I have the code to both, so I'll have a bash at a cut-n-shunt job.

Posted by Simon Brunning at 01:18 PM | Permalink | Comments (14)
End of Jython hiatus

Things are happening in Jython land again. Firstly, there's a new alpha release. It's not ready for the real world yet, it's true, but it's nice to see concrete progress.

Also, there have been a number of Jython related articles and blog postings recently; The Way You Develop Web Applications May Be Wrong, Fun with Jython, Introduction to Jython, Part 1: Java programming made easier and Part 2: Programming essentials, and Simplify Web development with Jython, Spring and Velocity.

Which brings me on to Spring. I'm always a bit suspicious when something looks too good to be true, (after all, why settle for snake-oil then you can have the whole snake,) but Sam assures me that Spring really is as good as it claims to be, so I'm tempted to give it a bash.

Update: A couple more good recent Jython articles: Use Jython to Write Ant Tasks and Learn how to write DB2 JDBC tools in Jython.

Posted by Simon Brunning at 12:32 PM | Permalink | Comments (9)
Where to put Python

Rand Anderson seems to regret installing Python to c:\dev\python23 on his Windows box. Hmmm, that's exactly the same place that I install it to, and it's never given me a moment's trouble. I wonder what is giving him problems?

Posted by Simon Brunning at 12:12 PM | Permalink | Comments (0)
April 19, 2004
Python recipes

There have been a couple of very interesting Python recipes added to the Python Cookbook recently.

I love Michele Simionato's Parsing the command line. Parsing the module's docstring for the command line options is a brilliant idea. It feels really pythonic; most other languages, for example, treat indentation as purely documentary, and require you to repeat your code block delimitation using delimitation characters and using indentation, whereas Python treats the indentation as definitive, and doesn't require you to repeat yourself - DRY! Similarly, this recipe treats the docstring's definition of the supported command line options as definitive, and doesn't require you to repeat yourself.

Raymond Hettinger's Bind Globals into Constants at compile time is a lovely example of the kind of thing that Python 2.4's method decorators are designed to support.

I have to say, I'm not that keen on the current decorator syntax; a list of decorators on the line preceding the function/method definition looks ugly to me. I'd prefer the decorators in the def statement somewhere, or inside the function somewhere, like the docstring. But what do I know; Guido's the world-class language designer, after all!

Posted by Simon Brunning at 12:43 PM | Permalink | Comments (13)
How was Python UK 2004?

How was Python UK 2004? Python Programmer Weblogs, python-uk and c.l.py are all silent on it...

Posted by Simon Brunning at 10:52 AM | Permalink | Comments (1)
April 16, 2004

Somehow, I've not come across Epydoc before. I'll have to give it a bash: look what a lovley job it makes of the standard library!

Posted by Simon Brunning at 02:35 PM | Permalink | Comments (2)
Converting Word documents to text

The thing I love about Python is that if it sounds simple, it usually is. Here's a script to save all Word documents in and below a given directory to text:

import fnmatch, os, pythoncom, sys, win32com.client

wordapp = win32com.client.gencache.EnsureDispatch("Word.Application")

    for path, dirs, files in os.walk(sys.argv[1]):
        for doc in [os.path.abspath(os.path.join(path, filename)) for filename in files if fnmatch.fnmatch(filename, '*.doc')]:
            print "processing %s" % doc
            docastxt = doc.rstrip('doc') + 'txt'
            wordapp.ActiveDocument.SaveAs(docastxt, FileFormat=win32com.client.constants.wdFormatTextLineBreaks)

Requires Python and the Python for Windows extensions.

My stepmother has been horribly virus hit, so I'm off to rebuild her PC this weekend. Sigh. I'll burn a CD with all her data before the rebuild, of course, but I'm worried that some or all of her documents might be infected - so I'll back them all up as text files, too, so that in the last resort, she'll still have all her work.

Update: As Ryan points out, it also requires a copy of Word. Thanks, Ryan: I should have mentioned that.

Another update: I cleaned this up a little and submitted it as a Python Cookbook recipe: Converting Word documents to text.

BTW, the rebuild was a nightmare. Win2K refused to recognise the modem, which is, of course, the worst thing that could possibly have happened. I ended up buying a new one. The whole job, including running Windows Update etc, ended up taking over nine hours!

Posted by Simon Brunning at 02:32 PM | Permalink | Comments (14)
April 15, 2004
Python UK conference tomorrow

Good luck to all the organisers and attendees at the UK Python Conference 2004, which starts tomorrow. Have fun, ladies and gentleman. I wish I could be there with you...

Posted by Simon Brunning at 01:02 PM | Permalink | Comments (2)
April 13, 2004

Brian Edwards has put together Java port of winGuiAuto.py. Little does he know that I've been cleaning this up over the last week or so, a version 1.0 release is just days away, and he'll have to do it all over again. Mwahahahahaha!

Seriously, Brian, cool stuff. BTW, you use Coroutine for Java, and say that you are looking for an open source alternative. Well, I gather that there's a Java port of Thomas Heller's fabulous ctypes module in the works: ctypes-java. You might want to take a look.

Also, did you do any of the Python to Java conversion automatically? (It certainly looks like it.) What did you use?

Posted by Simon Brunning at 05:10 PM | Permalink | Comments (6)
A language comparison: postcode splitting in RPG and Python

As you might have guessed from my last post, I've got some postcode parsing to do. The requirement is pretty simple; I have to parse a postcode into an outcode and (optional) incode. The good new is that I don't have to perform any validation - I just have to chop up what I've been provided with in a vaguely intelligent manner. I can't assume much about my import in terms of formatting, i.e. case and embedded spaces. But this isn't the bad news; the bad news is that I have to do it all in RPG. :-(

Nevertheless, I threw a little Python function together to clarify my thinking. I often do this when I'm coding something nasty in Java. It's worthwhile to make sure that the algorithm that I'm using works before grappling with Java, and Python is perfect for this. And given RPG's awkwardness, it's worth prototyping even the simplest algorithm - you don't want to spend all that time cutting code only to find that it doesn't work even in principal!

Anyway, the Python function:

def parse_uk_postcode(postcode):
    postcode = postcode.replace(' ', '').upper()
    if len(postcode) <= 4:
        return postcode, ''
        return postcode[:-3], postcode[-3:]

(A syntax highlighted version with unit tests here: postcode.py.)

Then I put the RPG version together: postcode.rpg. It's much longer and ugler, but it seems to work.

This is a very tolerant way of dealing with postcodes. It will accept just about anything. In my case, that's what I want; I'm pulling data in from a big SAP database. If that's inaccurate, it's definitively inaccurate. ;-)

In other cases, you might want to validate the postcode. Even here, you have more than one choice. One approach is to make sure that the postcode follows the rules as specified at the Universal Postal Union and the UK Govornment Data Standards Catalogue. I've coded this up: postcode_strict.py. This might even be useful to someone! (I didn't bother with an RPG version of this; I don't need one, and life's too short for writing this kind of thing in RPG if you don't really need it.) The other approach would be to validate against a list, should you have one. Duncan Gough steered me towards Brainstorm's downlaodable postcode lists, but these contain outcodes only.

Oh, BTW, any suggested improvements to any of these functions in any of these languages would be gratefully recieved, as would Java versions for comparison.

Update 14th April: Alan Green's done a Java version of the simple version. Thanks, Alan!

Also, I've spotted a bug in the strict version, which I'll fix at lunchtime. Basically, I'm using the list of characters valid at the 4th position to check characters at both the 3rd and 4th positions. This is incorrect; there's a different list of valid characters for the 3rd position. :-(

Another update 14th April: It's fixed, it works now, and I've even added a docstring or two. Look at postcode.py, or download a zip file containing postcode.py.

Posted by Simon Brunning at 04:57 PM | Permalink | Comments (18)
April 05, 2004
Eckel on typing Java and Python

Bruce Eckel (of Thinking in Java fame) has been posting recently on his increasing disillusionment with Java's typing scheme, and how's he's finding that what he calls "Latent" typing is better, in practice if not in theory. (Eckel's "Latent" typing is what a Pythoneer would probably call "Dynamic" typing and a Ruby-head "Duck" typing.) The whole set of posts are worth a read: Generics Aren't, About Latent Typing, How to Argue about Typing and I'm Over It.

Posted by Simon Brunning at 02:10 PM | Permalink | Comments (2)
March 22, 2004
Karmic feedback

I'm getting a spot of Karmic feedback for taking the piss out of Mark for his burger flipping VB6 programming - I'm starting on a six week RPGIV project at a client site next week!

This is bad: in decreasing order of love, my used-at-work programming languages are:

As you can see, RPGIV isn't high on the list. Sigh.

Still, I'll be working with one or two people I know and like, so it isn't all bad.

Posted by Simon Brunning at 04:29 PM | Permalink | Comments (9)
March 16, 2004
Joel on Python

Joel on Python: "I'm sure most programmers consider this [semantically meaningful indentation] to be frighteningly annoying, but most programmers are wrong. Giving indentation semantic meaning is a stroke of genius. In one fell swoop, it forces code to be indented neatly and correctly, while avoiding an entire class of bugs caused by code that looks like it's doing X when it's really doing Y and averting a whole class of worthless flamewars."

Python is full of strokes of genius; this is merely one of the most obvious, in-your-face examples.

Joel also says that he doesn't have the time to learn Python. But then, elsewhere, he says that he uses VB for scripting!

Joel - really, you can't afford not to learn Python!

Posted by Simon Brunning at 02:04 PM | Permalink | Comments (5)
March 15, 2004
Instant web server

Instant web server.

Every now and again, even I'm amazed by how cool Python is.

Hey, how about combining this with Hans' Windows Explorer integration? Right click on a folder, "Serve from here"? I'll give this a bash at lunchtime...

Posted by Simon Brunning at 10:59 AM | Permalink | Comments (11)
February 26, 2004
Impromptu London Python Meetup

There's an impromptu London Python meetup this evening at The Chandos, near Trafalgar Square. I had already arranged to meet Steve for a beer, so we changed venue; I'll be there.

Posted by Simon Brunning at 10:13 AM | Permalink | Comments (3)
February 17, 2004
Why Python people are so nice to each other

It last night's Java Meetup, I worked out why it is that Python people are so nice to one another; we don't have braces, so we don't have brace wars.

Posted by Simon Brunning at 10:40 AM | Permalink | Comments (6)
February 16, 2004
What's new in Python 2.4

What's New in Python 2.4.

What about Generator Expressions? I hope that they are in there!

The new keyword arguments on lists' sort() method are also really nice, simplifying the DSU idiom. (Or is that a texture?)

Via Daily Python-URL.

Posted by Simon Brunning at 12:50 PM | Permalink | Comments (2)
February 13, 2004
I may have to get new mobile

I've been surprisingly uninterested in mobile phones in the past. I've been more than happy with my pay-as-you-go Nokia 3110.

But that may be about to change. Very cool stuff.

Posted by Simon Brunning at 10:05 AM | Permalink | Comments (2)
February 12, 2004
PDF generation

Scope creep; it'll get you every time.

An important part of the system that I'm currently working on is a financial statement. This needs to be printable, and to look good when printed. To begin with, I was confident that CSS styled HTML would do the necessary. But now I find that we need this statement to look exactly the same as the paper one that users currently get, including things like fonts and the location of page breaks. Also, the client now wants cross referencing; "See page 12 for a breakdown", that kind of thing. So, HTML ain't gonna cut it, CSS or no CSS. Sigh.

Naturally at this point, we looked at PDF. We can do all the above and more with PDF. But how to generate it?

Generating PDF is nothing like generating HTML. It's a binary format with all sorts of indexing and cross referencing. You can't just use a template tool like JSP or Velocity. (In fact, it's a sort of wrapped and compressed Postscript. Postscript is actually an executable format.) So, we need a tool to generate our PDF for us. (The tool doesn't have to be for Java/J2EE, though that would help.)

Naturally, I looked at Reportlab. Their RML2PDF tool is exactly what we are looking for; we could easily generate the required RML (an XML dialect) file from a JSP. But, look at the price! RML2PDF is simply way beyond our budget. Sorry, Andy. :-(

Some of the other commercial offerings are rather a lot cheaper. Style Report, for instance, can be driven from Java objects or direct from SQL, and includes a JSP taglib, so it would fit right into our current architecture. Mark is evaluating tis product, along with ReportMill, Formula One e.Report and Crystal Reports. If anyone has used any of these, please let us know how it went!

On the OSS front, iText looked promising, but we aren't allowed GPL software on our products. (No, not even LGPL software; its meaning is ambiguous in the context of a Java application, and we don't intend taking any risks.) The other OSS tools either had the same license issues, or were at too low a level, or both.

So, what does everyone else use?

Posted by Simon Brunning at 03:06 PM | Permalink | Comments (22)
February 06, 2004
What's wrong with J2EE

Mike Clark and Glenn Vanderburg have been pondering J2EE's complexity.

Now, I've been buried up to my neck in J2EE for a while now, and from this position it's easy to loose sight of the big picture. We are using lots of neat toys, each of which helps me out in one way or another, so I'm happy to have them. Since they really do all help, I'm right to be happy.

El Presidente, though, looks upon this huge list with more than a little trepidation. And he's right too; we are using a lot of tools, many of which are fairly complex. By rights, our project is a fairly simple one. What do we need all this stuff for? (And we've kept the list as short as we comfortably can, believe me!)

Well, J2EE is at least part of the problem. A simple 'Hello World' application isn't, well, simple in J2EE. Servlets, JSPs, the deployment descriptor, the WAR file, the context, and so on.

You might argue that this is because J2EE isn't designed for simple applications. And you'd be right; it's designed for complex applications; it scales well. This is true up to a point. But. But if it scaled that well, we wouldn't need all this other stuff, would we? (An MVC framework, a persistence layer, additional taglibs, etc, etc, etc.)

(OK, so, I know that J2EE has its own persistence layer: EJBs. But I've been warned off them so many times I didn't even consider them. Also, The new JSP 2.0 includes the JSTL, removing much of the need for external taglibs.)

But the other side of the problem is Java itself. I think that at heart, Glenn has it right. Java is not amenable to extension, and J2EE extends it well beyond what ESR refers to as its 'functional envelope'.

Python doesn't have a J2EE, but if it did, I suspect that it would be far simpler.

Still, I can't say I'm not having fun with all this stuff, so it isn't all bad. ;-)

Posted by Simon Brunning at 02:01 PM | Permalink | Comments (5)
February 05, 2004
UK Python Conference 2004

It's on. Which is good.

The bad news is that unless my finances take a radical turn for the better within the next two months, I'll not be going. :-(

My company has no interest in Python, so it'll be self financing or nothing.

Posted by Simon Brunning at 05:01 PM | Permalink | Comments (0)
Python: The Programming Language for Nice People

Alan Green: "In general, the Python blogging community is full of interesting people, who are capable of expressing themselves clearly, who are polite and who can respect alternative points of view. Does the language rub off on the people or do the people rub off on the language?" Modesty forbids my linking directly to Alan's post. ;-)

Well, I can't answer the question, but I will point out that it's not just the blogs; comp.lang.python is also full of exceptionally nice, helpful people. So, there is certainly some kind of link here...

Posted by Simon Brunning at 12:57 PM | Permalink | Comments (3)
February 02, 2004
A Decimal Data Type - PEP 327

PEP 327 appears to be exactly what I've been hoping for - an immutable decimal data type in the Python standard library.

+1 from me. ;-)

Posted by Simon Brunning at 10:42 AM | Permalink | Comments (1)
January 07, 2004
Getting Windows version information in Python

I recently needed to find out which version of Windows on of my scripts was running on. Python 2.3 introduced the os.sys.getwindowsversion() function, which gives you exactly that, but interpreting its output is a bit of a trick. It turns out that it's a fairly thin wrap of GetVersionEx(), and its output is an OSVERSIONINFO structure unpacked into a tuple. So, how's this for a nasty one-liner?

win_version = {(1, 4, 0): "95", (1, 4, 10): "98", (1, 4, 90): "ME", (2, 4, 0): "NT", (2, 5, 0): "2K", (2, 5, 1): "XP"}[os.sys.getwindowsversion()[3], os.sys.getwindowsversion()[0], os.sys.getwindowsversion()[1]]

I suppose I really ought to turn this into a function... ;-)

BTW, I've only tested this on NT and up - if it works (or otherwise) on 9x platforms, I'd love to hear from you.

Posted by Simon Brunning at 01:05 PM | Permalink | Comments (7)
January 05, 2004
Browser as Desktop UI

Bruce Eckel posts a nice example of a program which uses a browser as its GUI on a single PC - Browser as Desktop UI. Class. I'll give this approach a go Real Soon Now.

Posted by Simon Brunning at 02:16 PM | Permalink | Comments (9)
JavaScript in Python

python-spidermonkey, a Python/JavaScript bridge module. Cool, but if I'm honest, I can't see any use for this for me at the moment...

Via Simon Willison.

Posted by Simon Brunning at 02:00 PM | Permalink | Comments (2)
December 17, 2003
Joel on Windows and Unix

I friend of mine recently referred to Joel as "A pompous, opinionated windbag". Which raised a laugh, I must say, but it isn't really fair. Joel's writing varies between the insightful and the frankly flaky, it's true, but I think that the former predominates.

In Biculturalism, he sums up the differences between the Windows and Unix cultures with: "Unix culture values code which is useful to other programmers, while Windows culture values code which is useful to non-programmers".

He was prompted to think about this while reading Eric S. Raymond's excellent The Art of UNIX Programming. ESR can be rather flaky himself at times - he's a gun nut, for one thing, and we really don't see his point on this side of the pond. But on technical issues his judgement is superb. We already knew that he likes Python. In The Art of UNIX Programming, we see him give an overview of Python and Java, amongst other languages. He's pretty fair, I'd say, but his preference is clear.

Posted by Simon Brunning at 04:14 PM | Permalink | Comments (8)
December 15, 2003

Microsoft employs human beings shock!

Tweakomatic looks like a nice toy, allowing you to do all the cool things that you can do with TweakUI with WMI scripts. All this from Microsoft themselves! Free! (As in beer, not as in speech. Totally unsupported. May contain nuts.)

The Scriptomatic Tool also looks interesting. I wonder if those auto generated scripts can be translated into Python? Oooh, Tim Golden's wmi.py looks just the ticket... ;-)

Via Sanjay.

Posted by Simon Brunning at 01:05 PM | Permalink | Comments (1)
December 08, 2003

Oh, bugger, I'd better get winGuiAuto.py cleaned up and ready for release, hadn't I? ;-)

I need to:

  • Finish the docstrings.
  • Add list box support.
  • Write some simple docs and examples.
  • Build an installer script.

Oh, and register it on PyPI. And that will be version 1.0 done.

I'm already thinking of a version 2. Version 1 is a bit old-school, really. There's plenty of passing hwnds around going on, and I don't want that. I'd like to make version 2 object oriented. I'm having one major problem working out how this would work, though.

Clearly, there will be a Window class, and creating its instances will be created in much the same way as you'd currently get a hwnd using the findTopWindow() function. Then you'd ask this Window instance for its controls. The problem is that I'd expect the Control class to be abstract, and to have concrete classes like Button, ComboBox, EditBox and so on. These classes would have only the behaviours applicable to the control. But I don't know how to find out which of these classes to use for a given control - or even if it's possible in principle to make that decision.

Ah, bugger it. I'd better concentrate on finishing version 1 before I get too carried away...

Update: Firstly: a somewhat updated version of winGuiAuto.py.

Secondly, I gather that in order to work out what kind of control I have the Window Style might come in handy. I'll look into it. Thanks to "Lucky" Campbell for this hint. ;-)

Posted by Simon Brunning at 12:58 PM | Permalink | Comments (9)
December 04, 2003
Python Bounties

Mark Shuttleworth is at it again!

I've mentioned Mark's SchoolTool project before. Now, he's offering to fund work towards building Python scripting interfaces.

Hmmm. I woinder if he's be interested in my Windows GUI automation stuff - scripting the unscriptable? Probably not - looks like it's all Linux stiff. Ho hum.

Via Jeremy Hylton.

Posted by Simon Brunning at 12:33 PM | Permalink | Comments (0)
December 03, 2003
Running PyChecker from PythonWin

Python tip of the day: Running PyChecker from PythonWin.

Posted by Simon Brunning at 05:15 PM | Permalink | Comments (0)
December 01, 2003

When trying to explain the difference between dynamic typing and weak typing, I used to refer to this page (specifically the Addendum at the bottom). I still will - it's brief, but gets the point across.

For the long version, though, in future I'll refer to What the heck is: A type.

Posted by Simon Brunning at 01:48 PM | Permalink | Comments (6)
November 19, 2003
7 hours, one line of code

Some days, the code just flows. But not when you are calling the Windows API. :-(

I've been working a bit more on Windows GUI automation, specifically on combo boxes.

The problem was with automating the selection of items in the combo. To begin with, I was just sending a CB_SETCURSEL message to the combo, like so:

win32gui.SendMessage(hwnd, win32con.CB_SETCURSEL, item, 0)

This did the selection in the combo box so far as I could see, but it wasn't sticking - the changed selection wasn't having any effect on the rest of the dialog.

Turns out, I need also to send a CBN_SELCHANGE, too. Finding this out, along with working out how to send the bloody thing, has taken all day. Sigh.

For what it's worth, here is the final (working?) selectComboboxItem() function, and the whole winGuiAuto module. This is work in progress, mind, but you're welcome to it if it's useful to you.

Posted by Simon Brunning at 04:56 PM | Permalink | Comments (7)
November 17, 2003
Jython taglib

The Jython taglib allows you to embed Jython code in your JSPs. I'm not suggesting that this is a good idea, but it's there if you want it. ;-)

Posted by Simon Brunning at 03:57 PM | Permalink | Comments (1)

Hmmm. I like to feel that I'm pretty cutting edge, pretty state of the art. So, it's pretty embarrassing for me to admit it, but I've been caught well behind the curve when it comes to LOAF. Until this morning, I didn't even really understand what LOAF was for. Can you imagine that!

Perhaps, though, it's understandable. A paradigm shift of this magnitude doesn't come along every day. The 'net will never be the same again. Empowerment through standards.

Well, anyway, you'll be pleased to know that Small Values is now fully LOAF compliant.

Posted by Simon Brunning at 02:16 PM | Permalink | Comments (9)

"Unum is a Python module that allows defining and manipulating true quantities, i.e. numbers with units like volts, hours, meter-per-second. Consistency between units is checked at each expression evaluation; unit conversion and unit output formatting are performed automatically when needed."

I mainly work on reinsurance industry software, and we only really care about money, so I won't find much use for this. But it's worth keeping a note of - should I ever need to work with physical quantities in future, this package looks like it would be worth its weight in gold.

Posted by Simon Brunning at 12:05 PM | Permalink | Comments (0)
November 10, 2003
Python UK 2004

Right - diaries out. Python UK 2004, Friday 16th and Saturday 17th April, Oxford.

Posted by Simon Brunning at 03:59 PM | Permalink | Comments (3)
About @*^#{@~ time!

The Daily Python URL goes RSS!

Posted by Simon Brunning at 10:05 AM | Permalink | Comments (7)

Fame and influence at last!

Well, not that much influence. ;-)

Jokes apart, it's nice that in land of Python, the little man like me has a voice. Better to be heard and disagreed with than ignored. And Guido ahs, to say the least, a history of getting things right. If he thinks 'magic strings' should remain, the chances are he's right.

Posted by Simon Brunning at 09:43 AM | Permalink | Comments (0)
November 07, 2003
Code Kata

Steve's just about getting to the end of Head First Java now. (Which, BTW, he recommends.) He's going to work through Thinking In Java next, which I recommend.

But I've also advised him not to stick too closely to book learning. The best thing to do, I find, is dive off onto real coding whenever you have an idea for something to write. Do as much as you can, then and when you get stuck, go back to the books until you have another brain wave.

Robocode is great for this, if you are learning Java. You can write a simple robot very quickly, but the sky's the limit - as you work through the books, you'll get ideas for all sorts of clever things that you can do.

Another good source of ideas are Dave Thomas's Code Kata. Not just good for newbies, these coding exercises are good practise for anyone. I see Andy and Ian have been using them. I may have a go myself!

Posted by Simon Brunning at 01:54 PM | Permalink | Comments (3)
November 06, 2003
Garbage collection

Java theory and practice: A brief history of garbage collection. A good, high-level overview of the subject.

Posted by Simon Brunning at 02:42 PM | Permalink | Comments (2)

The SchoolTool project isn't making too much of a wake at the moment, but I suspect that before too long, there will be a bit more buzz around it.

SchoolTool is (or will be) a fully open source, free education administration system. Think SAP for schools. It's written in Python, with an interesting and flexible architecture.

The project is being funded by The Shuttleworth Foundation, as founded by Mark Shuttleworth. Yes, that Mark Shuttleworth.

Mark was at last year's Python UK conference. He was already planning this project at that time, and he was looking for people to work with. He basically wanted someone with strong Python skills, and lots of XP experience. Since I don't really fit the former category, and I don't even remotely fit the latter, I wasn't the man that he was looking for. Which was a bit of a shame. But I though I knew a man who was - Steve Alexander, whom I'd met at a previous Python UK conference.

Bizarrely enough, I bumped into Steve on a crowded train to Reading just a couple of weeks later, and I mentioned Mark's project to him. Steve was (and is) working in Lithuania, so it seemed to me unlikely that Steve would be able to join the project. I was under the impression that Mark wanted the it all be based in London. But, with Steve's permission, I passed his contact details on to Mark anyway.

Clearly I was wrong, since Steve is now on the SchoolTool team. Cool! I suppose that these days, there's little reason why a project needs to be based on any one place, after all.

So, anyway, if you want to contribute to a truly worthy open source project, SchoolTool could be your man. I wish it luck.

Posted by Simon Brunning at 02:09 PM | Permalink | Comments (0)
November 05, 2003
Game Programming With Python

I'd not heard about the Game Programming With Python book, but it seems that it's out. Blinding.

Posted by Simon Brunning at 01:35 PM | Permalink | Comments (0)
Don't like fireworks?

Don't have tickets for Revolutions tonight? Like beer? Got a high nerd threshold?

Then come along and meet Steve, Andy and I this evening at the The Porterhouse London in Covent Garden.

If pervious meetings are anything to go by, we'll talk about Java, Python, blogging, perhaps a bit of DHTML, and any other nerdy stuff that springs to mind.

Oh, and birds, and beer. And probably Australia.

Posted by Simon Brunning at 09:21 AM | Permalink | Comments (2)
November 04, 2003
Python Quick Reference

Python 2.3 Quick Reference. Don't leave home without it.

Bravo, Richard.

Posted by Simon Brunning at 03:24 PM | Permalink | Comments (1)
Fixing Windows shortcuts

I've just about installed everything I need now, but there are still a few things that I only use occasionally, and which I'm installing as I come to need them. There is, though, one big problem all of a sudden.

For some poorly understood reason, whenever anyone installs any Windows software at my place of work, all the program groups and shortcuts get put into the 'all users' profile, rather than into one's own profile. Most of us remember to move these to our own profiles, lest other users pick these up when they next log in. Most of us. Most of the time. ;-)

At least, this is what used to happen. Now, our network fascists team have removed everyone's write authority to the 'all users' profile. Which means that you now get no program groups and shortcuts when you install stuff. Usually this doesn't matter, 'cos you can create your own. Some software, though, needs shortcuts which aren't so easy to create manually. One product that I use creates 30+ shortcuts, each with different arguments.

To create these, I just zipped up the appropriate program group from someone else's PC. But of course, all these shortcuts have the wrong paths in them. Sigh.

Python to the rescue! Mark Hammond's Python Extensions package contains working example code in link.py. With this, you can knock up a quick-and dirty like fix_paths.py in a couple of minutes, and away you go.

Posted by Simon Brunning at 02:29 PM | Permalink | Comments (2)
November 03, 2003
Generator Expressions

PEP 289 -- Generator Expressions

I like this proposal. (Sorry, Hans!)

Python's List Comprehensions have long been a favourite of mine - powerful, and terse without being difficult to read or, uh, comprehend. (Those with only one for, that is. List comprehensions with multiple fors overflow my brain.)

But I must admit - I don't like the name much. 'Comprehension' - what does that have to do with anything?

List comprehensions always create the whole list. You don't always need the whole list at once, and if the list is big (or contains big objects), this might be a problem memory-wise. And if course, if your 'list' is infinite you can't materialise it at all! Python's generators are perfect for dealing with large or potentially infinite sequences.

PEP 289 proposes a list comprehension like syntax for creating generators - the generator expression.

Since the output of any finite generator can be turned into a list using the list() built-in, the existing list comprehension syntax will become merely syntax sugar for a generator expression so wrapped. But by wrapping in calls to dict() or tuple() or so on, one can create dictionaries and tuples as easily as lists.

Also, generator comprehensions are a natural fit with reduction functions like sum() - why materialise a whole list at once just to add up the numbers? New reduction functions are also planned to take advantage - though I hope these go into a module, rather than bulk out the built-ins too much.

All this, and a name that makes sense!

Posted by Simon Brunning at 05:11 PM | Permalink | Comments (4)
October 31, 2003
Tuple arguments

I've just come across this while browsing through Python-Dev - tuple arguments. WTF?

So, you can do:

>>> def f(a, (b, c), d):
... print a, b, c, d
>>> f('a', ('b', 'c'), 'd')
a b c d

What I can't work out is - why?

Posted by Simon Brunning at 05:27 PM | Permalink | Comments (7)
October 09, 2003
Zip it

I'm rather pleased with this c.l.py post of mine. Python never ceases to impress me, to give me that "how cool is that?" feeling.

Andy wanted to know how it worked. Here goes:

The zip() built-in function takes a number of sequences as arguments, and returns a list of tuples, each tuple consisting of the nth element of each of the argument sequences. That makes no sense, does it? Never mind, it's easier to demonstrate than to explain:

>>> zip(['a', 'b', 'c'], [1, 2, 3])
[('a', 1), ('b', 2), ('c', 3)]

There, now that makes sense. ;-)

But the OP had a list of lists, like so:

>>> spam = [['-', '-', '-', '-', '-', '-', '-', 'K', 'S', 'A', 'K'], ['-', '-', '-', '-', 'L', 'Q', 'Q', 'T', 'N', 'S', 'E'], ['T', 'L', 'E', 'E', 'L', 'M', 'K', 'L', 'S', 'P', 'E']]

If you just pass spam to zip(), well, that's only one sequence. It's a sequence containing sequences, yes, but it's just a sequence nevertheless. So you'll get a list of tuples, each containing just one of spam's sub lists:

>>> zip(spam)
[(['-', '-', '-', '-', '-', '-', '-', 'K', 'S', 'A', 'K'],), (['-', '-', '-', '-', 'L', 'Q', 'Q', 'T', 'N', 'S', 'E'],), (['T', 'L', 'E', 'E', 'L', 'M', 'K', 'L', 'S', 'P', 'E'],)]

What we actually want to do is to pass each of spam's sub lists into zip() as a seperate argument. We can do this the brute force way easily enough:

>>> zip(spam[0], spam[1], spam[2])
[('-', '-', 'T'), ('-', '-', 'L'), ('-', '-', 'E'), ('-', '-', 'E'), ('-', 'L', 'L'), ('-', 'Q', 'M'), ('-', 'Q', 'K'), ('K', 'T', 'L'), ('S', 'N', 'S'), ('A', 'S', 'P'), ('K', 'E', 'E')]

This give the OP what he was asking for. But I don't want to give you that. It's ugly, doesn't scale well to lists with many sub-lists, and only works if the sublist has a specific number of sub-lists. And being Python, there's a nice way of doing it.

Python's function argument handling is pretty sophisticated in comparison to other languages that I know. You've always been able to define a function that is able to take any number of arguments. The function receives these argument as a tuple:

>>> def clever(*args):
... print args
>>> clever(1, 2, 3)
(1, 2, 3)

Python 2.0 introduced a new way of calling a function with a tuple of arguments. Just pass in the sequence, prefixed with an asterisk, and each element of the sequence gets passed into your function as a separate positional argument

>>> eggs = [1, 2, 3]
>>> clever(*eggs)
(1, 2, 3)

We can use this feature to pass each element of code>spam to zip() separately, as so:

>>> zip(*spam)
[('-', '-', 'T'), ('-', '-', 'L'), ('-', '-', 'E'), ('-', '-', 'E'), ('-', 'L', 'L'), ('-', 'Q', 'M'), ('-', 'Q', 'K'), ('K', 'T', 'L'), ('S', 'N', 'S'), ('A', 'S', 'P'), ('K', 'E', 'E')]


Posted by Simon Brunning at 11:54 AM | Permalink | Comments (4)
October 08, 2003
Web applications rule the enterprise

Developers show their independent streak, favoring Web-based apps

Actually, legacy applications in COBOL and RPG rule the enterprise in my experience. But in terms of new enterprise applications, I can certainly believe that web based applications are very popular. The advantages are huge, provided that you don't need any UI that a browser based app can't give you. (And as this DHTML widget shows, a browser can give you more than you might expect.)

Posted by Simon Brunning at 02:00 PM | Permalink | Comments (3)
Scroll Lock

What's the "Scroll Lock" key on my computer for?

It even mentions Python, though I must point out that using back-ticks instead of the repr() function is not the done thing these days.

The Windows key is actually pretty useful, and can be made more so.

Posted by Simon Brunning at 10:49 AM | Permalink | Comments (15)
October 07, 2003
Running mod_python on Apache on Windows

Running mod_python on Apache on Windows. Just keeping the link in case I need it later myself. ;-)

Posted by Simon Brunning at 11:33 AM | Permalink | Comments (9)
PythonCard and Boa Constructor

PythonCard and Boa Constructor not ready yet, according to Andrew Dalke.

His major criticism of both tools is that there is no support for any layout management other than absolute positioning. This is a fair criticism - many of your dialogs need to be resizable, and absolute positioning just won't cut the mustard. But then again, many dialogs don't need to be resizable, and I've found that PythonCard works fine for these.

Support for layout management is in the pipeline for PythonCard, and I'm looking forward to it. (How close is it, Andy?) Until then. you'll need to hand code some of your panels. (I'm just learning a bit of wxPython now - this section from Mark Hammond and Andy Robinson's "Python Programming on Win32" is a good starting point.) But PythonCard can already help you out with many (most?) dialogues, saving lots of time.

Posted by Simon Brunning at 11:26 AM | Permalink | Comments (4)
September 25, 2003
Failure and Exceptions

In Failure and Exceptions, James Gosling argues the case for checked exceptions. (Bruce Eckel makes the opposite case in Does Java need Checked Exceptions?).

Gosling's argument seems weak to me. He claims that it's impossible to test every circumstance, especially the unexpected, (which is true), and that exceptions can keep a program working in the face of this. Well, checked exceptions can keep a program from falling over, but that's not the same thing as keeping it working. I'd prefer a program to fall over than for it to keep on truckin', writing crap to a database. This has happened to all of us, I'd imagine, and a clean failure is far preferable.

Besides, in the real world, there often isn't anything you can do in the face of many exceptions, but the compiler insists that you have a catch block for them somewhere anyway. The number of times I've seen them empty...

The workaround in Bruce Eckel's article works fine, but I'd rather have the choice as to how to deal with exceptions, as Python gives me.

Posted by Simon Brunning at 12:38 PM | Permalink | Comments (4)
September 22, 2003
Programming Fonts

Most developers spend a huge amount of time looking at code. Obviously, the quality of your VDU is very important, but it's also important to use a good font.

Obviously, you're going to use a non-proportional font for coding. As a Windows victim user, you get a couple by default. Courier New is just too hideous to contemplate. Lucida Console is better, but both these fonts have one big defect in common - it's hard to distinguish between zeros and upper case letter 'o's. Me, I prefer Andale Mono. (You can download Andale Mono here.)

Ned Batchelder points out Tristan Grimmer's programming fonts. Proggy Clean especially looks really nice for day to day code and text editing. Proggy Tiny, is, well, a bit too tiny for editing with, but it might make a good console font. I'll give them a try.

Update: I've had a look, and I think I'll be sticking with Andale for the moment, though Proggy Clean is almost as nice - it just takes up that tiny bit more room. Some samples: Andale Mono, Proggy Clean, and (for Hans) FixedSys.

(BTW, this code snippet arose because a colleague was struggling using a text editor to open a 1.2 gig log file in order to find all the lines containing a specific exception. A slight variation on this code pulled out the required lines, and took 13 minutes on an oldish PC. Another Python convert, I hope!)

Another update: V S Babu mentions Bitstream Vera in passing. There's a non-proportional font in there which looks pretty nice. An example - Bitstream Vera Sans Mono. But again, I think I'll stick with Andale.

Posted by Simon Brunning at 10:37 AM | Permalink | Comments (14)
September 12, 2003
Groovy, man

James Strachan is working on a new dynamically typed scripting language for the Java platform, Groovy.

I can't say that I understand James' motivation here. Why not just use Jython? Jython's quite behind Python though it is the closest to what I want right now, he says. It's true that the most recent Jython release is equivalent to C Python 2.1, two major releases old. But Python 2.1 was great - it's just that Python 2.3 is better. What does he want that Jython doesn't deliver?

Now, J*, that was a good idea.

Posted by Simon Brunning at 11:12 AM | Permalink | Comments (2)
September 09, 2003
Not my finest hour

There's a debate going on right now on python-dev about what kind of changes are acceptable in micro releases. (Micro releases are where you go from x.y.z to x.y.z+1 - for example, from 2.2.1 to 2.2.2.)

At one point, Fred Drake said "We might not be able to remove a core dump since it would allow code to run that was not run before, thereby changing the behavior of the code".

No one would rely on something like a core dump, right? Well, perhaps, but I was reminded of one of my nastiest ever iSeries hacks, which was very nearly as bad. Scarily enough, this was (and is) used in production code.

Posted by Simon Brunning at 12:31 PM | Permalink | Comments (0)
September 08, 2003
Getter and setter methods are evil

Why getter and setter methods are evil explains, uh, why getter and setter methods are evil. Don't ask for the information you need to do the work; ask the object that has the information to do the work for you, it advises.

I hadn't really thought about this, but it strikes me as good advice. Looking through my own code, I see almost no simple setter methods, and few getters. I do use 'is' type getters fairly frequently, though. This feels OK to me.

This isn't the same thing as Python's reason for avoiding getters and setters, BTW. Python's descriptors mean that you can directly access object attributes without breaking encapsulation, making getters and setters very un-Pythonic.

Update September 9th: Having thought about this overnight, I'm a little concerned that this might be a bit too purist, a bit too principle of least privilege. Yes, so long as the designer of the class has anticipated every need that a client of the class might have, it's better to encapsulate firmly, and to prevent anything unanticipated from happening. In the real world, the designer hasn't thought of everything.

Have you ever raged that a method or attribute that you need to access has been marked private, because the designer of the class that you are using didn't anticipate your every need? I know I have.

Still, the designer should provide a named method for everything for which he/she does anticipate a need. Access to an object's attributes, be it via setters and getters. or directly, strikes me as a code smell.

Posted by Simon Brunning at 11:03 AM | Permalink | Comments (2)
September 04, 2003

Nearly a year ago now, I wrote about persistence. OODBMSs didn't do it for me, so this left the question of how best to use an RDBMS with an OOP language.

A year on, I've still not come across anything which stands out. Not until now, that is. Simon Willison has pointed out SQLObject, and it looks really interesting.

Don't take this as a recommendation, since I've not had a chance to play with this yet, let alone to use it in anger. But it's worth a look, I think.

If and when I do have a chance to give SQLObject a work out, I'll let you know how it goes. If you have any experiences to relate in the meantime, please feel free. ;-)

Posted by Simon Brunning at 03:47 PM | Permalink | Comments (3)
August 28, 2003
Python fixed decimal types and immutability

David is learning Python. He's posted some of his observations, many of which are very interesting - see Python first impressions, Python data hiding and Trust me: I'm a programmer.

Clearly, David is also aware of the problems with using floating point values to hold financial values, since he's found Ng Pheng Siong's Money class. I recommended that he look at FixedPoint instead, since it's pretty much the de facto standard.

But there's one thing that both modules get wrong. As Ka-Ping Yee pointed out on Python-Dev, it's important that any fixed point numeric type be immutable. Both FixedPoint and Ng Pheng Siong's BigDecimal are mutable. For one thing, this means that they cannot safely be used as dictionary keys. But there are other reasons for favouring immutability - simplicity, inherent thread safety, and safe object sharing spring to mind.

I don't know if there is any movement towards including FixedPoint, or something like it, in Python's standard library in version 2.4. I certainly hope so.

Posted by Simon Brunning at 11:30 AM | Permalink | Comments (10)
August 27, 2003
Dynamic languages and virtual machines

In Dynamic languages and virtual machines, Jon Udell discusses Perl and Python implementations on Java's JVM and .NET's CLI.

"Back when .Net was Microsoft's shiny new replacement for boring old Java, the Redmond rhetoricians used to make a couple of points with which I heartily agreed. First, your platform ought not be joined at the hip to a programming language. Different people use different languages for different reasons; it's wise to accommodate them all. Second, dynamic (aka scripting) languages were going to be a .Net priority.

But when ActiveState tried the experiment, it didn't go well. The CLI is, by design, not friendly to dynamic languages."

Looks like Jython is not going to be knocked the number one spot any time soon.

Via the Python Daily URL.

Posted by Simon Brunning at 01:53 PM | Permalink | Comments (1)
Sample aptitude tests?

Steve is looking for sample programmer aptitude tests. Any suggestions?

This one is funny, but Steve is looking for real ones.

Posted by Simon Brunning at 11:25 AM | Permalink | Comments (10)
August 21, 2003
More Ruby goodness

Following up yesterday's What's better about Ruby than Python?, Hans Nowak identifies some more Ruby jewels.

Jeffrey Shell's Ruby/Python comparison posting to c.l.py is also worth a look - Jeffrey obviously knows Ruby pretty well, and he identifies both strengths and weaknesses as compared to Python.

Again, there are ideas here that Python might benefit from stealing, but nothing to tempt me away from Python. All this name, $name, @name, and @@name business appals me.

Posted by Simon Brunning at 12:22 PM | Permalink | Comments (2)
Test versus Type

Oliver Steele's excellent post, Test versus Type, explores at some length the argument that test driven development makes static typing unnecessary at best, positively injurious at worst.

I leave with you with a quotation from Quinn Dunkan:

"The static people talk about rigorously enforced interfaces, correctness proofs, contracts, etc. The dynamic people talk about rigorously enforced testing and say that types only catch a small portion of possible errors. The static people retort that they don't trust tests to cover everything or not have bugs and why write tests for stuff the compiler should test for you, so you shouldn't rely on only tests, and besides static types don't catch a small portion, but a large portion of errors. The dynamic people say no program or test is perfect and static typing is not worth the cost in language complexity and design difficulty for the gain in eliminating a few tests that would have been easy to write anyway, since static types catch a small portion of errors, not a large portion. The static people say static types don't add that much language complexity, and it's not design "difficulty" but an essential part of the process, and they catch a large portion, not a small portion. The dynamic people say they add enormous complexity, and they catch a small portion, and point out that the static people have bad breath. The static people assert that the dynamic people must be too stupid to cope with a real language and rigorous requirements, and are ugly besides.

This is when both sides start throwing rocks."

Via Ted Leung.

Posted by Simon Brunning at 11:27 AM | Permalink | Comments (0)
August 20, 2003
What's better about Ruby than Python?

There is a thread over on c.l.py on this subject.

It's generating orders of magnitude more heat than light. Jeremy Dillworth's post, though, is well worth a read. Certainly nothing here is going to convince me to switch over, but there are ideas here that Python could steal.

Python's way of defining static and class methods is nasty, I have to admit. The Python developers are looking at fixing this, but for the moment, Ruby is prettier here.

Ruby's operator overloading syntax also looks very nice.

Posted by Simon Brunning at 01:53 PM | Permalink | Comments (12)
August 19, 2003
Python - just say NO!

Java Programmers Unite: Say NO To Python

Jokes apart, I don't think that increasing programmer productivity would increase unemployment, at least not in the long term. I think that part of the problem is that too many company boards have had their fingers burned by large IT projects delivering very poor ROIs. The more IT delivers value for money, the more people will be willing to spend.

At least, that's what I'd like to think. Perhaps we are all doomed.

Posted by Simon Brunning at 01:22 PM | Permalink | Comments (4)
WyPy: A Minimal Python Wiki

WyPy implements a basic Wiki in 23 lines of the ugliest Python code I've ever seen. Clever, though, and it works fine.

Via the still-RSS-free Daily Python URL.

Posted by Simon Brunning at 11:47 AM | Permalink | Comments (5)
August 18, 2003
Running Python from a Windows network

A nice little tip from Gerhard Häring - Running Python from a Windows network.

Posted by Simon Brunning at 03:31 PM | Permalink | Comments (0)
August 14, 2003
Python and Java: a Side-by-Side Comparison

Python & Java: a Side-by-Side Comparison

Not the first Java vs. Python comparison around, but one of the better ones, I think.

Posted by Simon Brunning at 02:30 PM | Permalink | Comments (6)
August 13, 2003
mxBase available for Python 2.3

Marc-Andre Lemburg has announced a new version of his essential Python package, mxBase. It works under Python 2.3 now.

This package includes mxDateTime - every date/time tool you'll ever need, and then some. Superb.

Marc-Andre has also released a new version of mxODBC, a Python ODBC Interface. This is also excellent, but be aware, commercial use of this is not free.

Posted by Simon Brunning at 11:11 AM | Permalink | Comments (6)
10 Python pitfalls

Hans Nowak has written an excellent article, 10 Python pitfalls.

Points 2, 3, 7 and 8 apply to Java as well as to Python.

It seems to me that the difference between mutable and immutable objects, which is a crucial one, is not given due prominence in any of the tutorials that I've seen, either for Python or Java.

Update: According to the Java Language Specification, point 3 does not apply to Java, i.e. a = a + b is exactly the same as a += b in all cases. If I'm reading it right, that is. I haven't got time to try this out now, though.

Posted by Simon Brunning at 10:39 AM | Permalink | Comments (3)
August 12, 2003
Processing RSS in Java

Using RSS in JSP pages offers a nice overview of RSS processing in Java.

Now I just have to think of a use for it. ;-)

For RSS processing with Python, see RSS for Python.

Posted by Simon Brunning at 01:56 PM | Permalink | Comments (2)
The Standard Python Library updated

The effbot is posting a series of updates to his superb The Standard Python Library, covering modules added to the Python Standard Library since version 2.1.

Of particular interest (to me, at least): datetime and csv. I'm looking forward to his coverage of logging, sets, and especially itertools.

Posted by Simon Brunning at 12:09 PM | Permalink | Comments (0)
August 01, 2003
IT the EasyJet way

In Open Source Flying, Matthew Langham contends that the way the air travel industry has changed over the years may be a good model for the way the IT industry is changing.

In the old days, if you wanted to fly, you went to your national carrier and payed whatever they demanded, and that was that. Just as now, 99% of businesses go to one of the big vendors (Microsoft, IBM, Sun, etc.) for their software.

These days, there are a number of low cost carriers fighting over you. The national carriers are still there, offering high price, high standard, high convenience travel, but they no longer own the skies.

Will the big vendors lose out? I can't say I see any sign of it yet, but it would be nice if he were correct. ;-)

Via Daily Python-URL.

Posted by Simon Brunning at 01:46 PM | Permalink | Comments (1)
Nerd meetings and events in London

NullBlogException posted a list of Meetings and events in London.

I think I'll give one or more of these a bash. The Python booze-ups just ain't happening.

Posted by Simon Brunning at 01:05 PM | Permalink | Comments (1)
July 30, 2003
Python 2.3 is here

Python 2.3 final was released yesterday. Go get it.

I pointed out the cool new stuff when the 1st beta came out.

Posted by Simon Brunning at 10:21 AM | Permalink | Comments (0)
July 25, 2003
Russ on Python

Russ has been looking at Python. He's decided against using it, and he has written up his conclusions.

The points he raises are good ones. I've discussed Python Web Frameworks before, and this remained his major gripe. Fair enough. I agree. And Python isn't perfect - no argument there.

Where I differ from Russ is really on a matter of taste more than anything else. He says "If I need to go to an IRC channel or search through mailing lists or newsgroups to find solutions to simple problems, I get annoyed."

Well, for me, the Python community is certainly one of Python's greatest assets, with c.l.py at its heart. I've asked questions there many times, and people have always helped me. When I was a Python newbie, I'd regularly ask questions there, only to have Python Demi-gods provide answers within minutes. You simply cannot buy support like that - and you get it for nothing from the Python Community.

Russ had a quite a bit of trouble getting stuff going. I suspect that someone on c.l.py would have been able to help him out with most of it.

In the Java world, I've not found anything quite like c.l.py. Recently, the Java blogsphere has started to take shape. Just yesterday, Marc Logemann helped me out with something that I'd not been able to get working for ages. (Thanks, Marc!) But before blogging, I would have had nowhere to go.

He's right about the fact that documentation for 3rd party libraries for Python can be, uh, inconsistent in quality. (Core Pythons documentation is superb.) But that's an open source issue in general, I think, not particular to Python.

Russ suggests that Python needs a 'Corporate Angel'. That would be great, I can't deny. But I think that it's the PR that Python would benefit from more than anything else. For me, Python is usually the best language for getting the job done, but not for getting the job. It doesn't boost your CV. That's where Java and J2EE come in. ;-)

One last, FYI point. Python is growing JAR file equivalents in Python 2.3. No reason Russ should have known that, though.

Anyway, thanks, Russ, for an interesting, blinkers-off, rant free view of Python from a Java fan's perspective.

Update 28th July. See also V. Satheesh Babu's Java, Python and Russ.

Posted by Simon Brunning at 04:26 PM | Permalink | Comments (1)
Python 2.3 release candidate 2

Python 2.3 release candidate 2

Probably (hopefully!) the last release candidate.

Posted by Simon Brunning at 09:47 AM | Permalink | Comments (1)
July 23, 2003

Nice little windows utility - AR RAM Disk.

If you develop software, you probably have steps in your build process where you create a lot of temporary files. (For example, a typical Ant build process will compile a lot of Java into class files, then put them together into a jar file). Creating all these transient files would be quicker on a RAM disk, and would fragment your disk less.

If, that is, you have the RAM for it.

Via John Lipsky.

Posted by Simon Brunning at 02:03 PM | Permalink | Comments (6)
July 21, 2003
The Ideal Programmer

Bruce Eckel, The Ideal Programmer.

An interesting, if unfocused, semi-rant about the poor quality of the average coder.

Some interesting numbers: 5% of the programmers are 20 times more productive than the other 95%. The majority (probably that other 95%) of programmers don't read books on programming. Now, I'd love to take this at face value - after all, I read a lot of books on programming. But most books probably don't make people into better programmers, just better informed programmers. In fact, it's often the complete opposite. The code examples in most tech books irritate me greatly, for example - they get across the narrow technical point that they are attempting to illustrate, but apart from that, they are often good examples of how not to code.

There are, however, a very few books which can make one a better programmer, I think. Code Complete and The Pragmatic Programmer, for example, should be mandatory reading for anyone who makes a living cutting code. Other good examples might be the GoF book, or Bitter Java.

How many people in our profession really love what they do? Not many - 95% (the same 95% again?) are in it for the cash - indoor work, with no heavy lifting. There do exist, though, programmers who do not love what they do, but do nevertheless approach it in a professional manner. I know - I work with some of them. But the couldn't-care-less brigade are always present, too...

Posted by Simon Brunning at 11:42 AM | Permalink | Comments (4)
Python 2.3 release candidate 1

Python 2.3 release candidate 1 was released on Friday.

I've been running beta 2 for a while, and it's good.

There may have to be another release candidate, since 2.3 currently doesn't work on Cygwin. But the Python dev team are hoping that it's a Cygwin bug rather than a Python bug, and that release candidate 1 will be the only one.

In any case, there is a pretty hard deadline on 2.3 final - it needs to be out by the 31st if it's to make it into the next OS X release.

Update: Looks like there will be a release candidate 2.

Posted by Simon Brunning at 10:11 AM | Permalink | Comments (1)
July 17, 2003
Python Warts updated

Andrew Kuchling has updated his Python Warts page, to take recent changes to Python into account.

There are a couple of things in there that I really don't see as warts at all. Raw strings, for example, seem to me to be a a fairly elegant was of solving the escaping problem.

The explicit self. requirement is something I find helpful. It makes it obvious whether you are dealing with an instance variable or a local one. In Java, I always use the this. prefix.

The .join() string method? What can I say? I've just got so used to it now that I wouldn't have it any other way. Besides, the martellibot has shown why join() is best implemented as a string method.

What's missing? Well, as of 2.3, you still need the string module for several constants, even though (almost all) the functions are available as string methods. But I gather that by version 3.0, the string module will be deprecated. So by then, the constants will have to have been put somewhere else - probably they'll be attributes of the built-in str object.

Assuming that the str object does grow attributes, the idea could be extended. When you open a file using the built-in file() object, you need to pass it a bunch of mode flags. These you pass as strings, which I find ugly - another wart, IMHO. These could easily become attributes of file. So, instead of:

myFile = file(filename, 'rb')

, you could do:

myFile = file(filename, file.READ + file.BINARY)

Longer, yes, but easier to remember and to read, I think.

Opening files isn't the only place where you use fairly arbitrary characters like this - the struct module springs to mind, where you have 'format characters'. These should defined as constants by the module, I think.

Oh yes, one other thing. os.path.walk must die. And I see it's on its way out now - the Timbot's new os.walk generator has made it into 2.3, and a thing of beauty it is too.

Posted by Simon Brunning at 02:34 PM | Permalink | Comments (3)
July 15, 2003

Congratulations to Andy Todd on the birth of Alexander.

Posted by Simon Brunning at 05:33 PM | Permalink | Comments (1)
Visual Basic to Python

It's early days, but vb2Py (Visual Basic to Python Converter) looks an interesting project.

VB, love it or hate it, is unquestionably ubiquitous. Anything that will help any former burger flippers who have seen the light can only be a good thing.

Via Kevin Altis.

Posted by Simon Brunning at 11:21 AM | Permalink | Comments (5)
July 09, 2003
Python Web Frameworks

There are a whole bunch of Python Web Frameworks out there. Russ doesn't know what to use. Neither do I.


Posted by Simon Brunning at 03:36 PM | Permalink | Comments (15)
July 07, 2003
Python Boosts JAR File Auditor Functionality

Spotted on Java Today - Python Boosts JAR File Auditor Functionality.

Python stuff seems to be showing up more and more frequently on Java related sites these days.

Which is nice.

Posted by Simon Brunning at 01:56 PM | Permalink | Comments (4)
July 02, 2003
Dynamically extending Python classes

Mark 'Dive into Python' Pilgrim gives a nice demonstration of Python's dynamism in Dynamically extending APIs.

Posted by Simon Brunning at 11:36 AM | Permalink | Comments (0)
July 01, 2003
Text Processing in Python

Looks like David Mertz's Text Processing in Python is out. I can't see myself holding out too long on that purchase.

Try before you buy - read Text Processing with Python online.

Just one criticism - why-oh-why another one-chapter Python tutorial at the beginning? I really can't see the point. Virtually every Python book has one of these. You don't get this with, say, Java books. They assume that you know Java already.

Also interesting from the pen of David - Why list comprehensions are called list comprehensions.

Posted by Simon Brunning at 03:32 PM | Permalink | Comments (7)
Open source = higher quality

Interesting. In Closed source versus open source in a model of software bug dynamics, Damien Challet and Yann Le Du of the University of Oxford show that open source software has less defects than closed source, other circumstances being equal.

I'll have to try this on on El Presidente - "It's your fault that the software I wrote is crap. You insisted that it be closed..."

Via Azeem Azhar.

Posted by Simon Brunning at 02:50 PM | Permalink | Comments (1)
Python 2.3

Python 2.3b2

I've upgraded, and as usual with Python, It Just Works.

Cool stuff in there - see Andrew Kuchling's What's New in Python 2.3 for details.

Update: See also Alex Martelli's What's New in Python 2.3? for another overview, less exhaustive (which isn't like Alex), but which covers some of the most useful enhancements in some detail.

Posted by Simon Brunning at 10:13 AM | Permalink | Comments (6)
June 13, 2003
Sun and Zend push scripting for Java - so?

Sun & Zend push scripting for Java

Is this related to JSR 223: Scripting Pages in JavaTM Web Applications (Via Aaron Johnson)?

My question is, what does this add to what Jython already gives us? You can already use Java classes in Jython, or subclass them, use Jython classes in Java, write taglibs and servlets in Jython, you name it.

See jPublish for a nice example of what you can do.

Posted by Simon Brunning at 12:14 PM | Permalink | Comments (1)
June 12, 2003
Python Descriptors

Fore those of you who find metaclasses just too simple, check out the How-To Guide for Descriptors

I'll find the time to digest this later. Right now, I'm just saving the link.

Via the suddenly hyperactive Python Daily URL.

Posted by Simon Brunning at 03:56 PM | Permalink | Comments (2)
Tempt me

Buy me one of these, and I'll feel better - What do Python programmers like?

Via Slices of Py.

Posted by Simon Brunning at 03:54 PM | Permalink | Comments (3)
June 11, 2003
Regular Expression library

This could be handy - RegExLib.com.

Also handy if you are working with JavaScript - Test Your own JavaScript regular expresssion.

Posted by Simon Brunning at 12:53 PM | Permalink | Comments (2)
May 30, 2003
What is an object?

A post over at c.l.py steered me towards this - Building user interfaces for object-oriented systems.

It has some interesting, if perhaps somewhat controversial, things to say on the nature of object orientation.

You may have read in a book somewhere that an object is a data structure of some sort combined with a set of functions, called methods, that manipulate that data structure. Balderdash! Poppycock! First and foremost, an object is a collection of capabilities. Very true, this. The important thing about an object is what is does, not what it has. The latter is an implementation matter.

Classes are irrelevant -- they're just a convenience provided for the compiler. Also true. This was pointed out to me while looking at JavaScript recently. Its rather, uh, idiosyncratic OO model does away with 'classes' as such. Instead, you just define a construction function, and add methods to its prototype. Look, Ma, no classes. (I don't really like this approach much - it makes subclassing rather clumsy if nothing else. But it does work after a fashion.)

All data is private. Period. (This rule applies to all implementation details, not just the data.) get and set functions are evil. (They're just elaborate ways to make the data public.) I like Python's approach here. No data is really private (see The principle of least privilege for why), but you can intercept any references to this data if you want. So, you just refer to object.attribute, and it's the object's business whether that just accesses the data attribute or calls a method. No need for get and set methods here.

All objects must provide their own UI. What? Is he serious? The presentation object should always be separate from the business object! Some business objects don't need any presentation layer, and some may need several. (The persistence layer should also be separate.)

Posted by Simon Brunning at 10:43 AM | Permalink | Comments (8)
May 28, 2003
Writing good exceptions

Cameron Laird on how to use exceptions - Writing good exceptions. Not how to use them in terms of syntax, but rather in terms of semantics. The examples are in Python, but the advice is applicable to any language supporting exceptions.

We have a lot of classes in one of my current Java projects (written by a cow orker) in which every method has a catch-all exception handler which logs any unexpected error, and then tries to keep on going. Me, I prefer the RuntimeException approach.

Posted by Simon Brunning at 01:45 PM | Permalink | Comments (2)
May 22, 2003
'Point-and-click' programming

Code diagrams enable 'point-and-click' programming. Yeah, right.

Anthony has been thinking about this sort of thing (see his Visual Programming posts), but I remain profoundly sceptical.

Posted by Simon Brunning at 10:43 AM | Permalink | Comments (8)
May 16, 2003
How to write a main() function in Python

Python main() functions, from the BDFL himself.

Most of my scripts have a main() function, looking pretty much like Guido's first example.

I particulary like Guido's main(argv=None) suggestion - I'll be using this in future.

Posted by Simon Brunning at 01:36 PM | Permalink | Comments (2)
May 09, 2003
Another day, another language...

I'm off to Amsterdam next week to support one of our clients, who have a lot of JavaScript. Which I've never used.

Anyone know a good tutorial? ;-)

I've just got a funky new laptop, so I should be online OK. We'll see.

Posted by Simon Brunning at 04:48 PM | Permalink | Comments (13)
May 08, 2003
Strong Typing vs. Strong Testing

Bruce Eckel (of Thinking in Java fame) writes about why static typing is pretty much redundant if you are unit testing properly - Strong Typing vs. Strong Testing.

It got to be said, though, that statically typed languages have one big advantage over dynamically typed ones - their GUIs can provide much better auto-completion. This was mentioned on c.l.py recently, but I'm not sure that I agree with Martin's view that this can be fixed. Imagine that you'd entered this:

def myFunction(anArgument):

At this point, which methods can your IDE suggest? Pretty much none at all, I'd say.

Not, I hasten to add, that I think that this advantage of static typing overrides the advantages that dynamic typing can give you - see Bruce's post for that side of the story, expressed rather better that I ever could hope to do.

Posted by Simon Brunning at 01:13 PM | Permalink | Comments (3)
May 02, 2003
Asynchronous generators

Garth Kidd's Spawned Generators - what a good idea! All the advantages of generators and threads in one easy-to-use class.

Two great tastes that taste great together!

Posted by Simon Brunning at 01:44 PM | Permalink | Comments (2)
May 01, 2003
Standard libraries - Java vs. Python

"The main thing which would keep it there [Java] for me would be the APIs (both Sun's APIs and open source APIs)."

Anthony has mentioned Java's library as a reason for choosing Java before. But coming from the Python side, I can't see what Sun's Java library has that the Python Standard Library doesn't.

What am I missing?

Posted by Simon Brunning at 01:48 PM | Permalink | Comments (6)
April 28, 2003
Floating Point Arithmetic: Issues and Limitations

Floating Point Arithmetic: Issues and Limitations

About once a week or so, someone will post to c.l.py, reporting as a bug the fact that 0.1 is showing up as 0.10000000000000001. This isn't a bug, it's just the way that floating point works. There is nothing peculiar to Python about this behaviour, either - any floating point implementation will show some variation on this behaviour. Java, RPG, C#, VB, you name it.

In a (so far unsuccessful) attempt to have this 'bug' reported less frequently, Tim Peters added this appendix to the Python Tutorial. It's worth a read whatever you code in.

In general, then, business oriented software should avoid using floating point, and should certainly never use it to store currency values. For that you shoud use Decimal or java.math.BigDecimal, or the like.

Posted by Simon Brunning at 05:49 PM | Permalink | Comments (2)
Are Programmers People?

Are Programmers People? And If So, What to Do About It?

Ken Arnold on human factors in programming language design.

Naturally, in a discussion about why programming languages are crap, Python is bound to be mentioned as a counter-example!

Via Ned Batchelder.

Posted by Simon Brunning at 03:42 PM | Permalink | Comments (1)
Python 2.3

Python 2.3 Beta 1 is out.

A.M. Kuchling has put together his usual What's New in Python 2.3 document.

I particularly like the inclusion of the logging and csv modules in the standard library. I already use both of these, so I'm glad they are now the standard.

Also good - the string method changes. One of these was my feature request - the optional arguments on the strip method and its siblings. This was backported to 2.2.2 - it was added to the string method, but not to the string module function, though the documentation incorrectly said that it was added to both. Given the frequency with which this comes up on c.l.py, it seems that this is a much-used feature already!

I'm also keen on extended slices, importing from zip archives (i.e. JAR files for Python), and the if 'fred' in 'bill and fred' thing.

Generators are now enabled by default - I've been using these a lot.

Posted by Simon Brunning at 10:37 AM | Permalink | Comments (3)
April 15, 2003
Python - an agile programming language?

Python is an Agile Programming Language

I like this - I've always felt that the term 'scripting' language is a little, well, demeaning. 'Agile' seems to sum it up rather well.

Oh, and it seems we've converted Anthony!

Posted by Simon Brunning at 04:48 PM | Permalink | Comments (1)
comp.lang.python made flesh

Andrew Koenig wasn't able to make it to the UK Python Conference this year - his company has a travel ban due to the threat of terrorism. Anyone would think that America was unpopular, or something.

Anyway, Andy Robinson put together a short-notice replacement session - a panel discussion entitled "P2EE - is Python ready for the enterprise?" On the panel were Andy, Guido, Jacob Hallén, Laura Creighton and Marc-Andre Lemburg.

This discussion was comp.lang.python made flesh - good natured, rambling, frequently going wildly off topic, the occasional total non sequiter, that sort of thing.

One of the threads of discussion was about Python advocacy. Andy and the other Python-in-a-tie people are really big on this. To them, Python is strategic, it's a 'platform'. They want it to have 'market share', they want CEOs to have heard of it, and they want them to have heard good things about it. Me, I can't get excited about this. I sympathise with their position, but Python, to me, is tactical - it's a tool. It's the best goddamn tool I've ever had, and it's a beautiful and elegant tool, but it's just a tool nevertheless. I don't care if CEOs have heard of it. So long as the user base stays large enough to keep the 'platform' viable, that's all I really care about. Which is probably lucky - Python in unlikely to ever have a marketing budget to speak of, so Python will probably only ever grow organically.

There was then a quick discussion of the difficulties of application deployment, and distutils' unhelpfulness in this regard. I didn't really follow this with my full attention - as a way of installing libraries, either pure Python or with C extensions, distutils just works for me. As for application deployment, well, that is just plain hard in general. My needs are very simple, and I've been happy using py2exe and Inno, though I'm thinking of switching to NSIS. But if you want cross-platform scriptable installers, then I'm not sure what exists. Distutils, though, was designed to simplify module and package distribution rather than application deployment, or so it seems to me. Marc-Andre suggested that extending it to support application deployment is trivial enough that everyone could use it, but I think that he was forgetting that most of us don't have a brain as large as his.

We then talked a little about web application frameworks, and the complete and utter lack of a de facto standard in this area. This has been pretty much reiterated on c.l.py now. I myself would be interested in using a Webware/Cheetah combination, but I'm rather stuck in Java-land, where J2EE/JSPs/Taglibs rule the roost. I'm interested in Struts - pure JSPs are an invitation to the Magic JSP anti-pattern discussed in Bitter Java. But I'm also very interested in Anthony Eden's JPublish project. It uses Velocity for its templating, which is *much* nicer than JSPs, and for the action scripting and business logic, you can use Java or any of the BSF languages, which gives you access to Jython. I'll blog more about this later, because this is a lovely approach.

Another issue discussed - documentation. Andy Robinson felt that Python should provide better tools for the production of documentation. Python's docstring approach is a good one for 'embedded' documentation, and for the generation of API reference documentation. reStructuredText support will just be the icing on the cake. As for the rest of the documentation, well, as I pointed out, this is not a technological problem, but a sociological one - people have always failed to write documentation, and they probably always will. Good tools exist, but people would rather do other things.

On the off chance that anyone is interested, Duncan Grisby has put up some photos taken at the conference, many of the ones from Wednesday taken at this session. It's interesting to put faces to names...

Posted by Simon Brunning at 04:05 PM | Permalink | Comments (0)
April 11, 2003
Python and Apache

Python and Apache is a useful little guide to configuring Apache to run Python CGI scripts.

The guy obviously didn't really get on with Python - he calls code blocks delimitation by indentation 'tiresome' - it was the first thing that attracted me to Python! But, hey, it's his loss.

Posted by Simon Brunning at 08:58 AM | Permalink | Comments (0)
April 07, 2003
Python and Patterns

Duncan Booth gave a presentation at Python UK 2003 on Patterns in Python.

Anyone not knowing what a software pattern is, and who is the slightest bit interested, should pay a visit to the Portland Pattern Repository.

It was a superb talk, mostly because of the audience participation, and Duncan's handling of that participation.

It was, in some ways, the audience from Hell. Sitting on the back row were Guido and Alex Martelli (AKA the martellibot). Elsewhere sat Anthony Eden and some other Java pattern-head whose name I didn't get. All of these people threw all manner of nasty questions, objections and counter-examples at Duncan, who reminded me of nothing so much as a first class batsman in dealing with them all.

He gave a few good examples: Singleton, Borg, Observer/Observed (or possibly Publish/Subscribe - one of the little debates kicked off over that one). He also presented on the Flyweight pattern. Well, everyone else seemed to understand him...

He also covered what he called 'Little patterns in Python', things like DSU (of which he gave a nice little example, BTW), and the use of list comprehensions. The question here was as to whether these things qualify as patterns. The general consensus was that these are actually idioms rather than patterns. Someone referred to them as 'textures', though, and I rather liked that - these sorts of things do seem to supply the texture to Python source code.

Posted by Simon Brunning at 01:26 PM | Permalink | Comments (0)
April 04, 2003
Python UK 2003 - I'm back!

This will be a brief one - I've only got a 1/2 day today, and I've got a ton of work to catch up on. I've got notes enough for a couple of week's worth of postings out of this, so expect details later.

The conference was superb. I'm still buzzing. I had a fabulous time. I had a chance to talk to some really cool people - Guido, Alex Martelli, Mark Shuttleworth (yes, that Mark Shuttleworth), Anthony Eden, Andy Todd, Andy Robinson, Marc-Andre Lemburg, Duncan Grisby, Paul Brian, Duncan Booth, Tim Couper and his bright-young-thing daughter, Fiona. (Pretty as well as bright, but married. :-( )

I'm still not sure whether it was cooler to meet Guido or an astronaut, to be honest. Some of these people were seriously bright. Nevertheless, I feel I was able to contribute to some of the discussions without making too much of an arse of myself.

It was nice to meet up with some people in the same boat as me, too - I'm the office eccentric, in a way. Every time a problem comes up, and I pipe up "You could do that in...", the groan goes round the office "Yes, you could do it in Python, we know..." For whatever reason, the fact that I am right doesn't seem to stop people thinking that I'm a little odd. Well, for the last couple of days I've been with the other office eccentrics who are usually right, too.

Much more later...

Posted by Simon Brunning at 10:48 AM | Permalink | Comments (2)
April 01, 2003
Python UK Conference 2003

I'm off to the Python UK Conference 2003 after work today.

Say 'Hi' if you spot me. I'll be on the desk some of the time.

Loads of good stuff to see. Most important to me professionally will be Anthony Eden's Scripting Java Applications with Jython session. Guido's keynote will be unmissable too, naturally.

Other than that, well, I'll probably want to see the big names' sessions - Marc-André Lemburg and Alex Martelli. But then, I might find Boyd Roberts's Object Storage in Python session more useful tan Alex's, since I don't know C or C++. Andy Todd's PythonCard session looks good, too.

Posted by Simon Brunning at 01:53 PM | Permalink | Comments (2)
March 31, 2003
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 by Simon Brunning at 01:43 PM | Permalink | Comments (9)
March 21, 2003
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)

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")

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)
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)
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)
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)
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 by Simon Brunning at 04:59 PM | Permalink | Comments (4)
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 by Simon Brunning at 12:49 PM | Permalink | Comments (1)
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):
if wantedClass and not windowClass == wantedClass:
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 = []
win32gui.EnumChildWindows(currentHwnd, windowEnumerationHandler, childWindows)
except win32gui.error, exception:
# This seems to mean that the control does *cannot* have child windows
for childHwnd, windowText, windowClass in childWindows:
# print "Found ", childHwnd, windowText, windowClass
if selectionFunction(childHwnd, windowText, windowClass):
return childHwnd
descendentMatchingHwnd = searchChildWindows(childHwnd)
if descendentMatchingHwnd:
return descendentMatchingHwnd

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 by Simon Brunning at 05:03 PM | Permalink | Comments (8)
Python UK Conference 2003

The Python UK Conference 2003. See you there!

Posted by Simon Brunning at 04:20 PM | Permalink | Comments (4)
March 19, 2003
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 by Simon Brunning at 01:50 PM | Permalink | Comments (17)
March 17, 2003
Struts Action Scripting

Struts Action Scripting

Write Struts actions in your language of choice.

Via Daily Python-URL.

Posted by Simon Brunning at 01:33 PM | Permalink | Comments (0)
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 by Simon Brunning at 05:03 PM | Permalink | Comments (0)
February 20, 2003
PEP 308 - run away, run away!

Over the last couple of weeks there has been the Mother and Father of all debates (degenerating into ranting, trolling, and personal abuse at times) on c.l.py regarding the possible introduction of a ternary operator to Python. Guido is happy to add one, or not, but he wants the community's consensus of opinion for once and for all - should there be a ternary operator in Python, and if so, what should its syntax be?

I've not really used anything like the ternary operator. Java has one, but I don't use it, and my cow orkers don't know what it is, so they don't either. So, I'd be happier doing without it.

But if we must have one, then I'd prefer one of the more Pythonic syntaxes. Let's use words, not punctuation! Of all of them, I dislike:

result = (if condition then expression1 else expression2)

least. It has a slightly list comprehension like feel to it, and I think that its meaning would be fairly obvious even to someone who had never even heard of the construct, which is a sign of good syntax, I think. But I gather that there is some problem parsing this. Ho hum...

Update: Turns out that Mark does know what the ternary operator is, and uses it, but didn't know it by that name. Sigh.

Update: Guido has spoken. There will be no ternary operator in Python.

Seven Deadly Sins of Introductory Programming Language Design

Seven Deadly Sins of Introductory Programming Language Design (PDF)

An interesting read this, I thought. Most I agree with, some I don't.

It occurred to me that a few of the issues raised might point towards ways of improving Python as an introductory language. (I'm not talking about Java here 'cos I consider Java to be totally inappropriate for beginners.)

  • A single numeric type. Python is already moving in this direction. Slowly. Kinda-sorta. Python's two integer types (integers and long integers) are already pretty indistinguishable from a programmers point of view. The paper suggests that the single type be a rational. The addition of a rational type has been discussed on python-dev, but I don't think that there are any immediate plans to go ahead. But even if there, I just can't see Python abandoning integers and floats. A single type would make life rather easier for beginners, but Python is a real world tool. Anything which would help the beginner at the expense of crippling the experienced just wouldn't fit.

  • A single non-terminating loop construct. I do like the idea of something like a loop statement. The standard idiom for this in Python is while 1:, which I can see a beginner mistaking for something happening once. Perhaps better these days would be while True:, but again, I can see a beginner thinking - while what is true?

  • Zero offsetting. I can certainly see the fact that list[1] refers to the 2nd item of a list is likely to be a problem for a newcomer. But what to do about it? Apart from the practical impossibility of changing something like this in an existing language, (can you imagine the furore on c.l.py if this was suggested!), it's also the case that in practise this is a more convenient notation. If beginners started off with 1 offsetting, and had to move to zero offsetting later, well, that's even harder. And I speak from experience here, coming from RPG.

On reflection, it seems that none of these would have any chance of making it into Python. Only the non-terminating loop construct would be reasonably backward compatible, and while while True: is ugly, it works. Ah well...

One thing I didn't agree with, (as you might expect from a Python fan) is the paper's assertion that using indentation to specify scope is an example of 'detrimental cleverness'. It refers to 'useful redundancy' between delimiters and indentation. I don't see it as useful redundancy, I see it as potentially confusing. If the two don't match, which is correct (in terms of the programmers intention)? Redundancy is almost always A Bad Thing in code, and having both delimiters and indentation is no exception.

What I don't see, though, is any indication that all this is anything more than personal opinion. Informed opinion, yes, but opinion nevertheless. Real useability studies would be good.

Via iamcal.

Posted by Simon Brunning at 01:29 PM | Permalink | Comments (1)
February 14, 2003
The Python 2.3 Method Resolution Order

The Python 2.3 Method Resolution Order. Everything you wanted to know about Python's implementation of multiple inheritance, but were afraid to ask.

Posted by Simon Brunning at 05:55 PM | Permalink | Comments (1)
February 07, 2003
Typing: Safety causes Bugs

Alan Green: Typing: Safety causes Bugs.

Hmmm. Well, I've been using a mixture of Python and Java for some time now, so here is my personal conjecture:

I don't think that the extra typing required by 'safety' features actually cause bugs - they just don't stop them. Or rather, the ones that they stop are balanced by the additional ones that they introduce. For every time Java saves me from using a String as an int, I'll get a runtime error casting something around in order to get to a method that I know damn well it has, even if the bloody compiler doesn't.

In Python, if an object has a method, I can just call it. Thank you. If this isn't going to work, I'll find out while testing.

Ah yes, testing. That's where you stop bugs. Static typing might have pointed you at a few bugs a little earlier than your testing would have, but your testing would have picked them up soon enough. And if you don't test properly, your stuff is going to be buggy anyway.

The so called 'safety' features are only going to catch a subset of problems, and you would have found these problems eventually anyway. So if they add too much work at the coding stage, they are a net time loss.

Cameron Laird and Kathryn Soraiz's Syntax Checking the Scripting Way is interesting on this. And I'm reminded of a quotation:

The static people talk about rigorously enforced interfaces, correctness proofs, contracts, etc. The dynamic people talk about rigorously enforced testing and say that types only catch a small portion of possible errors. The static people retort that they don't trust tests to cover everything or not have bugs and why write tests for stuff the compiler should test for you, so you shouldn't rely on only tests, and besides static types don't catch a small portion, but a large portion of errors. The dynamic people say no program or test is perfect and static typing is not worth the cost in language complexity and design difficulty for the gain in eliminating a few tests that would have been easy to write anyway, since static types catch a small portion of errors, not a large portion. The static people say static types don't add that much language complexity, and it's not design "difficulty" but an essential part of the process, and they catch a large portion, not a small portion. The dynamic people say they add enormous complexity, and they catch a small portion, and point out that the static people have bad breath. The static people assert that the dynamic people must be too stupid to cope with a real language and rigorous requirements, and are ugly besides.

This is when both sides start throwing rocks.

Quinn Dunkan, 13 Jul 2001

Posted by Simon Brunning at 03:14 PM | Permalink | Comments (0)
Shipping the prototype

Shipping the prototype - Let's promote scripting languages to the status they deserve

My point is that languages like Python, but also Perl, Ruby, and JavaScript/JScript/ActionScript/EcmaScript, are strategic in ways that we don't yet fully acknowledge.

Via The Daily Python URL.

Posted by Simon Brunning at 10:58 AM | Permalink | Comments (0)
February 06, 2003
Interviews with Guido van Rossum

Links to artima.com's A Conversation with Guido van Rossum interview have been floating all over the blogsphere, but I haven't seen any links to this Guido van Rossum interview.

The interview is part of the pre-publicity for the Python UK Conference 2003.

Posted by Simon Brunning at 05:41 PM | Permalink | Comments (1)
February 05, 2003
Python Programmer Weblogs

Python Programmer Weblogs is an online aggregator, feeding off thirty or so Python oriented weblogs, including mine.

Might this be the beginnings of a Python version of java.blogs? The software that it runs on, Spycyroll, now has a SourceForge project.

Posted by Simon Brunning at 12:22 PM | Permalink | Comments (1)
Dave Thomas has a blog

Dave Thomas (co-author of The Pragmatic Programmer) has a new weblog - PragDave. One for the aggregator!

If you've not read The Pragmatic Programmer, you should. Well, if you are a programmer, that is. Not a lot in it for accountants, for example. (Or maybe there is - 'No broken windows', anybody? Still, there is certainly a lot of techie stuff in there.)

Via Ned Batchelder.

Posted by Simon Brunning at 12:07 PM | Permalink | Comments (1)
February 04, 2003
JSR-666: Programmability Enhancements

JSR-666: Programmability Enhancements.

Is this a conscious reworking of Python's PEP 666: Reject Foolish Indentation?

Via Charles Miller.

Posted by Simon Brunning at 01:47 PM | Permalink | Comments (1)
VSS for Eclipse - updated

Marcus Nylander's VSS Plugin for Eclipse has been upgraded to to COM automation - it's much faster now.

Funnily enough, I've had to do some VSS automation myself, in Python. VSS's object model is a bit nasty, but it's easy enough to write an OO wrapper while clutching the documentation. Then you can use the wrapper, and forget all about the ugly stuff underneath.

I'll probably clean this VSS stuff up and post it at some point.

Posted by Simon Brunning at 10:03 AM | Permalink | Comments (4)
The effbot is no longer a Python developer

I'm no longer a python developer

A real shame, this. He's been a real contributer to Python. Possible his most high profile contribution is Python's new (at 2.0) unicode regular expression module, which I use every day. (Well, OK, most days.) But this is far from being his only contribution.

I don't see him much on c.l.py any more, either, which is a shame. He's helped me out in the past. I'm not surprised, though - the volume of postings on c.l.py is huge these days.

Oh, and if you are a Python developer and don't yet have The Python Standard Library, I recommend it. When using a new module for the first time, I find a simple example or two a much more effective quick start than the docs, good though they are, and Python Standard Library gives you exactly this.

Posted by Simon Brunning at 09:25 AM | Permalink | Comments (4)
January 27, 2003

TN5250j is a 5250 terminal emulator for the AS/400 written in Java, which allows Python scripting!

(Well, Jython scripting, to be precise.)

This is going to be so useful...

Via Daily Python-URL

Posted by Simon Brunning at 01:39 PM | Permalink | Comments (2)
Programming at Python Speed

Programming at Python Speed

Posted by Simon Brunning at 01:17 PM | Permalink | Comments (0)
Perl 6 and Python 3000

AMK's Perl 6 and Python 3000 is an interesting read.

The total Python re-write, Python 3000, definitely isn't going to happen. Joel says that you shouldn't re-write working software at all, but Python is being re-written. It's just that it's being re-written one piece at a time.

I particularly like Tim's line - The "ain't broke, don't fix" philosophy is a good guide here, provided you've got a very low threshold for insisting "it's broke" <0.4 wink>.

Posted by Simon Brunning at 12:15 PM | Permalink | Comments (0)
January 24, 2003
Anthony Eden on Scripting Java Applications with Jython

Anthony Eden is giving a presentation on Scripting Java Applications with Jython at the upcoming Python UK Conference 2003. I, for one, am really looking forward to this.

Other people that I'm looking forward to: Marc-André Lemburg, Alex Martelli and Andy Todd.

And, of course, Guido himself. We are not worthy.

Update: I forgot to mention - Anthony has blogged about this before.

Posted by Simon Brunning at 01:25 PM | Permalink | Comments (0)
January 23, 2003
path module for Python

Jason Orendorff's path module is an object oriented wrapper for Python's os.path stuff. Very nice!

I already have a replacement for the workable, but dog-ugly, os.path.walk, but this goes much further.

Via Daily Python-URL.

Posted by Simon Brunning at 04:54 PM | Permalink | Comments (0)
January 21, 2003
Python blogs

A list of Python programmer's weblogs. I've added those that I read. Any more?

No Python equivalent of java.blogs around. There may not be enough Python around to make it worthwhile making one. Or are there?

Via the effbot.

Posted by Simon Brunning at 02:20 PM | Permalink | Comments (3)
January 17, 2003
Boa Constructor alpha 0.2 out

Boa Constructor alpha 0.2 is now available.

Try this with the new version of wxPython.

Version 0.1 didn't really work. I gather that you could get a working version via CVS from Sourceforge, but that felt a little too much like hard work. Hopefully, version 0.2 should work straight out of the box.

Update: Doesn't work for me - bug reported...

Posted by Simon Brunning at 09:49 AM | Permalink | Comments (0)
January 13, 2003
Erroneously Empty Code Paths

Ned Batchelder on Erroneously Empty Code Paths. Wise words.

Posted by Simon Brunning at 12:59 PM | Permalink | Comments (0)
January 07, 2003
Running Python scripts from the Windows command line

Add .py and .pyw to PATHEXT on Windows

Posted by Simon Brunning at 12:56 PM | Permalink | Comments (0)
Python 2.3a1

Python 2.3a1 is out!

Posted by Simon Brunning at 09:20 AM | Permalink | Comments (1)
December 19, 2002
Encapsulation gotchas

The mutable return value gotcha mentioned in Avoid these simple Java encapsulation gotchas certainly isn't specific to Java - the same would apply to Python, and (I think) to C#.

Now, as a Python-head, I'm not big on enforcing encapsulation - see The principle of least privilege. But you certainly don't want to break encapsulation by accident, and mutable return values are an accident waiting to happen.

Posted by Simon Brunning at 04:09 PM | Permalink | Comments (0)
December 13, 2002
Python templating

I've got a fairly simple function to put together for my father - I want to give him a simple online form enabling him to maintain his gig list. The host supports CGI only, so obviously I'm going to use Python.

Equally obviously, I'm going to want a template engine. The problem here that there are just so many of the bloody things!

I had a quick look at YAPTU, but I just didn't like it - you shouldn't need all this re compiling business.

Cheetah looks nice, though - rather Velocity-like. This paper (found via ZOpen-X) introduces Cheetah. If you've not come across Velocity - have a look at Start up the Velocity Template Engine.

Posted by Simon Brunning at 03:30 PM | Permalink | Comments (3)
Python introspection

Interesting new Guide to Python introspection by Patrick K. O'Brien over at developerWorks.

Also worth a look if you are new to Python - The Power Of Introspection, chapter two of Dive Into Python, Mark Pilgrim's excellent Python tutorial.

Posted by Simon Brunning at 03:12 PM | Permalink | Comments (0)
Windows screensaver randomiser

A little toy that I put together for myself - a Python script to pick and apply a random screensaver on a Windows box. Do with it what you will. Get it here - RandomizeScreenSaver.zip.

I could turn this into an exe, if there was any interest.

Posted by Simon Brunning at 10:44 AM | Permalink | Comments (1)
December 10, 2002
EasyGui 0.5

EasyGUI is a module for very simple, very easy GUI programming in Python.

I'm keeping an eye on this.

Posted by Simon Brunning at 02:19 PM | Permalink | Comments (3)
December 09, 2002

adodbapi is a DB-API 2.0 compliant module for connecting to ADO databases.

Posted by Simon Brunning at 01:18 PM | Permalink | Comments (1)
November 08, 2002

The deeper I look into persistence, the more confused I get.

In the old days, it wasn't too hard. We wrote our SQL, muttered a swift prayer to Codd, and away we went. In the even older days, we used native access methods, but there was still an RDBMS underneath.

In fact, the first systems that I worked on used flatfile, tapes, and DB1, all under PL/I. But my memories of that time are lost in the mists of Guinness.

But now, it's all very different. It isn't just data that we want to persist, it's objects. And from what I can tell, there isn't a generally accepted right solution to this.

One approach is to map objects onto tables in an RDBMS. Castor JDO can do this, as do Entity EJBs. In fact, there are many such frameworks. The advantages of this are obvious, especially to those of us who are comfortable with SQL. (My friend Steve used to whistle The Ride Of The Valkyrie when I was doing SQL updates.)

But it isn't very OO, is it? Not very twenty-first century.

Then there are OODBMSs. Java has Ozone, about which I know nothing, and Python has ZODB, which I've used, and is pretty funky.

Somehow, though, I can't see OODBMS replacing RDBMSs. Perhaps it's just that I've not got used to them. But when I first learned about RDBMSs, a light went off in my head - I knew that they were just right. I get no such flash of light from OODBMSs. But then, what do I know?

I suppose that there is always pickle. For Python, at least...

Update 11th November: A couple of approaches I neglected to mention. You can persist to XML. Castor does this, in addition to being able to persist to an RDBMS.

Then there is the Prevayler/PyPerSyst approach - keep everything in memory. Which is OK for small data sets, I suppose...

Posted by Simon Brunning at 01:44 PM | Permalink | Comments (5)
November 04, 2002
What is Python?

The Python programming language page at the Wikipedia is the best short description of Python that I've yet seen.

Via SumErgoCogito.

Posted by Simon Brunning at 01:26 PM | Permalink | Comments (1)
November 01, 2002
File renaming - Java vs. Python.

See the Python (imperative) version, and the Java version.

Now, this is totally unfair to Java - this is exactly the sort of job that you shouldn't use it for. What it does demonstrate is the importance if picking the right tool for the job.

As to the functional version of the Python script, well, it looks ghastly to me. But that's probably more to do with the fact that I'm not used to fuctional programming than anything else - I'm sure that Alex's code is fine, and that a functional style is appropriate to the task. But if you haven't grokked functional programming yet, it just looks wrong.

Posted by Simon Brunning at 01:14 PM | Permalink | Comments (0)
October 30, 2002
Class reloader

Michael Hudson's metaclass based Autoreloader. Don't try to understand this - your brain may explode.

Via Python owns us.

Update 4th November: It's a Cookbook entry now, updated and with discussion.

Posted by Simon Brunning at 02:59 PM | Permalink | Comments (1)
October 21, 2002

Software idea may be just crazy enough to work reports on Mitch Kapor's Chandler, a cross platform open-source PIM which might just be able to go toe-to-toe with Outlook.

Mitch Kapor designed Lotus Agenda about a million years ago.

Sound's like it's written (at least partly) in Python, too. Now that is cool!

Via Techdirt.

Update: Yup, it's in Python - see the technology page. Could this be Python's killer app at last?

Posted by Simon Brunning at 12:53 PM | Permalink | Comments (0)
October 15, 2002
Python 2.2.2

Python 2.2.2 is out.

If you are using Python 2.2, upgrading is a no-brainier, since 2.2.2 is 100% backward compatible.

Posted by Simon Brunning at 12:37 PM | Permalink | Comments (1)
October 07, 2002
Scripting Java Applications

Anthony Eden has some interesting things to say on the subject of scripting Java applications.

Naturally, there are loads of options available for scripting Java apps, and choosing the right one can be difficult. Unless you are a Python bigot, like me, in which case the answer is obvious. ;-)

The Bean Scripting Framework (BSF) looks fascinating, though. BSF is a scripting framework which allows you to use any one of a number of languages to script your Java app, of which Jython is only one.

We are hoping to get Anthony over to talk at Python 2003 on scripting Java applications with Jython.

JPublish looks interesting, too.

Posted by Simon Brunning at 02:01 PM | Permalink | Comments (1)

I have mentioned Prevayler before. Now Patrick K. O'Brien is building a Python version - PyPerSyst.

I remain a little dubious about the approach used by Prevayler (and PyPerSyst), but I'll be very interested to see the results.

Posted by Simon Brunning at 12:51 PM | Permalink | Comments (4)
September 27, 2002

FixedPoint.py now has its own SourceForge project!

A whole project for one module might seem like a bit much, but it's such an essential module that I think it's a good idea.

There has been some discussion in c.l.py about whether you can use floating point for financial database work. Having 'grow up' with fixed point for this sort of thing, it's a no-brainer so far as I am concerned.

Posted by Simon Brunning at 02:59 PM | Permalink | Comments (1)

PdfSearch is a full-text PDF file indexer and searcher.

It incorporates Dsave Mertz's indexer.py.

Posted by Simon Brunning at 02:53 PM | Permalink | Comments (0)
The EffNews Project

The EffNews Project: Building an RSS Newsreader is now complete.

Everything you need to know to build a simple RSS aggregater.

It would be good to incoporate Mark's ultra-liberal RSS parser into this.

Posted by Simon Brunning at 02:50 PM | Permalink | Comments (0)

Kaa is a client based webblogging tool, in pure Python. Looks cool.

I think that I'll stick with Movable Type for the moment, though. It's server based, which I like, though it does add a couple of hurdles in terms of hosting & installation.

I have tried to donate to Movable Type, but PayPal sign-up doesn't work for me - it rejects my password, no matter what I enter. What can I do? I certainly can't be bothered to ring PayPal's helpline! I'd like to donate, but if it's that much hassle, I can't really be bothered.

Via Python Daily URL.

Posted by Simon Brunning at 01:18 PM | Permalink | Comments (0)
September 23, 2002
News Aggregator

Vattekkat's News Aggregator is pretty groovy.

I'll steal it, when I have the time.

Currently, I'm using feedreader, but I'm not that fond of it. Nothing wrong with it, as such - I just don't feel affection for it.

In addition to the changes that Vattekkat plans to make, it would be nice to externalize the list of sites to read, and to provide a mechanism for maintaining the list. Hey, this is open source - he has to leave something for the rest of us to do!

Posted by Simon Brunning at 02:05 PM | Permalink | Comments (1)
MAL's packages

Marc-André's been hard at work - new versions of the essential mxBase (including mxDateTime) and mxCommercial (i.e. mxODBC) have been released.

Posted by Simon Brunning at 01:25 PM | Permalink | Comments (1)
September 20, 2002
XML-RPC for Python

The Python Web services developer: XML-RPC for Python

Examples, with narrative, of XML-RPC clients and servers. Nice and simple - it seems like XML-RPC and Python are good partners!

Via Babu.

Posted by Simon Brunning at 01:43 PM | Permalink | Comments (1)

A new, Unicode friendly release of wxPython is out.

wxPython is the force behind Boa Constructor and PythonCard, and seems to be the most popular GUI toolkit for Python at the moment. It might even achieve critical mass some day.

Don't know wxPython? Documentation for beginners used to be scarce, but it's coming on stream now - see IBM's tutorial, and the wxPython site's own tutorial.

Posted by Simon Brunning at 01:37 PM | Permalink | Comments (1)
Text Processing in Python

The first four chapters of David Mertz's Text Processing in Python are online.

Fascinating stuff - I shall certainly be picking this up when it comes out - whenever that might be.

Only today, I was asked for a good RE tutorial, and I was able to recommend chapter 3.

I'm working through Mastering Regular Expressions, 2nd Ed at the moment. It's making my head hurt, but I'm learning a lot.

Posted by Simon Brunning at 01:03 PM | Permalink | Comments (1)
September 18, 2002
The "What Sucks" Index

The "What Sucks" Index - PHP comes out well, with Python coming in second. VB sucks big-time, C++ sucks bigger-time, and Perl and Java suck a bit.

All very scientific, I'm sure. ;-)

Via c.l.py.

Posted by Simon Brunning at 04:57 PM | Permalink | Comments (0)
The End of Inheritance

The End of Inheritance: Automatic Run-time Interface Building for Aggregated Objects is a fascinating new recipe on the Python Cookbook.

Knowing both Python and Java has made me think about the relationship between types, interfaces, inheritance and classes a lot more than knowing just one would have done, I think. It certainly seems to me that the central concept is the interface - what roles can the object take. This is quite a separate thing from inheritance - that's about behavior, what an object actually is.

A good example here is the Python concept of a 'file'. Any object which follows the file 'protocol' (or the required subset of that protocol which is actually used) can be used anywhere that a real file object can. You could do this in Java quite easily, by implementing 'file' using an interface, but people usually seem to use inheritance instead.

This recipe allows you to build a class composed of other objects (with a 'has-a' relationship), but to automatically implement the behaviors of the contained objects.

You can do something similar with Java's Dynamic Proxy Class API, as as Java 1.3.

Via the Python Daily URL.

Posted by Simon Brunning at 02:07 PM | Permalink | Comments (0)
September 17, 2002
Python and ADO

ADO is Micro$oft's strategic database interface.

It isn't going away, and if you are a Windows victim user, it's a good way of getting at data. There are two ways to get at it using Python - either directly via COM, or via OPAL's Python DB-API 2.0 driver. The first way is more flexible, the second is code compatible with other DB-API 2.0 drivers. Take your pick!

Posted by Simon Brunning at 02:05 PM | Permalink | Comments (0)

Psyco is a Python compiler. Looks ike black magic to me - large speed improvements no work required!

Feedback is overwhelmingly positive.

If I had any performance issues with any of my Python stuff, I'd try this like a shot. But I don't.

Posted by Simon Brunning at 01:33 PM | Permalink | Comments (0)
September 16, 2002
Python UK 2003

It's official - I'm on the committee.

As I have said before, I don't tend to like committees, but it's a nice bunch of people that I'll be working with, so it might even end up being fun!

Posted by Simon Brunning at 12:30 PM | Permalink | Comments (0)
September 13, 2002
Simple JSP Custom Tag in Jython

One recipe which didn't make it into the Python Cookbook is Simple JSP Custom Tag in Jython.

How to Create Custom JSP Tags is a good intro to custom tags. Nicer in Jython, though!

Another good Jython for J2EE recipe, A simple Jython servlet did make the cut.

Posted by Simon Brunning at 03:32 PM | Permalink | Comments (0)

AutoIt. AutoIt is a simple tool that can simulate key presses, mouse movements and window commands (maximize, minimize, wait for, etc.) in order to automate any windows based task (or even windowed DOS tasks).

What is cool about this is that it's available as an ActiveX control, and is therefore Python scriptable using win32com.

Posted by Simon Brunning at 01:55 PM | Permalink | Comments (1)
September 12, 2002
Python and MQSeries

Python MQI Interface.

MQSeries is pertty big in the iSeries world, so I'll hang onto this link for future reference.

Posted by Simon Brunning at 05:44 PM | Permalink | Comments (3)
Lightweight services for Python

IBM Lightweight Services. IBM Lightweight Services (LWS) is a J2EE (JavaTM 2 Platform, Enterprise Edition) application that provides an event-driven hosting environment for lightweight services. Lightweight services are persistent, transactional, server-side programs developed in lightweight programming languages such as JavaScript and Python.

Via Erik's Weblog.

Posted by Simon Brunning at 05:41 PM | Permalink | Comments (0)
September 06, 2002
Building an RSS Newsreader

The EffNews Project: Building an RSS Newsreader

If this is up to /F's usual standard, this should be very educational.

I look forward to part two - but don't hurry it, Fredrik. When it's ready.

Posted by Simon Brunning at 03:30 PM | Permalink | Comments (2)
Python UK conference 2003

The Python UK conference 2003 looks like it's going to be good. I'll try and save up and attend both days next year.

Bravo Andy for all his hard work so far. The word committee strikes fear into my heart. But then, no one likes them, they are sometimes a necessary evil, and Andy can't do it all on his own, so I have put myself forward to help.

There is no way that I could do a talk, though. Not only do I not really have much that I could talk about apropos Python, but also I am seriously phobic about public speaking.

It will be exciting to meet Guido, I must say!

Posted by Simon Brunning at 09:52 AM | Permalink | Comments (0)
September 04, 2002
C# vs. Java

A Comparison Of Microsoft's C# Programming Language to Sun Microsystems' Java Programming Language

Some interesting stuff here.

Java desperately needs a foreach statement, properties and variable length argument lists. Especially foreach.

C# isn't cross platform, and exception handling looks weak.

Naturally, Python has all this. God, Python programmers are spoiled!

Update September 13th: A Comparative Overview of C#, another C# vs. Java comparison.

Posted by Simon Brunning at 11:48 AM | Permalink | Comments (2)
August 30, 2002
Python roundup

A number of interesting Python bits and bobs.

Posted by Simon Brunning at 01:57 PM | Permalink | Comments (1)
August 23, 2002
PDF generation

Cameron Laird and Kathryn Soraiz's Yes You Can talks about generating PDF, specifically from Python.

It lead me to Etymon™ PJ Classic, though, an open source Java library for PDF generation.

Posted by Simon Brunning at 01:54 PM | Permalink | Comments (1)
August 21, 2002
Python South-East UK booze-up page

See the Python South-East UK booze-up page for the date and venue of the next meeting. All welcome!

(Source, such as it is, here and here).

If you can suggest any better venues, please do. If you can suggest code improvements, likewise. ;-)

Posted by Simon Brunning at 04:44 PM | Permalink | Comments (1)
August 20, 2002
Python South-East UK booze ups

Hopefully, last week's meeting will become a regular occurrence.

With that in mind, I modestly present boozeup.py, a function for generating the dates of our meetings. (The next is on the 12th of September.)

Needs a bit of testing, and I'll also wrap it up in a CGI, along with a venue generator. For this, I need 12 suggested venues, with a URL for each. A couple more near Paddington, perhaps one in Reading and another in Oxford, one in South London near the ReportLab boys, that sort of thing.

The last meeting was a blast. Chris Miles and I ended up going to Cubana and drinking cocktails. I was a bit woolly on Friday, I must say.

So, I only need 10 venues really - Cubana is a must, and I know South London pubs rather too well.

Posted by Simon Brunning at 02:02 PM | Permalink | Comments (1)
August 16, 2002
On the choice of programming languages

What makes one really like some programming language?

Beyond technical details and empirical evaluations there is a religion-like feeling that one can get obsessed with. And I love the feeling. I just wish I could get rid of it.

This could be me...

Posted by Simon Brunning at 01:04 PM | Permalink | Comments (0)
August 15, 2002
Python UK booze up

I'm off to the Python UK booze up after work this evening - see you there!

You'll know me by my tin of Spam. No, really.

Posted by Simon Brunning at 02:48 PM | Permalink | Comments (0)
August 13, 2002
Python DB-API 2.0 driver for Microsoft ADO

The OPAL group have a preliminary version of an ADO module for Python.

The Database Row Module looks interesting, too...

Posted by Simon Brunning at 04:04 PM | Permalink | Comments (1)
August 06, 2002
Weak, Soft and Phantom references in Java

Reference Objects and Garbage Collection By Monica Pawlan.

See also O'Reilly on the WeakHashMap class, and an implementation of SoftHashMap, which is missing from the Sun library.

Weak references exist in Python, but unfortunately soft references do not. Which is a shame, 'cos they are very useful for eliminating memory leaks from data caches.

Posted by Simon Brunning at 01:51 PM | Permalink | Comments (1)
August 05, 2002

Quixote: a Python-Centric Web Application Framework is a nice intro to Quixote.

See also The MEMS Exchange Architecture.

Posted by Simon Brunning at 01:17 PM | Permalink | Comments (1)
July 31, 2002
SimpleParse 2

I have mentioned SimpleParse before. Well, version 2 is out.

No chance to play with it as yet - I have taken the girls to visit their Gran in Newcastle. But I have no reason to suppose that it's any less cool than version 1. ;-)

Posted by Simon Brunning at 08:28 PM | Permalink | Comments (0)
July 26, 2002
Python sorts

A very interesting thread about sort algorithms over on Python-Dev. The Timbot in full flight!

Posted by Simon Brunning at 03:40 PM | Permalink | Comments (0)
July 24, 2002

A nice little example PyGoogle script.

Posted by Simon Brunning at 02:01 PM | Permalink | Comments (0)
Mastering Regular Expressions, 2nd Ed

Mastering Regular Expressions, 2nd Ed, is out. The author explains What's New with Regular Expressions.

Python and Java coverage much expanded, apparently.

Update August 30th: Order placed with Computer Manuals.

Posted by Simon Brunning at 01:50 PM | Permalink | Comments (0)
July 22, 2002
GUI programming with PythonCard

Building GUI Applications with PythonCard and PyCrust.

Looks interesting. I've not tried PythonCard. Most of my GUI building is in Java, and it's a pig. Anything to make it easier can only be a good thing.

The seperation of the GUI logic from the GUI layout can only be a good thing. If it works, that is. Layout managers can be a royal pain (especially if you have to write your own to get the layout that you want), but they are powerful. For example, making resizing work they way that you want it to work relies of this level of control.

Posted by Simon Brunning at 01:24 PM | Permalink | Comments (2)
July 19, 2002
More Python related blogs

I come across a couple of partially Python related weblogs today, both UK based:

Both interesting reads.

I wonder if there should be a Python related web logs page on python.org?

Posted by Simon Brunning at 12:29 PM | Permalink | Comments (0)
July 17, 2002
Python Web Frameworks Overview

Paul Boddie's Python Web Frameworks Overview has moved to the new Python Wiki.

Posted by Simon Brunning at 04:34 PM | Permalink | Comments (0)
Son of Gadfly

GadflyB5 (so named because Richard Jones prefers Babylon 5 to The Next Generation) version 1.0 is out.

Gadfly is an RDBMS. It isn't ACID, and it doesn't scale well, so it isn't going to replace UDB/400 any time soon. But it is fast, simple, free, and in pure Python.

Posted by Simon Brunning at 04:23 PM | Permalink | Comments (1)
Search Amazon from Python

Mark Pilgrim's PyAmazon allows you to search Amazon by a variety or criteria, and returns standard Python objects. Cool!

Posted by Simon Brunning at 01:22 PM | Permalink | Comments (0)
Python FUD

An intertesting thread on c.l.py.

Python is difficult to read? Bwahahahahaha!

The resulting Python at a Glance document is a very good summary.

Posted by Simon Brunning at 09:44 AM | Permalink | Comments (1)
July 16, 2002
Generator-based state machines

Generator-based state machines is another of Dave Mertz's articles about generators and iterators.

Posted by Simon Brunning at 05:00 PM | Permalink | Comments (0)
Python Eclipse

Superb! Gerhard Kalab has started work on a Python plugin for Eclipse!

Early days yet, mind you, but excellent news nevertheless.

Posted by Simon Brunning at 04:54 PM | Permalink | Comments (1)
July 15, 2002
Python in the enterprise

Python in the enterprise: Pros and cons at builder.com lists, uh, the pros and cons of Python in the enterprise.

I'm not sure about the primitive SQL support thing, but other than that, it seems fair enough.

Tim Couper's "Selling Python to a Fortune 500 Company" presentation at the Python UK conference covered similar ground. But that isn't online.

Update: The c.l.py thread discussing this.

Posted by Simon Brunning at 03:25 PM | Permalink | Comments (1)

PyUT is a UML class diagram editor with Python and Java round-trip support.

Or it will be...

It's going to be good, though - see the features list and screenshots.

Posted by Simon Brunning at 01:15 PM | Permalink | Comments (1)
July 04, 2002
PythonWin - running scripts as an external process

Chris Liechti has a PythonWin patch for nrunning scripts as an external process.

I havn't tried this out yet, 'cos I'm Javaing today. Cool though.

Posted by Simon Brunning at 01:26 PM | Permalink | Comments (0)

Aaron Swartz has put a superb HTML to text conversion utility up on his weblog.

See also License Haiku.

(Via Boing Boing)

Posted by Simon Brunning at 12:37 PM | Permalink | Comments (1)
July 02, 2002
Python Metaclasses

There has been a lot of discussion about metaclasses on c.l.py recently.

Ian McMeans asked for examples of the sort of thing that can best be done using metaclasses, and Mark McEahern demonstrates the use of metaclasses to implement aspect oriented programming in Python.

If this stuff makes your brains leak out of your ears, see Vladimir Marangozov's introduction to metaclasses. If it doesn't make your brains leak out of your ears, well, you are a lot cleverer than I am.

I linked to Jeff Epler's FinalMethods metaclass some time ago.

Aspect Oriented programming links here.

Posted by Simon Brunning at 03:19 PM | Permalink | Comments (3)
The Martellibot speaks...

Doesn't he just!

Anyway, the interview with Alex Martelli is worth a read. Interesting chap.

Posted by Simon Brunning at 09:30 AM | Permalink | Comments (1)
June 28, 2002
Open source web application servers.

Open-source servers today discusses a number of interesting web app platforms.

I use Apache and Tomcat at work. Java is my company's platform of choice, and we are doing a lot of servlet stuff. Seems to work beautifully. Small footprint too - WebSphere is a monster.

JBoss and Enhydra I will look at further - I'm just reading up on J2EE now. (Java for the Web with Servlets, JSP, and EJB. Good. A big book, but that's 'cos it covers a lot.)

I have mentioned Zope before.

(Via Daily Python URL)

Posted by Simon Brunning at 01:29 PM | Permalink | Comments (1)
The case for static types

The case for static types at developerWorks is an interesting counterpoint to Cameron Laird and Kathryn Soraiz's article.

I'm beginning to think that the thing that I dislike most about Java is not the static typing. I think it is mainly down to the fact that you cannot override the built-in operators ('+', '-' and so forth).

This, combined with the fact that the common data structures (Vectors, Hashtables and so on) are not built-ins, but come as part of the standard library. It seems to me that 80% plus of my code involves these data structures. Due to the fact that every operation requires an explicit method call, the code is very verbose. They don't call Java 'Object Oriented COBOL' for nothing!

In Python (You knew I was going to get on to Python, didn't you!) you can override operators, and high level data strictures are built-in. So you can iterate through any sequence with a simple:

for item in sequence:

Lists and files are both sequences, so both can be iterated with this syntax. And because you can override operators, you can make sequences of your own simply by overriding a couple of methods, and then process them with this syntax. Beautiful.

Posted by Simon Brunning at 11:50 AM | Permalink | Comments (0)
June 27, 2002
Eclipse on c.l.py

This thread indicates that there is some interest in a Python plugin for Eclipse. I wonder if anything will come of it.

Posted by Simon Brunning at 02:37 PM | Permalink | Comments (0)
June 25, 2002
Else clauses in Python

Python supports 'else' clauses on 'for', 'while' and 'try' blocks, as well as on 'if' blocks. The effbot demonstrates their use.

Posted by Simon Brunning at 02:16 PM | Permalink | Comments (0)
June 24, 2002
Python related blogs

Python owns us lists some Python related web logs, kindly including my own modest effort.

His list includes links to Babu, Andrew Todd, Kevin Altis and Patrick O'Brien, all of which will be regular reading for me in future.

Hmmm. Link oriented, eh? Fair enough, but that wasn't the plan...

Posted by Simon Brunning at 01:45 PM | Permalink | Comments (1)
Python - it is rocket science...

Space shuttle engineers use Python to streamline mission design.

"We achieve immediate functioning code so much faster in Python than in any other language that it's staggering," says Friedrich. "Java and C++, for example, have much more baggage you have to understand just to get a functioning piece of software."

(Via SumErgoCogito)

Posted by Simon Brunning at 01:33 PM | Permalink | Comments (0)
June 21, 2002
Python interfaces and object adaptation

PEPs 245 (Python interface syntax) and 246 (Object adaptation) are both a little mind stretching, but would be really good additions to Python, I think.

Or perhaps they are too mind bending?

And remember - there is no PSU.

Posted by Simon Brunning at 02:33 PM | Permalink | Comments (0)
June 20, 2002
The truth behind programming languages

Brainfuck, Mueller: "I wasn't aware of the existence of Perl". ;-)

More about Brainfuck.

Posted by Simon Brunning at 03:07 PM | Permalink | Comments (1)
June 18, 2002
Code Migration and Modernization

PEP 290, the Code Migration and Modernization guide, is up.

The key in dict thing is really nice.

See also PEP 8, the official Python style guide.

Posted by Simon Brunning at 12:30 PM | Permalink | Comments (1)
Python PS2 and GameCube ports?


Posted by Simon Brunning at 12:21 PM | Permalink | Comments (1)
June 13, 2002

If you need to parse complex text files, sooner or later re runs out. Either the whole thing becomes a hideous nightmare, or it can't do what you need at all.

When this happens, SimpleParse is probably what you need.

David Mertz has written about SimpleParse in his developerWorks article Parsing with the SimpleParse module. He explains EBNF, and gives an example, parsing smart ASCII.

Posted by Simon Brunning at 01:38 PM | Permalink | Comments (1)
Here be Dragons!

Jeff Epler posts FinalMethods, which uses metaclasses to enforce final methods in Python.

Just don't ask me how it works, OK?

Posted by Simon Brunning at 01:24 PM | Permalink | Comments (0)
Large projects in Python

Domenic Merenda has compiled a list of Large projects developed in Python.

Includes IBM, HP, Microsoft and NASA. Not included in his list, Industrial Light & Magic use Python too.

Update 24 June 2002: Details of the NASA thing.

Posted by Simon Brunning at 12:19 PM | Permalink | Comments (1)
June 12, 2002
New release of omniORB

A new version of Duncan Grisby's CORBA ORB for C++ and Python, omniORB, has been released.

I saw Duncan speak at this year's Python UK conferance. He sold me on CORBA, I must say, but I haven't put it to use yet. I wouldn't be surprised if I used CORBA with Java first.

Posted by Simon Brunning at 03:32 PM | Permalink | Comments (0)
June 11, 2002
Iterators and Generators

One of the biggest changes in Python 2.2 so far as I was concerned was the introduction of iterators and simple generators.

These allow some very elegant solutions to problems involving the processing of generated sequences. David Mertz has an interesting article explaining Iterators and simple generators on the developerWorks site, and another explaining how to use them to implement very lightweight threads.

Posted by Simon Brunning at 12:09 PM | Permalink | Comments (1)
Python 2.3

The first version of AMK's What's New in Python 2.3 document is out.

AMK puts out one of these per Python release, and they contain everything that you need to know to upgrade. Well, they contain everything that I need to know, at any rate.

The new enumerate() Built-in Function looks dead handy, and the new optional argument for the strip methods is my feature request! Cool!

Universal newline support looks good too, thought I haven't had a problem with this myself. I'm pretty much +0 on the bool type.

Posted by Simon Brunning at 10:23 AM | Permalink | Comments (0)
June 10, 2002
The BDFL speaks

Linux Magazine's interview with Guido is on-line.

Posted by Simon Brunning at 06:23 PM | Permalink | Comments (1)
June 07, 2002
New release of win32all

Mark Hammond has released a new version of win32all.

Downloads available for Python versions 2.1 and 2.2.

I have installed it and tried it. (Some pretty simple COM-driving-Excel stuff.) It seems to work.

Posted by Simon Brunning at 03:52 PM | Permalink | Comments (0)
Zope News

Zope News is very irregular, but the June edition is out.

Zope is pretty cool, but also pretty daunting. I have used a couple of pre-built products (ZWiki and Squishdot) with great success, but I've not tried building anything of my own.

I like the Steve Alexander haiku:

Guido's good ideas
Like new buds in the Spring
cause Jim to refactor

A proper haiku, with a seasonal reference and everything.

Posted by Simon Brunning at 02:28 PM | Permalink | Comments (0)
June 06, 2002
wxPython tutorial

IBM's developerWorks has a wxPython for newbies tutorial. Has had for some time, in fact, but I've never seen it.

They also have a Tkinter tutorial. I've written some Tkinter GUI stuff, but the consensus on c.l.py seems to be that wxPython is the way to go.

See also Python GUI toolkits.

Posted by Simon Brunning at 02:16 PM | Permalink | Comments (3)
Using Swing with Jython

Useless Python has an article on Jython and Swing.

Other good tutorials and code snippets here too. Worth exploring if you have some time while you are waiting for the Python Cookbook.

(Or you could always look at the cookbook online.)

Posted by Simon Brunning at 02:09 PM | Permalink | Comments (0)
May 31, 2002
The Python Business Forum

Python in a tie.

Posted by Simon Brunning at 11:39 AM | Permalink | Comments (0)
May 29, 2002
Language Neutrality and the Java Platform

Interesting links from Lambda the Ultimate.

Of course my favorite language has been implemented on the Java platform, so it's good enough for me!

Posted by Simon Brunning at 01:57 PM | Permalink | Comments (0)
May 27, 2002
PC Pro

PC Pro is probably the best mainstream PC magazine available in the UK at the moment. But it almost never mentions non-Windows or non-commercial software.

When it comes to practical information about the Windows platform, running it, configuring it, and the purchase of hardware and software for it, I think that its content is considerably better than that of its closest rival, PCW.

But I have to say, in some ways, it's beginning to irritate me. It seems to totally ignore the Linux platform, and OS software in general. In terms of development environments, its pretty much Microsoft all the way, with a smattering of Delphi. Even Java is left out in the cold.

Just for a change, though Dick Pountain's column mentions Python. I was very glad to see this, despite its inaccuracies. A change on the horizon?

Dick refers to Python as a typeless language. It isn't. It's a dynamically typed language, but it's also a strongly typed language. The distinction is real, although of course the terminology is somewhat subjective. The terms that I have used are common in the Python community at least. Dive into Python explains the distinction very well here.

Also, Dick had no way of knowing this, but Python is probably going to grow a boolean type in the near future.

I referred to PC Pro as a mainstream magazine. Some of the more, uh, specialist magazines are excellent. DDJ is very good, and I recently came across Software Development. Both worth a look. If you are a total nerd, that is.

Posted by Simon Brunning at 01:38 PM | Permalink | Comments (2)
May 24, 2002
The MEMS Exchange Architecture

AMK wrote this very interesting article, discussing the architecture that he and the MEMS Exchange team used to implement a complex web based application.

I'm particularly interested in looking at Quixote and ZODB.

Now I re-read the article, though, Grouch looks worth a look, too. unittest less so, since PyUnit made it into the Python standard library.

Posted by Simon Brunning at 04:14 PM | Permalink | Comments (0)
May 23, 2002
Bicycle Repair Man!

There seems to be a new version of Bicycle Repair Man. I'll have to check it out.

Bicycle Repair Man is a refactoring browser for Python.

I use the Java refactorings in Eclipse extensively, but I haven't given Bicycle Repair Man a bash yet.

Posted by Simon Brunning at 01:52 PM | Permalink | Comments (0)
May 21, 2002
Eclipse 2.0 soon

According to the release schedule for Eclipse 2.0, it will be released at the end of June.

We use Eclipse as our IDE for Java development. It is bloody good.

It is also going to form the basis of future versions of the WebSphere Development Tools for iSeries. RPG in Eclipse - I can't wait!

There are also Eclipse plug-ins for C# and Ruby - perhaps a Python plug-in is in progress? Can't find one.

Posted by Simon Brunning at 12:33 PM | Permalink | Comments (0)
May 20, 2002
What is Well-Commented Code?

Interesting discussion at Slashdot Developers.

I must say that I am commenting a lot less these days. Using modern IDEs like Eclipse or Boa, long names are not a problem., so I'd rather give a function a self explanitory name, and not bother commenting it at all.

Back on the iSeries, 90% of my work is on existing RPGIV code. With a six character limit on field and subroutine names, well, loads of comments are needed..

One of the comments on the /. discussion agrees with this. And has a link to a Radio 4 live feed! Cool!

Posted by Simon Brunning at 12:57 PM | Permalink | Comments (1)
May 15, 2002
Python GUI toolkits

Deadly Bloody Serious mentions the current c.l.py thread, covering the various GUI toolkits available for Python. No mention of the anygui project, I notice.

anygui will be very interesting when ready, I think. For the moment, though, c.l.py tends to lean towards wxPython. I can see why - look what you can do with it. Also, the forthcoming Boa Constructor uses it.

Boa isn't running over Python 2.2 yet, but when it does, I think that it may replace PythonWin as my Python IDE. For a start, it has PyChecker support built in.

Posted by Simon Brunning at 01:27 PM | Permalink | Comments (0)
May 10, 2002
Python Web Frameworks Overview

Paul Boddie has posted a preliminary Python Web Frameworks Overview.

I'm looking forward to hearing what he has to say about Quixote. It sounds very interesting.

Posted by Simon Brunning at 02:51 PM | Permalink | Comments (1)
May 08, 2002
The Python Pattern

"Developers typically see a tenfold productivity increase when they switch to Python" according to Bruce Eckel, speaking during a Design Patterns In Python class.

Check out Bruce's Thinking in Java. I bought the printed version of this after going through the first couple of chapters of the soft version. Highly recommended.

Thinking in Python is an interesting project. It isn't a Python tutorial - it's mainly about patterns, with implementations in Python.

If I were interested in C#, I'd take a look at Thinking in C#, a preliminary version of which is now available. But I'm not, so I won't.

Posted by Simon Brunning at 02:10 PM | Permalink | Comments (0)
May 02, 2002
Jython Essentials

I picked up Jython Essentials on my way home last night, more or less on a whim. I don't actually use Jython, but a juxtaposition of my language of choice, my favourite technical publisher, and my workaday language was impossible to resist.

Its a good book, and I learned a lot about Jython. It's even cooler than I thought. You can subclass Java classes in Jython, or vise versa. A Java class subclassed in Jython can then be re-subclassed in Java again. It's just all too cool to be true!

Type conversions between the two languages is pretty much automatic, though you can get fine control if you want it. You can embed Jython in a Java app if it needs scripting. You can compile a Jython app into a single Java class or jar, either a small one requiring the jython.jar to run, or a big standalone one. And the interactive prompt is a brilliant way to explore the behavior of Java existing classes, and to smoke test your own. It's a one stop shop for all your Java scripting needs.

It also got me thinking again about why I prefer Python to Java so much. The things which irritate me the most are these:

  • Boiler plate code. This is the code which you end up writing again and again and again. Looping through the containers, for example, requires so much code. Now I don't object to verboseness as such - where it adds value. But where it just adds characters, it's irritating. Python's

    for line in list:


    syntax is perfectly comprehensible, and concise.

    And don't get me started on Enumerations...

  • Integration of data structures into the language. You can't override the the built in operators for classes, which leads to very verbose code.

  • Hand holding. If Java tells me one more time that a local variable 'may not have been initialised', when I know damn well it will have been, I swear I'll scream.

Having said all that, Java has its pluses - interfaces are really cool, and JavaDoc is a wonderful tool.

Posted by Simon Brunning at 03:59 PM | Permalink | Comments (0)
May 01, 2002
Syntax Checking the Scripting Way

Cameron Laird and Kathryn Soraiz's article is well worth a look.

One of the most frequent objections to scripting languages (such as Python) is that their lack of static types and declarations will make your code buggier. Until I tried Python, I would have thought the same thing myself. In practice, though, it just doesn't seem to be a problem.

At work, I use Java. Sure, some of the mistakes that I might make are picked up at compile time (or earlier, using a smart IDE like Eclipse). But only some of them. So I have to unit test thoroughly anyway. So all that the static type checking buys me is that I find some errors earlier than I otherwise would.

This would be good, except that static type checking makes me jump through a lot of hoops sometimes to get stuff done. I am certainly many times more productive with Python than with Java.

Now, I would never have discovered this unless I had given Python a try. Dave Thomas and Andy Hunt recommend that a professional developer should learn one new language a year, and preferably one based upon a new paradigm. I'll second that.

My next target is the functional language Haskell.

Posted by Simon Brunning at 03:58 PM | Permalink | Comments (0)
EuroPython 2002

If only! My company aren't into Python, and there is no way I could afford to go off my own back. Ah well...

Posted by Simon Brunning at 12:13 PM | Permalink | Comments (0)
April 29, 2002

It looks as though Mark Hammond's Python.NET isn't dead after all. Bravo, Mark!

Posted by Simon Brunning at 05:33 PM | Permalink | Comments (0)
Python on the iSeries

Per Gummedal has updated his iSeries port of Python to version 2.2.1. Get it here.

I've been working on PC based Java stuff for a while now, so I haven't been keeping an eye on Per's work, but it looks to have come on a long way.

I'm still not sure that it can beat a Jython/JTOpen toolkit combination for functionality, though.

Posted by Simon Brunning at 01:30 PM | Permalink | Comments (5)