Richard Jones' Log: Sane Python application packaging: conclusion (for now?)

Thu, 15 Jan 2009

This is part four of my continuing adventure in packaging my Python application.

In part three I was close to a solution. In the end I have decided to:

Use the "build_apps" distutils command I wrote to generate zip application bundles for the three target platforms. The zip file contains all libraries (pure python, thankfully) and a launcher script to run the application. Split out the examples from the rest so there's just one examples zip file and the other zip files are about half as heavy. Generate a standard distutils source distribution which is intended for Linux system package maintainers. Upload all those files to Google Code using a modified googlecode_upload.py script. Still register with PyPI but set the download_url to point to Google Code.

The upload script was modified in two ways:

First, it's broken with the svn module available under Ubuntu (and others). I modified the code to directly parse the svn passwords. It's a gross hack and probably not widely useful so I won't submit a patch. For the curious the code is below. Secondly I hard-coded it to upload the five files I want to send, just to make my life easier.

I'll await feedback from actual users but I believe that this solution will be good enough.

By the way, I just released a new version of the application in question. It's Bruce, the Presentation Tool (who puts reStructuredText in your projector). The 3.2 release is pretty nice with support for external styles, recording, automated playback of various types, gradual exposure of lists and some other stuff. It's pretty cool.

On to the change to googlecode_upload.py, which replaces get_svn_auth() with:

def get_svn_auth(project_name, config_dir): """Return (username, password) for project_name in config_dir.""" realm = (' Google Code Subversion Repository' % project_name) authdir = os.path.join(config_dir, 'auth', 'svn.simple') for fname in os.listdir(authdir): info = {} key = None for line in open(os.path.join(authdir, fname)): line = line.strip() if line[0] in 'KV': continue if line == 'END': break if line in 'password username svn:realmstring'.split(): key = line else: info[key] = line if info['svn:realmstring'] == realm: return (info['username'], info['password']) return (None, None)