Irrational Exuberance!

Writing to Application Support in PyObjC

August 22, 2008. Filed under cocoapyobjc

When writing a Cocoa app with PyObjC it can be easy to fall into the bad habit of storing the wrong kind of data inside the .app folder. For example, in an application I am writing I use an SQLite database which I access from inside the .app folder like this:

import os,sqlite3
def getDatabase(self):
    path = os.path.join(os.path.dirname(__file__),'my_dict.sqlite')
    return sqlite3.connect(path)

Because that database contains immutable data, storing it inside the .app folder is an appropriate place for it to exist. However, in that same app I also need to store some user specific data. Unlike the immutable database, the correct place to store user specific data is in a subfolder of ~/Library/Application Support/.

The function to calculate that folder can be implemented like this:

import os
from AppKit import *
from Foundation import *
def applicationSupportFolder(appname=u"MyAppNameHere"):
    paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory,NSUserDomainMask,True)
    basePath = (len(paths) > 0 and paths[0]) or NSTemporaryDirectory()
    fullPath = basePath.stringByAppendingPathComponent_(appname)
    if not os.path.exists(fullPath):
        os.mkdir(fullPath)
    return fullPath

That will allow us to find the support folder for any application (as long as we know its name), but we can make it even more useful by building a second function on top which builds the complete path for a given filename.

def pathForFilename(filename,appname=None):
    base = (appname and applicationSupportFolder(appname)) or applicationSupportFolder()
    return base.stringByAppendingPathComponent_(filename)

Using pathForFilename looks like this:

path = pathForFilename('user_data.xml','my_app')
fin = open(path,'r')
prefs = SomeCustomPythonClass(fin.read())

Let me know if there are any questions or comments.