<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Reliably Broken &#187; plist</title>
	<atom:link href="http://reliablybroken.com/b/tag/plist/feed/" rel="self" type="application/rss+xml" />
	<link>http://reliablybroken.com/b</link>
	<description>It&#039;s a blog: let&#039;s do funch!</description>
	<lastBuildDate>Thu, 01 Dec 2011 21:27:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Using plists for site-specific Django settings</title>
		<link>http://reliablybroken.com/b/2009/05/using-plists-for-site-specific-django-settings/</link>
		<comments>http://reliablybroken.com/b/2009/05/using-plists-for-site-specific-django-settings/#comments</comments>
		<pubDate>Wed, 20 May 2009 22:00:51 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[plist]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=150</guid>
		<description><![CDATA[I have a Django project that I am going to deploy at several sites, but I need to tweak the project settings slightly for each site. Specifically I need different a EMAIL_HOST address and related settings for sending mail at each site. The simplest route is to customize the project settings.py as part of the [...]]]></description>
			<content:encoded><![CDATA[<p>I have a <a href="http://www.djangoproject.com/">Django</a> project that I am going to deploy at several sites, but I need
to tweak the project settings slightly for each site. Specifically I need
different a <a href="http://docs.djangoproject.com/en/dev/ref/settings/#email-host">EMAIL_HOST address and related settings</a> for sending mail at each
site.</p>

<p>The simplest route is to customize the project settings.py as part of the
site deployment, but that will drive you insane when you deploy the wrong
custom-settings to a site.</p>

<p>Another approach is similar to that used by many for switching between settings
when moving between testing / staging / live environments: your <code>settings.py</code>
has a few lines something like</p>

<pre><code>try:
    from sitesettings import *
except ImportError:
    pass
</code></pre>

<p>so you can over-ride any setting by putting them in a <code>sitesettings.py</code> file,
and then make sure your deployment never overwrites that site-specific file.</p>

<p>In my case I want to make it easy for the site administrator to customize
the settings, but I am worried that it is too easy for someone who does not
know Python syntax to inadvertently break things by writing a <code>sitesettings.py</code>
that throws <a href="http://docs.python.org/library/exceptions.html#exceptions.SyntaxError">a <code>SyntaxError</code> exception</a>. Given the significance of
white-space in Python I feel this would be easy to get wrong.</p>

<p>So I&#8217;ve gone for storing the custom settings in Mac OS X&#8217;s <a href="http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/plist.5.html">property list
format</a>. Bless Python for it has <a href="http://docs.python.org/library/plistlib.html">the plistlib module</a> that reads
and writes the simple XML format of property lists.</p>

<p>Here&#8217;s my module that imports all properties from a plist straight into the
module&#8217;s namespace. This then makes it easy to over-ride Django&#8217;s settings
by doing</p>

<pre><code>from plistsettings import *
</code></pre>

<p>A couple bits made my lips move during the writing. The contents of <code>__all__</code>
are updated dynamically because I wanted to use this with
<code>from plistingsettings import *</code> without worrying that my module&#8217;s imports
would get clobbered by imports used in the <code>plistsettings</code> module. And working
out how to bind keys and values to the module itself is not obvious to me -
it <em>feels</em> like one ought to be able to use <code>self</code> within the scope of the
module to refer to the module itself. Except you can&#8217;t. No biggie.</p>

<pre><code># plistsettings.py
import os.path
import plistlib
import sys
from xml.parsers.expat import ExpatError


__all__ = []


PLIST_PATH = '/Library/Preferences/com.example.plist'


def read_prefs(plist_path):
    """Import settings from preference file into this module's global namespace.

    Returns a dictionary as returned by plistlib.readPlist().
    """
    try:
        if os.path.exists(plist_path):
            prefs = plistlib.readPlist(plist_path)
        else:
            return
    except ExpatError:
        return

    mod = sys.modules[__name__]
    global __all__

    for key, value in prefs.items():
        setattr(mod, key, value)
        __all__.append(key)
    return prefs

read_prefs(PLIST_PATH)
</code></pre>

<p>Now if you are the kind of Mac guy who enjoys using <code>defaults</code> you can write
out your site-specific settings from the command-line.</p>

<pre><code>defaults write /Library/Preferences/com.example EMAIL_HOST smtp.example.com
plutil -convert xml1 /Library/Preferences/com.example.plist
</code></pre>

<p>N.B. Mac OS X 10.5 <code>defaults</code> uses the binary format by default, so you need
<code>plutil</code> to convert it back to XML because <code>plistlib</code> does not handle
the binary format.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/05/using-plists-for-site-specific-django-settings/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

