from http://inventwithpython.com/hacking/chapter20.html