Monthly Archives: December 2009

Merry Christmas

Thank you to the varied shop staff in London this past week for being without exception polite, enthusiastic and helpful when I asked for help. Especially the girl in HMV Bond Street who spelt Zappa as “zapper” – she was cute. It made tedious shopping joyful.

Let’s do it again next year! Love Dave

Context managers

I was re-writing the exellent watchedinstall tool and needed to simplify a particularly gnarly chunk of code that required three sub-proceses to be started and then killed after invoking another process. It occurred to me I could make these into context managers.

Previously the code was something like…

start(program1)
try:
    start(program2)
except:
    stop(program1)
    raise

try:
    start(program3)
except:
    stop(program2)
    stop(program1)
    raise

try:
    mainprogram()
finally:
    stop(program3)
    stop(program2)
    stop(program1)

Of course that could have been written with nested try / except / else / finally blocks as well, which I did start with but found not much shorter while almost incomprehensible.

With context managers the whole thing was written as…

# from __future__ import with_statement, Python 2.5

with start(program1):
    with start(program2):
        with start(program3):
            mainprogram()

So much more comprehensible! Here’s the implementation of the context manager (using the contextlib.contextmanager decorator for a triple word score):

import contextlib
import os
import signal
import subprocess


@contextlib.contextmanager
def start(program_args):
    prog = subprocess.Popen(program_args)
    if prog.poll(): # Anything other than None or 0 is BAD
        raise subprocess.CalledProcessError(prog.returncode, program_args[0])

    try:
        yield
    finally:
        if prog.poll() is None:
            os.kill(prog.pid, signal.SIGTERM)

For bonus points I might have used contexlib.nested() to put the three start() calls on one line but then what would I do for the rest of the day?

Snow Leopard: a reactionary writes

Things I like about Mac OS X version 10.6:

(Mac OS X 10.6 is also known as Snow Leopard, although I dislike Apple’s use of the operating system codename in their publicity material because it leads to conversations where people talk about “Leopard” and “Tiger” and one has to stop for a second to translate those to actual operating system versions and no-one is ever going to refer to Mac OS X 10.3 as Panther these days, let alone 10.2 being Jagwire or heaven forbid Puma and Cheetah. What are the chances I’ll have to look up the codename for 10.5 by the time we reach 10.10? Version numbers are not so evocative but are less confusing than codenames. This doesn’t mean I will stop naming hard disks after Mac OS codenames – my desktop has Veronica, Gershwin, Harmony and Sonata connected at the moment, with Copland and Pink sitting on the shelf as appropriate…)

Things I like about Mac OS X Snow Leopard:

  • Apple’s drivers for my Epson all-in-one printer / scanner actually work. Epson’s drivers for the same printer / scanner only worked if you never used the scanner and promised to attend church more often.
  • Significantly snappier.
  • QuickTime Player’s minimal interface.

Things I dislike about Mac OS X Snow Leopard:

Everything else in 10.6 is good. However it strikes me that the de-emphasizing of old-style Mac metadata (type / creator codes) and the default of not showing your computer’s hard drive icon on the desktop are evidence of the triumph of old-school Next-ies within Apple.

I think the decision to cover-up the hierarchical filesystem is a bad thing.

P.S. Wouldn’t it have been awesome if, having released Mac OS X Cheetah, Apple had continued with naming their releases after other famous Hollywood animal actors? Why they stopped naming releases after disappointing Sylvester Stallone movies is beyond me – most any version of System 7 could have been named Lock Up.

Serving custom Django admin media in development

I’ve just discovered Django‘s development server always serves admin media. This is tremendously useful because it means you don’t need to configure a static serve view in your project urls.py during development.

However what bit me was I wanted to use a customised set of admin media and had configured a view for the ADMIN_MEDIA_URL path and was going batty trying to work out why Django was ignoring it. It used to be that as long as you had DEBUG = False in settings.py then the development server did not try to help serve the admin media automatically.

Changeset 6075 added a switch to the runserver command for over-riding the admin media directory.

python manage.py runserver --adminmedia /path/to/custom/media

That change was made more than two years ago. It is right there in the documentation. A little bit of magic that wasted fifteen minutes of my frantic schedule (except for the fact I do not have a frantic schedule).