Mac OS X Services - Changes between Tiger, Leopard and Snow Leopard

When a file or folder is selected in the Finder and a Mac OS X Service is invoked, either through the Services menu or its keyboard shortcut, the input fed to the service depends on what version of Mac OS X is running.
  • In Tiger, (10.4), no input is fed to the service.
  • In Leopard (10.5), the absolute path to the file is the input. E.g. "/Users/steve/tablet.rtf"
  • In Snow Leopard (10.6), if the service is configured properly to work on files and folders, then the input will be file URL like "file://Users/steve/tablet.rtf".
In Leopard, any service that accepted selected text would automatically work with selected files or folders in the Finder. However, Snow Leopard changed that. It is still possible for a service to accept both selected text and files plus folders, but if you create a Service using Automator, you are forced to choose one or the other. So, pick one and save your Service. For this example, I'm assuming you picked 'Files and Folders'.

Next, edit the ~/Library/Services/Foo.workflow/Contents/Info.plist and change this:


to this:


Then, in the Python program that is your service, you may want something like this to detect that your input is a file path:

if input.starswith('file://') or input.startswith('/'):
# I think I got a file path as input

For more details, see Services Properties in the Mac Dev Center. Happy holidays!


Calculating the keytag of a DNSKEY in Python

In DNSEC, sometimes you want to know the "keytag" of a DNSKEY record. Here's a Python implementation that uses dnspython:

import struct

def keytag(dnskey):
Given a dns.rdtypes.ANY.DNSKEY dnskey, compute and return its keytag.

For details, see RFC 2535, section 4.1.6
if dnskey.algorithm == 1:
a = ord(dnskey.key[-3]) << 8
b = ord(dnskey.key[-2])
return a + b
header = struct.pack("!HBB", dnskey.flags, dnskey.protocol, dnskey.algorithm)
key = header + dnskey.key
ac = 0
for i, value in enumerate(ord(x) for x in key):
if i % 2:
ac += value
ac += (value << 8)
ac += (ac >> 16) & 0xffff
return ac & 0xffff


Using Django's Syncdb outside of Django

I'm working on another project that uses Django's ORM that isn't (yet) a web applicaiton. There's no settings.py file as the application has its own configuration system build on ConfigObj and optparase. But, before you can use the app, you need to create the tables that Django's ORM needs for your Models. If you app lives in a python package named 'fooapp', then put your Django models in fooapp.models and try this code:

from django.conf import settings
from django.core.management.commands import syncdb

opts, args = build_configuration()
my_app = 'fooapp'
cmd = syncdb.Command()

And do let me know if that works. Thanks!


Running Django with wsgiref that also serves Admin media

I wanted to run a Django app using Python's built-in wsgiref module. It also serves Django admin media. Consider this a stepping stone to running your Django app using CherryPy.
from wsgiref.simple_server import make_server
from django.core.handlers.wsgi import WSGIHandler
from django.core.servers.basehttp import AdminMediaHandler
httpd = make_server('', 8000, AdminMediaHandler(WSGIHandler()))


Rhymes with Pony

Yesterday I pushed out Owney which does USPS shipment tracking in Python. It uses a bit of Django as well. It's got rough edges, so please watch your fingers! I intend to polish it as time permits. I do want to make it a re-usable Django app, but I need some advice on how to make that work.

The original Owney was a dog with a very interesting life.



Snakes in the bassinet (Baby's first open source project)

I pushed out my first open source project this week. It's a Python interface to HelpSpot's web services API. HelpSpot is a help desk application that I use, like and happily recommend.

You can find my project python-helpspot on GitHub. I have another open source thing in the works too. That one is going to be a doggy and it'll have a touch of the django.


Missteps in Django - Part 3

This one will make it obvious that the missteps are my own mistakes, not problems inherit in Django. I'm not terribly embarrassed to look this dumb. Most days, I'm proud of my density. On with the show!

I guess this is another template issue. Oh well. I wanted to set the CSS class on an HTML tag based on some dynamic data. In this case, the data was the status field on my Shipment model:

class Shipment(models.Model):
description = models.TextField()
created = models.DateTimeField(auto_now_add=True);
status = models.CharField(max_length=64, default="new",

I'm omitting STATUS_CHOICES because its not important to my point. I wanted each displayed shipment to have a different background color. My initial idea was to try something like this:

class={% ifequal thing.status "new" %}"new"{% elifequal thing.status "exception" %}"exception"{% endelifequal %}...

Of course, Django doesn't have an elif construct in its templates. Doesn't matter because my idea was stupid and eventually I figured that I could do this:

class="status_{{ shipment.status }}"

and be done with it. I hope I had a good laugh at myself.