Jacob Kaplan-Moss

More buildout notes

I wrote this post in 2009, more than 15 years ago. It may be very out of date, partially or totally incorrect. I may even no longer agree with this, or might approach things differently if I wrote this post today. I rarely edit posts after writing them, but if I have there'll be a note at the bottom about what I changed and why. If something in this post is actively harmful or dangerous please get in touch and I'll fix it.

I got a lot of great feedback on my buildout tutorial I posted last week. In general, the comments there have some excellent tips, tricks, and extra pointer, so check ’em out.

After reading the comments and a few more I got over email, I thought I’d share a selected grab-bag of updates, hints, and details for those fooling around with Buildout and Django.

Django trove identifier

James Bennett pointed out that Django has its very own PyPI classification, Framework :: Django. It’s a good point: anyone posting Django-related packages to the cheeseshop ought to make sure that the list of classifiers in setup.py includes the Django classifier.

It looks like most folks are already doing this: right now there are 146 packages tagged with the Django classifier.

Testing against multiple versions of Django

Turns out there’s a neat trick you can use to develop/test against multiple versions of Django. This is a good idea: there’s supposed to be API stability between Django 1.0 and the forthcoming Django 1.1, but… well, “trust but verify.”

All you need to do is use multiple djangorecipe blocks:

[django-1.0]
recipe = djangorecipe
version = 1.0.2
projectegg = shorturls
project = shorturls
settings = testsettings
test = shorturls
testrunner = test-1.0
eggs = ${buildout:eggs}

[django-trunk]
recipe = djangorecipe
version = trunk
projectegg = shorturls
project = shorturls
settings = testsettings
test = shorturls
testrunner = test-trunk
eggs = ${buildout:eggs}

With that, you can easily run ./bin/test-trunk and ./bin/test-1.0 to test against both versions.

Certainly makes me happy.

Dependancies

Kevin Teague reminded me that listing eggs in the install_requires field of setup.py instead of buildout:eggs is a better way of managing dependancies: packages listed in install_requires get installed automatically by your users, whereas ones in the Buildout only get installed by you, locally.

Kevin also suggested that I list Django as a dependancy in install_requires. I’m actually not sure about this idea though: lots of people – me included – install Django through other means (djangorecipe, direct from source, etc.), so listing it as a hard dependancy means those folks will get an install of Django forced that they may not want. Indeed, listing Django as a dependancy breaks the multiple version trick I just shared.

Egg caches, shared eggs, and “omelette”

Kevin Teague and Ben Ford (via email) both shared a tip about making Buildout run faster by caching and sharing eggs.

You’ll basically add a couple of lines to your buildout.cfg:

[buildout]
eggs-directory = /home/you/.buildout/eggs
download-cache = /home/you/.buildout/dlcache

You can also put these same lines in a ~/.buildout/default.cfg; Buildout picks up user-level settings from that file.

~/.buildout/default.cfg is news to me; I think there’s probably some nifty tricks you could pull with that, but I’m still fooling with it.

Kevin also pointed introduced me to the so-called “omelette” recipe:

A big drawback of eggs is that you no longer have a single directory which you can grep, point an IDE at, etc. Fortunately there is a recipe to take a list of eggs and create a “flat” view by creating a collection of symlinks. The following config will give you a ./parts/omelette/ which you can use (one can even [set] PYTHONPATH [to] this location and use it in a completely “egg unaware” manner):

[omelette]
recipe = collective.recipe.omelette
eggs = ${buildout:eggs}

When combined with egg caching, it’s extra juicy to have a large central location of python packages, and let buildout simply create symlink[s] – views into this cache that express different working sets of packages.

I’m a bit fed up with all the “egg” puns – c’mon, “omelette,” really? – but the functionality’s neat.

Application templates

I got a few suggestions of ways to automate creation of the app environment. There’s a lot of options in this area:

HISTORY

A few people (Kevin, again, and someone else over email who’ve I’ve forgotten) also suggested that a good application template ought to include a HISTORY or CHANGELOG file along with the README.

Personally, I’ve never seen the point: for granular change history you’ll want to consult the revision control system, and each new version ought to come with high-level release notes as part of the docs. However, it’s not like having a HISTORY is going to hurt, so it’s worth considering.

Whiskey

I’m amazed by how many Pythonistas are also whiskey snobs. Suggestions included the Glenfiddich 30, which is fantastic, and the Macallan 12, which I have yet to try. But I will keep drinking my whiskey on the rocks, thank you very much.