At last after a very long time searching, I’ve found a keyboard shortcut that allows you to lock a Mac in a similar style to (⌃⌥Del, L) on Windows.

In iChat options set `Show status in menu bar`, and in Keychain also set `Show status in menu bar`.

Now when you press (⌃F8) the iChat status in your menu bar will get the focus. Then you can just press (←) once to highlight the Keychain status, (↓) to highlight `Lock Screen` and (↩) to select it.

This gives you (⌃F8, ←, ↓, ↩) as a rather convoluted and excessively long keyboard shortcut for locking your computer. It is however very handy when you are working in an office, need to go make coffee and want to [save on kittens](http://www.google.co.uk/search?q=%22every+time+you+touch+the+mouse+god+kills+a+kitten%22).

I’ve been reading about CouchDB on and off for a few months now, and recently decided to properly evaluate it as an option for my new website. This decision weirdly coincided with the release of Google AppEngine which uses their Bigtable system, which is vaguely similar to CouchDB (non-relational, document based, flexible and scalable).

Anyway, I tried to install CouchDB on Leopard, and hit a few minor issues which I thought I’d document for others trying to install it.

I installed from Macports (always a good first stop). There appears to be a missing dependency on SeaMonkey, so you need to do:

sudo port install seamonkey
sudo port install couchdb

When you first start couchdb it complians that: CouchDB needs write permission on the data directory: /opt/local/var/lib/couchdb or CouchDB needs write permission on the log directory: /opt/local/var/log/couchdb.

I tried doing sudo couchdb to get over that, and couchdb seemed to start happily, and there was a response from http://localhost:5984/. However, when I inserted my first document using couchdb-python, python hung completely with no repsonse (I left it for 10 minutes while I made a coffee). In retrospect, sudo couchdb probably wasn’t the correct way to go (particularly as those directories don’t even exist), but I was keen to start playing. The correct thing to do is probably to create a couchdb user that runs the database and do sudo -u couchdb couchdb to start the database. Unfortunately I’m quite lazy, so instead I just did:

sudo mkdir -p /opt/local/var/lib/couchdb
sudo chown ed /opt/local/var/lib/couchdb
sudo mkdir -p /opt/local/var/log/couchdb
sudo chown ed /opt/local/var/log/couchdb

Where ed should be replaced by your username. mkdir -p recursively makes directories (incase you don’t have /opt/local/var/lib/ or /opt/local/var/log) yet.

Anyway, hope this helps someone else, if they have problems.

I’ve been messing around with Python web frameworks for a quite a while now. Trying out lots of different ones and seeing which one feels like the best fit. As I’ve got closer and closer to the right one, I’ve also found that i am getting closer and closer to using WSGI.

WSGI seems excellent and could be great for Python. Frameworks tend to make things seem more difficult and mysterious than they really are. What has taken me a long time to learn is that WSGI is really very simple.

At it’s simplest there are three aspects to it:

  • You receive a dictionary with useful information in it (environ)
  • You receive a function to call that starts the response (start_response)
  • You return an iterator (ie a list) of strings (this is your page body)

Anything on top of that is just helpers. Helpers are great, but you don’t need a framework that hides what is really going on, when it’s as simple as that.

You can create a hello world app as simple as:

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return ["Hello World"]

Obviously that just returns Hello World with no html. Which is bad. So:

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    begin_body = "<html><body>"
    body = "Hello World"
    end_body = "</body></html>"
    return [begin_body, body, end_body]

We don’t want to write begin_body and end_body every time, so lets write a function to handle this for us:

def put_in_body(*args):
    begin_body = "<html><body>"
    end_body = "</body></html>"
    return [begin_body] + list(*args) + [end_body]

Then we can just:

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return put_in_body("Hello World")

We’re going to want to be able to do lots of different things, and we don’t want to write them all in the body of one function, so let’s write a dispatcher:

def dispatch(environ):
    # We need to get the path from the environ, and work out where to go.
    path_info = environ.get('PATH_INFO', '')
    if path_info == "/goodbye":
        return goodbye(environ)
    else:
        return hello_world(environ)

def hello_world(environ):
    return ["Hello World"]

def goodbye(environ):
    return ["Goodbye World"]

def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return put_in_body(dispatch(environ))

Now if you go to /goodbye it will say “Goodbye World”, otherwise it will say “Hello World”.

As you can see it is all very straightforward. It allows you to do things however you want. Adding more and more functionality is just a case of adding functions that returns strings, and telling the dispatcher when to call that function.

In a later post I’ll talk about threading. It turns out that’s easy as well.

If you want to run the code above, just easy_install paste and then add this to the bottom of your file (which I called wsgi_sample.py):

if __name__ == '__main__':
    from paste import httpserver
    httpserver.serve(app, host='127.0.0.1', port='8080')

Then you can do python wsgi_sample.py and visit http://localhost:8080 to see it working (don’t forget to visit http://localhost:8080/goodbye before you leave).