Announcing Chipmunk Backup

I put up on Launchpad a backup utility I wrote called Chipmunk Backup. It's not extremely configurable nor does it have a huge set of features. It's a simple tool for maintaining a number of GnuPG encrypted full backups of a directory in a remote, rsync-accessible location.

There's no ready to download archive, but checking out lp:chipmunk-backup with bzr should give you a working version.

It's written in PLT Scheme and is known to work with version 4.1.4.

Article page

Emacs tips: Navigate CamelCase words

Emacs tip #0: Always search EmacsWiki when you think you might need something.

Emacs tip #1: To navigate studlyCapped words, M-x c-subword-mode, as found on the CamelCase page. I had to add the following lines to my .emacs to get it work with C-left/C-right, M-b/M-f worked right out of the box:

(define-key global-map [(control right)] 'forward-word)
(define-key global-map [(control left)] 'backward-word)

Before that, they were bound to the -nomark variants.

Article page

Inline admin forms with admin site links in Django

I have a somewhat difficult relationship with Django's admin site. It's a very useful feature, but I haven't really done enough with it to know when I'm going to hit a wall, if that wall's in the code or in my understanding, and how hard it's going to be to climb over the wall.

This time I wanted to have inline admin forms, except that I didn't actually want to have the forms there, I just wanted to have links to the objects — and not their views on the actual site, but on the admin site. As far as I can tell, there's no built-in support for this.

According to the admin docs, there are two subclasses of InlineModelAdmin: TabularInline and StackedInline. Looking at django/contrib/admin/options.py confirms this. And as the docs say, the only difference is the template they use. The stacked version comes pretty close when we add all the fields to an InlineModelAdmin subclass's exclude array, but it doesn't have the link.

To solve this we first create a new subclass:

class LinkedInline(admin.options.InlineModelAdmin):
    template = "admin/edit_inline/linked.html"

When you want to create inline links to a model, you subclass this new LinkedInline class. So to use a slightly contrived example, if we have a Flight with Passengers:

class PassengerInline(LinkedInline):
    model = models.Passenger
    extra = 0
    exclude = [ "name", "sex" ] # etc

class FlightAdmin(admin.ModelAdmin):
    inlines = [ PassengerInline ]

And yes, we have to exclude all the fields explicitly: an empty fields tuple or list is ignored.

The new template is easiest to create by cutting down aggressively the stacked template. Like this:

{% load i18n %}
<div class="inline-group">
  <h2>{{ inline_admin_formset.opts.verbose_name_plural|title}}</h2>
{{ inline_admin_formset.formset.management_form }}
{{ inline_admin_formset.formset.non_form_errors }}

{% for inline_admin_form in inline_admin_formset %}
<div class="inline-related {% if forloop.last %}last-related{% endif %}">
  <h3><b>{{ inline_admin_formset.opts.verbose_name|title }}:</b>&nbsp;{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %} #{{ forloop.counter }}{% endif %}
    {% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
  </h3>
  {{ inline_admin_form.pk_field.field }}
  {{ inline_admin_form.fk_field.field }}
</div>
{% endfor %}
</div>

The primary/foreign key fields are necessary to keep Django happy.

The result looks about right, it just lacks the links. It seems that Django doesn't give the template all the information we need to make them work: there's root_path that gives us /admin/, app_label contains the application's name and inline_admin_form.original.id contains the id of the inline object. What is lacking is the path component that names the model. I don't think it's available by default (is there a clean way to ask Django what's available in a template's context?), so we need to add it. Amend LinkedInline to look like this:

class LinkedInline(admin.options.InlineModelAdmin):
    template = "admin/edit_inline/linked.html"
    admin_model_path = None

    def __init__(self, *args):
        super(LinkedInline, self).__init__(*args)
        if self.admin_model_path is None:
            self.admin_model_path = self.model.__name__.lower()

Now inline_admin_formset.opts.admin_model_path will be bound to the lowercase name of the inline object's model, which is what the admin site uses in its paths.

With this, we can now replace the inline-related div in the template with this:

<div class="inline-related {% if forloop.last %}last-related{%  endif %}">
  <h3><b>{{ inline_admin_formset.opts.verbose_name|title  }}:</b>&nbsp;<a href="{{ root_path }}{{ app_label }}/{{ inline_admin_formset.opts.admin_model_path }}/{{ inline_admin_form.original.id }}/">{% if inline_admin_form.original %}{{ inline_admin_form.original }}{% else %} #{{ forloop.counter }}{% endif %}</a>
    {% if inline_admin_formset.formset.can_delete and inline_admin_form.original %}<span class="delete">{{ inline_admin_form.deletion_field.field }} {{ inline_admin_form.deletion_field.label_tag }}</span>{% endif %}
  </h3>
  {{ inline_admin_form.pk_field.field }}
  {{ inline_admin_form.fk_field.field }}
</div>

That's it. Now Flights get links to Passengers without big forms cluttering up the page.

Article page

iPhone shuffle

These days I use an iPhone as my mobile music device. I have a bit over 1800 songs on it. I usually use shuffle and had it stuck in a weird state a couple of weeks ago — it was constantly playing me just a few tracks. I usually listen for just half an hour to an hour at a time, so I don't know if it would have started looping or what, but those were basically always there for a week's worth of commutes. I finally restarted the phone and that seemed to help, but what do you know, a couple of weeks, several restarts and one operating system upgrade later, it's again playing me exactly the same tracks.

As much as I love the The Roots, honestly, at this points Adrenaline!'s "Once a-again, once a-gain..." start makes me mostly think "once again indeed."

Article page

Crashes with NSURLConnection

Speaking of Cocoa (and iPhone) programming, for a change.

Having trouble with spurious EXC_BAD_ACCESS crashes when using NSURLConnection? NSZombie giving you not very clear messages about [Not A Type retain], pointing to an address that malloc_history says has been allocated somewhere with only framework code in the call stack? See Amro Mousa's blog entry about the subject.

In a nutshell, don't send the start message to a NSURLConnection object you've initialized with a +connectionWithRequest:delegate: or -initWithRequest:delegate:. It'll break stuff.

Apple, how about a warning about this in the docs? The docs for -start say "Causes the receiver to begin loading data, if it has not already.", not "Will break your program and make you waste uncounted hours debugging if receiver has already started." Or how about preventing this in the code? Is there some scenario where you'd want to call start after the object has already started?

Article page

Various Python related things

  • Python Magazine published my article "Using Dependency Injection in Python" in their August issue. Doug Hellman saw my blog entry about DI when I was switching web hosting and managed to repost old stuff to Planet Python, contacted me to ask if I wanted to expand on it a bit, I said yes, and now I've been published. Which is nice. I basically argue in the article that dependency injection is a good idea and you don't need to buy into a framework to get many of the benefits and provide some examples on how to do it. Which seems kind of apropos, seeing as there's yet another new contestant in that area.
  • I was hacking on something I wrote in Python recently and was doing it in a pretty heavily dependency injected manner, writing tests as I was going along. It came to me that one really basic, really nice thing about Python that isn't discussed all that much is that callables are duck typed and there are multiple choices on how to implement them. When you write a function that takes as a parameter something it calls to acquire values it doesn't have to care what the thing it's been given actually is. It can be a function, a callable, a bound method, a constructor, a lambda expression or even a generator. The caller doesn't have to care. It's not a language feature that's easy to fit in a bullet point or to appreciate without using it, but it is useful.
  • I was excited to see class decorators are coming in Python 2.6. Then I realized I can't remember what I wanted to use them for when I was really frustrated by their absence, but still, it's good. I always found their absence rather puzzling.
Article page