<?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; python</title>
	<atom:link href="http://reliablybroken.com/b/tag/python/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>Widths &amp; Heights with xlwt + Python</title>
		<link>http://reliablybroken.com/b/2011/10/widths-heights-with-xlwt-python/</link>
		<comments>http://reliablybroken.com/b/2011/10/widths-heights-with-xlwt-python/#comments</comments>
		<pubDate>Wed, 12 Oct 2011 15:47:43 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=693</guid>
		<description><![CDATA[This article about using xlwt to generate Excel in Python reminded me I needed to see exactly how to set column widths (the xlwt documentation doesn&#8217;t cover it). Let&#8217;s create a new Excel workbook and add a sheet: &#62;&#62;&#62; import xlwt &#62;&#62;&#62; book = xlwt.Workbook(encoding='utf-8') &#62;&#62;&#62; sheet = book.add_sheet('sheeeeeet') We need to get a column [...]]]></description>
			<content:encoded><![CDATA[<p>This <a href="http://www.youlikeprogramming.com/2011/04/generating-excel-documents-with-the-xlwt-python-library-with-examples/trackback/">article about using xlwt to generate Excel</a> in <a href="http://www.python.org/">Python</a> reminded me I needed to see exactly how to set column widths (the <a href="https://secure.simplistix.co.uk/svn/xlwt/trunk/xlwt/doc/xlwt.html">xlwt documentation</a> doesn&#8217;t cover it).</p>

<p>Let&#8217;s create a new <a href="http://office.microsoft.com/en-us/excel">Excel</a> workbook and add a sheet:</p>

<pre><code>&gt;&gt;&gt; import xlwt
&gt;&gt;&gt; book = xlwt.Workbook(encoding='utf-8')
&gt;&gt;&gt; sheet = book.add_sheet('sheeeeeet')
</code></pre>

<p>We need to get a column in order to set its width. You do that by call <code>col()</code> on the sheet, passing the column&#8217;s index as the only argument (or <code>row()</code> for accessing rows):</p>

<pre><code>&gt;&gt;&gt; sheet.col(0)    # First column
&lt;xlwt.Column.Column object at 0x10b2a6190&gt;
&gt;&gt;&gt; sheet.row(2)    # Third row
&lt;xlwt.Row.Row object at 0x10b2a7050&gt;
</code></pre>

<p>The index is zero-based. You can fetch a column even if you have not written to any cell in that column (this applies equally to rows).</p>

<p>Columns have a property for setting the width. The value is an integer specifying the size measured in 1/256 of the width of the character &#8217;0&#8242; as it appears in the sheet&#8217;s default font. xlwt creates columns with a default width of 2962, roughly equivalent to 11 characters wide.</p>

<pre><code>&gt;&gt;&gt; first_col = sheet.col(0)
&gt;&gt;&gt; first_col.width = 256 * 20              # 20 characters wide (-ish)
&gt;&gt;&gt; first_col.width
5120
</code></pre>

<p>For rows, the height is determined by the style applied to the row or any cell in the row. <em>(In fact rows also have a property called <code>height</code> but it doesn&#8217;t do what you want.)</em> To set the height of the row itself, create a new style with a font height:</p>

<pre><code>&gt;&gt;&gt; tall_style = xlwt.easyxf('font:height 720;') # 36pt
&gt;&gt;&gt; first_row = sheet.row(0)
&gt;&gt;&gt; first_row.set_style(tall_style)
</code></pre>

<p>Setting the style on the row does not change the style of the cells in that row.</p>

<p>There is no obvious way to set a default width and height for all columns and rows. An instance of <code>xlwt.Worksheet.Worksheet</code> has properties for <code>col_default_width</code> and <code>row_default_height</code> but changing those does not actually change the defaults.</p>

<p>The problem is that new columns are always created with an explicit width, while rows take their height from the style information.</p>

<p>My first attempt at setting defaults set the width on every column and the height on every row. It works, but <a href="http://office.microsoft.com/en-us/excel-help/excel-specifications-and-limits-HP005199291.aspx">creates 65,536 unnecessary empty row objects</a>.</p>

<p>A slightly better approach is to set the width on every column and to set the font height on the default style record in the workbook:</p>

<pre><code>import itertools
import xlwt

book = xlwt.Workbook(encoding='utf-8')
sheet = book.add_sheet('sheeeeeet')

col_width = 256 * 20                        # 20 characters wide

try:
    for i in itertools.count():
        sheet.col(i).width = col_width
except ValueError:
    pass

default_book_style = book.default_style
default_book_style.font.height = 20 * 36    # 36pt

book.save('example.xls')
</code></pre>

<p>Here I used <code>itertools.count()</code> and wrapped the loop in a try block so I can forget exactly how many columns are permitted. When the loop tries to access a bad index it will throw <code>ValueError</code> and the loop will exit.</p>

<p>You mustn&#8217;t replace the default style on an instance of xlwt.Workbook.Workbook, you have to update the property of the existing style (to ensure you are changing the <em>first</em> style record). Unfortunately there is no way to set a default column width (as of xlwt version 0.7.2) so the brute force method of setting every column will have to do &#8211; it isn&#8217;t so bad since there are only 256 columns.</p>

<p>Talking of widths and heights, have you heard <a href="http://www.youtube.com/watch?v=2WtqQ6X2F8Q">&#8220;Widths &amp; Heights&#8221;</a> by <a href="http://magicarm.co.uk/">Magic Arm</a>? Is good.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2011/10/widths-heights-with-xlwt-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Free software FTW! Updated filetimes.py</title>
		<link>http://reliablybroken.com/b/2011/09/free-software-ftw-updated-filetimes-py/</link>
		<comments>http://reliablybroken.com/b/2011/09/free-software-ftw-updated-filetimes-py/#comments</comments>
		<pubDate>Sat, 10 Sep 2011 13:36:50 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=674</guid>
		<description><![CDATA[Two years ago (flippin&#8217; heck it seems like only yesterday) I wrote about converting between Unix timestamps and Windows timestamps using Python. In that post I linked to my very simple implementation of a module that provides converting back and forth between the formats. A few weeks ago I received an e-mail from Timothy Williams [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://reliablybroken.com/b/2009/09/working-with-active-directory-filetime-values-in-python/">Two years ago</a> (flippin&#8217; heck it seems like only yesterday) I wrote about converting between Unix timestamps and Windows timestamps using Python. In that post I linked to my very simple implementation of a module that provides converting back and forth between the formats.</p>

<p>A few weeks ago I received an e-mail from Timothy Williams with changes to the my module so that it preserves the fractions of a second in the conversion. How sweet is that?!?!! Exclamation mark question mark exclamation mark cellida diaresis em-dash full stop king of punctuation.</p>

<p>It is fantastic that not only did someone find my code useful but also that they were generous enough to take the time to improve it and give the changes back to me. I love tasty, delicious free software and the people like Tim who make it tastier and more delicious.</p>

<p>So here is the new version of <a href="http://reliablybroken.com/b/wp-content/filetimes.py">filetimes.py incorporating Tim&#8217;s fixes</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2011/09/free-software-ftw-updated-filetimes-py/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>XPath bug in old versions of ElementTree</title>
		<link>http://reliablybroken.com/b/2011/09/xpath-bug-elementtree/</link>
		<comments>http://reliablybroken.com/b/2011/09/xpath-bug-elementtree/#comments</comments>
		<pubDate>Thu, 08 Sep 2011 10:47:46 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=669</guid>
		<description><![CDATA[I figured out why my XML parsing code works fine using the pure-Python ElementTree XML parsing module but fails when using the speedy and memory-optimized cElementTree XML parsing module. The XPath 1.0 specification says '.' is short-hand for 'self::node()', selecting a node itself. Parsing an XML document and selecting the context node with ElementTree in [...]]]></description>
			<content:encoded><![CDATA[<p>I figured out why my XML parsing code works fine using the <a href="http://effbot.org/zone/element-index.htm">pure-Python ElementTree XML parsing module</a> but fails when using <a href="http://effbot.org/zone/celementtree.htm">the speedy and memory-optimized cElementTree XML parsing module</a>.</p>

<p><a href="http://www.w3.org/TR/xpath/">The XPath 1.0 specification</a> says <code>'.'</code> is short-hand for <code>'self::node()'</code>, selecting a node itself.</p>

<p>Parsing an XML document and selecting the context node with ElementTree in Python 2.5:</p>

<pre><code>&gt;&gt;&gt; from xml.etree import ElementTree
&gt;&gt;&gt; ElementTree.VERSION
'1.2.6'
&gt;&gt;&gt; doc = "&lt;Root&gt;&lt;Example&gt;BUG&lt;/Example&gt;&lt;/Root&gt;"
&gt;&gt;&gt; node1 = ElementTree.fromstring(doc).find('./Example')
&gt;&gt;&gt; node1
&lt;Element Example at 10e0ed8c0&gt;
&gt;&gt;&gt; node1.find('.')
&lt;Element Example at 10e0ed8c0&gt;
&gt;&gt;&gt; node1.find('.') == node1
True
</code></pre>

<p>See how the result of <code>node1.find('.')</code> is the node itself? <a href="http://www.w3.org/TR/xpath/#path-abbrev">As it should be</a>.</p>

<p>Parsing an XML document and selecting the context node with cElementTree in Python 2.5:</p>

<pre><code>&gt;&gt;&gt; from xml.etree import cElementTree
&gt;&gt;&gt; doc = "&lt;Root&gt;&lt;Example&gt;BUG&lt;/Example&gt;&lt;/Root&gt;"
&gt;&gt;&gt; node2 = cElementTree.fromstring(doc).find('./Example')
&gt;&gt;&gt; node2
&lt;Element 'Example' at 0x10e0e3660&gt;
&gt;&gt;&gt; node2.find('.')
&gt;&gt;&gt; node2.find('.') == node2
False
</code></pre>

<p>Balls. The result of <code>node2.find('.')</code> is <code>None</code>.</p>

<p>However! I have a kludgey work-around that works whether you use ElementTree or cElementTree. Use <code>'./'</code> instead of <code>'.'</code>:</p>

<pre><code>&gt;&gt;&gt; node1.find('./')
&lt;Element Example at 10e0ed8c0&gt;
&gt;&gt;&gt; node1.find('./') == node1
True
&gt;&gt;&gt; node2.find('./')
&lt;Element 'Example' at 0x10e0e3660&gt;
&gt;&gt;&gt; node2.find('./') == node2
True
</code></pre>

<p><em>Kludgey because <code>'./'</code> is not a valid XPath expression.</em></p>

<p>So we are back on track. Also works for Python 2.6 which has the same version of ElementTree.</p>

<p>Fortunately Python 2.7 got a new version of ElementTree and the bug is fixed:</p>

<pre><code>&gt;&gt;&gt; from xml.etree import ElementTree
&gt;&gt;&gt; ElementTree.VERSION
'1.3.0'
&gt;&gt;&gt; doc = "&lt;Root&gt;&lt;Example&gt;BUG&lt;/Example&gt;&lt;/Root&gt;"
&gt;&gt;&gt; node3 = ElementTree.fromstring(doc).find('./Example')
&gt;&gt;&gt; node3
&lt;Element 'Example' at 0x107257210&gt;
&gt;&gt;&gt; node3.find('.')
&lt;Element 'Example' at 0x107257210&gt;
&gt;&gt;&gt; node3.find('.') == node3
True
</code></pre>

<p>However! They also fixed my kludgey work-around:</p>

<pre><code>&gt;&gt;&gt; node3.find('./')
&gt;&gt;&gt; node3.find('./') == node3
False
</code></pre>

<p>So I can&#8217;t code something that works for all three versions. This is annoying. I was hoping to just replace ElementTree with the C version, makes my code run in one third the time (the XML parts of it run in one tenth the time). And cannot install any compiled modules &#8211; the code can only rely on Python 2.5&#8242;s standard library.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2011/09/xpath-bug-elementtree/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Styling your Excel data with xlwt</title>
		<link>http://reliablybroken.com/b/2011/07/styling-your-excel-data-with-xlwt/</link>
		<comments>http://reliablybroken.com/b/2011/07/styling-your-excel-data-with-xlwt/#comments</comments>
		<pubDate>Sat, 02 Jul 2011 23:34:33 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[excel]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=648</guid>
		<description><![CDATA[This post is about how to create styles in Excel spreadsheets with the most excellent xlwt for Python. The documentation for xlwt (version 0.7.2) is a little sketchy on how to use formatting. So here goes&#8230; To apply formatting to a cell you pass an instance of the xlwt.XFStyle class as the fourth argument to [...]]]></description>
			<content:encoded><![CDATA[<p>This post is about how to create styles in <a href="http://office.microsoft.com/en-us/excel/">Excel spreadsheets</a> with <a href="http://www.python-excel.org/">the most excellent xlwt</a> for <a href="http://www.python.org/">Python</a>. The documentation for xlwt (version 0.7.2) is a little sketchy on how to use formatting. So here goes&#8230;</p>

<p>To apply formatting to a cell you pass an instance of the <code>xlwt.XFStyle</code> class as the fourth argument to the <code>xlwt.Worksheet.write</code> method. The best way to create an instance is to use the <code>xlwt.easyxf</code> helper, which takes a string that specifies the formatting for a cell.</p>

<p>The other thing about using styles is you should only make one instance of each, then pass that same style object every time you want to apply it to a cell.</p>

<p>An example which uses a few styles:</p>

<pre><code>import xlwt

styles = dict(
    bold = 'font: bold 1',
    italic = 'font: italic 1',
    # Wrap text in the cell
    wrap_bold = 'font: bold 1; align: wrap 1;',
    # White text on a blue background
    reversed = 'pattern: pattern solid, fore_color blue; font: color white;',
    # Light orange checkered background
    light_orange_bg = 'pattern: pattern fine_dots, fore_color white, back_color orange;',
    # Heavy borders
    bordered = 'border: top thick, right thick, bottom thick, left thick;',
    # 16 pt red text
    big_red = 'font: height 320, color red;',
)
</code></pre>

<p>I have no idea what it is based on, but 20 = 1 pt. So 320 = 16 pt text.</p>

<pre><code>book = xlwt.Workbook()
sheet = book.add_sheet('Style demo')

for idx, k in enumerate(sorted(styles)):
    style = xlwt.easyxf(styles[k])
    sheet.write(idx, 0, k)
    sheet.write(idx, 1, styles[k], style)

book.save('Example.xls')
</code></pre>

<p>It isn&#8217;t included with <a href="http://pypi.python.org/pypi/xlwt/0.7.2">the current distribution on the cheese shop</a>, but there is <a href="https://secure.simplistix.co.uk/svn/xlwt/tags/0.7.2/xlwt/doc/pattern_examples.xls">a useful Excel spreadsheet demonstrating cell patterns</a> in the source repository.</p>

<p>You can find the complete list of possible cell formats by reading <a href="https://secure.simplistix.co.uk/svn/xlwt/tags/0.7.2/xlwt/Style.py">the source for <code>xlwt.Styles</code></a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2011/07/styling-your-excel-data-with-xlwt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Class-based views for Bottle</title>
		<link>http://reliablybroken.com/b/2010/12/class-based-views-for-bottle/</link>
		<comments>http://reliablybroken.com/b/2010/12/class-based-views-for-bottle/#comments</comments>
		<pubDate>Fri, 03 Dec 2010 21:39:46 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[bottle]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=578</guid>
		<description><![CDATA[I&#8217;m not convinced this is actually a good idea, but I have an approach for using class-based views as handlers for a route with Bottle. (If you were mad keen on Django&#8217;s shift to class-based views you might reckon life wouldn&#8217;t be complete with a Bottle-based application until you employ classes for views. However Bottle&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m not convinced this is actually a good idea, but I have an approach for using class-based views as handlers for a route with <a href="http://bottle.paws.de/">Bottle</a>.</p>

<p><em>(If you were mad keen on <a href="http://www.djangoproject.com/">Django&#8217;s</a> shift to <a href="http://docs.djangoproject.com/en/dev/topics/class-based-views/">class-based views</a> you might reckon life wouldn&#8217;t be complete with a Bottle-based application until you employ classes for views. However Bottle&#8217;s use of decorators for tying URLs to views means it is less a natural fit than the same thing in Django.)</em></p>

<p>The problem is that you can&#8217;t just decorate the method in your class using <a href="http://bottle.paws.de/docs/dev/api.html#routing"><code>bottle.route</code></a> because if you use that decorator on a method in a class you are telling Bottle to use the method before it has been bound to an instance of that class.</p>

<p>So although I wish it did, the following example will not work:</p>

<pre><code>import bottle

class ViewClass(object):
    @bottle.route("/")
    def home_view(self):
        return "My home page."

obj = ViewClass()
bottle.run()
</code></pre>

<p>Running that will lead to errors about not enough arguments passed to the view method of your <code>ViewClass</code> instance.</p>

<p>Instead you need to register the route right after the object is created. This can be done in <a href="http://docs.python.org/reference/datamodel.html#object.__new__">the class&#8217;s <code>__new__</code> method</a>:</p>

<pre><code>import bottle

class ViewClass(object):
    def __new__(cls, *args, **kwargs):
        obj = super(ViewClass, cls).__new__(cls, *args, **kwargs)
        bottle.route("/")(obj.home_view)
        return obj

    def home_view(self):
        return "My home page."

obj = ViewClass()
bottle.run()
</code></pre>

<p>It works. It isn&#8217;t that pretty. You could achieve exactly the same thing by explicitly passing the <code>obj.home_view</code> method to <code>bottle.route</code> <em>after</em> the instance is created. The advantage to doing this in the <code>__new__</code> method is it will happen automatically whenever <code>ViewClass</code> is instantiated.</p>

<p>And if you go down this path then <a href="http://bottle.paws.de/docs/dev/tutorial.html#accessing-request-data">you should be aware of threads</a>. Hey! Nice threads! Also I have a cold.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/12/class-based-views-for-bottle/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running Django on Mac</title>
		<link>http://reliablybroken.com/b/2010/09/running-django-on-mac/</link>
		<comments>http://reliablybroken.com/b/2010/09/running-django-on-mac/#comments</comments>
		<pubDate>Wed, 29 Sep 2010 22:17:11 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[postgres]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=556</guid>
		<description><![CDATA[These are semi-detailed steps for installing all the bits to host a Django application on Mac OS X. Tested on 10.5, should work perfectly on 10.6. Use MacPorts: relatively easy to install and the best thing is everything is contained in a directory that you can be confident won&#8217;t eff up Apple&#8217;s stuff and won&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>These are semi-detailed steps for installing all the bits to host a <a href="http://www.djangoproject.com">Django</a> application on <a href="http://www.apple.com/macosx/">Mac OS X</a>. Tested on 10.5, should work perfectly on 10.6.</p>

<p>Use <a href="http://www.macports.org/">MacPorts</a>: relatively easy to install and the best thing is everything is contained in a directory that you can be confident won&#8217;t eff up Apple&#8217;s stuff and won&#8217;t be effed up by Apple&#8217;s stuff.</p>

<h2>Install Xcode</h2>

<p>You need the compiler and bits that are installed with Xcode. If you can&#8217;t find your Mac install discs (Xcode is included with every new Mac but not installed) you can <a href="http://developer.apple.com/technology/xcode.html">download it from Apple&#8217;s developer website</a>. Registration is required but is free.</p>

<p>The current version of Xcode is easy to find, while older versions are available in the downloads section under &#8220;Developer Tools&#8221;. Xcode version 3.1.4 is the last version that will work for Mac OS X 10.5 systems.</p>

<h2>Install MacPorts</h2>

<p>MacPorts have a nice pkg installer. You can also build it from source.</p>

<pre><code>curl -O http://distfiles.macports.org/MacPorts/MacPorts-1.9.1-10.5-Leopard.dmg
hdiutil attach MacPorts-1.9.1-10.5-Leopard.dmg
sudo installer -pkg /Volumes/MacPorts-1.9.1/MacPorts-1.9.1.pkg -target /
hdiutil detach /Volumes/MacPorts-1.9.1
</code></pre>

<p>If for some reason MacPorts cannot fetch updates you may need to <a href="http://reliablybroken.com/b/2010/03/using-macports-behind-a-firewall/">pull updates by hand</a>.</p>

<p>Check your $PATH after installing ports to make sure <code>/opt/local/bin</code> is in there. If it isn&#8217;t your can do <code>export PATH=/opt/local/bin:/opt/local/sbin:${PATH}</code> to fix things, and even add taht line to <code>~/.profile</code> so that bash picks it up every time (assuming you haven&#8217;t switched your shell).</p>

<h2>Install software</h2>

<p>The <code>port</code> command is used to manipulate the MacPorts installation. Use it to build and install the various bits we need. This takes a while, especially on old PowerPC machines. Make it more exciting by adding the <code>--verbose</code> flag. Exciting!</p>

<pre><code>sudo port install python26
sudo port install apache2
sudo port install mysql5-server
sudo port install mod_python26
sudo port install py26-mysql
sudo port install py26-django
sudo port install py26-south
</code></pre>

<p>And if you want to hook Django into a network directory then you almost certainly want to use LDAP.</p>

<pre><code>sudo port install py26-ldap
</code></pre>

<p>Cool kids these days say use <a href="http://docs.djangoproject.com/en/dev/howto/deployment/modwsgi/">mod_wsgi</a> instead of <a href="http://docs.djangoproject.com/en/dev/howto/deployment/modpython/">mod_python</a> for hosting Python applications with Apache, but I am not cool (and on 20 September 2010 I couldn&#8217;t persuade mod_wsgi to build from MacPorts on a clean installation).</p>

<h2>Configuring and starting MySQL</h2>

<p><em>UPDATED: <a href="http://reliablybroken.com/b/2010/09/running-django-on-mac/comment-page-1/#comment-1458">commenter matea</a> pointed to <a href="http://www.jasonrowland.com/2009/10/install-mysql5-on-snow-leopard-using-macports/">Jason Rowland&#8217;s MySQL on Mac</a> posting that includes steps to secure a default installation, so I&#8217;ve updated this section with the appropriate steps.</em></p>

<p>I always seem to be the only person who cares about non-English visitors&#8230; anyway, so I want to have <a href="http://www.mysql.com">MySQL</a> use UTF8 for everything. Edit the configuration so it does. As root, create a configuration at <code>/opt/local/var/db/mysql5/my.cnf</code> with these lines:</p>

<pre><code>[mysqld]
init-connect = 'SET NAMES utf8'
character-set-server = utf8
collation-server = utf8_general_ci
skip-networking

[mysql]
default-character-set = utf8
</code></pre>

<p>One thing about the line <code>skip-networking</code> in the configuration file is that it means MySQL will not listen to <strong>any</strong> network clients, including connections to <code>127.0.0.1</code>. Instead clients should connect to <code>localhost</code> or they should specify the path to the socket that MySQL uses for communication. If your MySQL &#8220;client&#8221; is a Django instance running on the same host then that should not be a problem.</p>

<p>Now initialize the database and start the server. (The use of <code>-w</code> in the second line tells launchctl to have the database daemon start at boot. If you don&#8217;t want to have MySQL running at boot use <code>-F</code> to <strong>force</strong> start just this one time instead of every time.)</p>

<pre><code>sudo -u mysql /opt/local/bin/mysql_install_db5
sudo launchctl load -w /Library/LaunchDaemons/org.macports.mysql5.plist
</code></pre>

<p>And let&#8217;s check that the server is up and configured right.</p>

<pre><code>/opt/local/bin/mysql5 -e "SHOW variables LIKE '%char%'"
</code></pre>

<p>You should see a table showing that the character set for the client and server is set to utf8.</p>

<p>Now run the secure installation script for MySQL. This will ask you to set a password for MySQL&#8217;s root account (the administrator) and ask whether to remove the test database and anonymous user access (you should do both):</p>

<pre><code>/opt/local/bin/mysql_secure_installation5
</code></pre>

<p>Thaz better.</p>

<h2>Configuring Postgresql instead of MySQL</h2>

<p>If you want to use <a href="http://www.postgresql.org">Postgres</a> instead of MySQL then you need a couple different packages out of ports.</p>

<pre><code>sudo port install postgresql84-server
sudo port install py26-psycopg2
</code></pre>

<p>Did you know Apple&#8217;s management tools use Postgres? Is true.</p>

<h2>Configuring Apache to serve a Django project</h2>

<p>Let&#8217;s suppose your Django project lives under <code>/Library/WebServer/example.com/myproj</code>, and the project&#8217;s settings file is <code>/Library/WebServer/example.com/myproj/settings.py</code>. Here&#8217;s how to configure Apache with mod_python to serve your project.</p>

<p>Create a separate site configuration for Apache in <code>/Library/WebServer/example.com/site.conf</code>.</p>

<pre><code>&lt;Location "/"&gt;
    SetHandler python-program
    PythonHandler django.core.handlers.modpython
    SetEnv DJANGO_SETTINGS_MODULE myproj.settings
    PythonOption django.root /
    PythonDebug On
    PythonPath "['/Library/WebServer/example.com'] + sys.path"
&lt;/Location&gt;

&lt;Directory /Library/WebServer/example.com&gt;
    Order deny,allow
    Allow from all
&lt;/Directory&gt;
</code></pre>

<p>Of course once everything is hunky dory you will go back and edit the site configuration so that <code>PythonDebug Off</code>.</p>

<p>And finally tell Apache to use mod_python and read the site configuration. Edit <code>/opt/local/apache2/conf/httpd.conf</code> and add a line at the end of the modules like:</p>

<pre><code>LoadModule python_module modules/mod_python.so
</code></pre>

<p>And then a line like:</p>

<pre><code>Include /Library/WebServer/example.com/site.conf
</code></pre>

<p>Now fire up Apache:</p>

<pre><code>sudo launchctl load -w /Library/LaunchDaemons/org.macports.apache2.plist
</code></pre>

<p>MacPorts has a convenient shortcut for this:</p>

<pre><code>sudo port load apache2
</code></pre>

<p>You also want to save Apache a little grief by pre-compiling the Python source files for the project:</p>

<pre><code>/opt/local/bin/python2.6 -m compileall /Library/WebServer/example.com
</code></pre>

<p>Hope this helps.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/09/running-django-on-mac/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Bottle&#8217;s view decorator and default variables</title>
		<link>http://reliablybroken.com/b/2010/08/curried-bottle-views/</link>
		<comments>http://reliablybroken.com/b/2010/08/curried-bottle-views/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 10:57:46 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[bottle]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=525</guid>
		<description><![CDATA[Bottle&#8216;s @view decorator provides a simple way to designate a template to render an HTML page. Your view function just has to return a dictionary, and its contents can be accessed from the template using the '{{ name }}' syntax. The @view decorator can also take keyword arguments. These are treated as default template variables [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bottle.paws.de/">Bottle</a>&#8216;s <a href="http://bottle.paws.de/docs/0.8/api.html#bottle.view"><code>@view</code> decorator</a> provides a simple way to designate a template to render an HTML page. Your view function just has to return a dictionary, and its contents can be accessed from the template using the <code>'{{ name }}'</code> syntax.</p>

<p>The <code>@view</code> decorator can also take keyword arguments. These are treated as default template variables &#8211; if the dictionary returned by your view function doesn&#8217;t have a key for one of the keyword arguments then the template will use the value passed into the decorator, like so:</p>

<pre><code>from bottle import view

@view('default.html', author='David Buxton')
def home():
    return {'title': 'Home page'}
</code></pre>

<p>That would render any instance of <code>'{{ author }}'</code> as <code>'David Buxton'</code>. And then you can have another view function that overrides the keywords by returning a different value in the dictionary:</p>

<pre><code>from bottle import view

@view('default.html', author='David Buxton')
def music():
    return {'title': 'Thalassocracy', 'author': 'Frank Black'}
</code></pre>

<p>And at that point I wonder what is the advantage of using keyword arguments with <code>@view</code>: you have to decorate each function separately, and if you want to override a keyword in your return dictionary then it would be easier not to specify the keyword in the first place.</p>

<p>Thus the real point of using keywords with the <code>@view</code> function is only apparent if you curry the <code>@view</code> decorator with keywords first so that you can re-use the curried decorator and avoid repeating yourself.</p>

<p><em>Someday I will re-write the previous sentence. Until then, sorry.</em></p>

<p>Instead of passing a default author each time as in the examples above, let&#8217;s make a new <code>@view</code> decorator (using Python&#8217;s <a href="http://docs.python.org/library/functools.html">functools module</a>) and then use that on each view function:</p>

<pre><code>import functools
from bottle import view

view = functools.partial(view, author='David Buxton')

@view('default.html')
def home():
    return {'title': 'Home page'}

@view('default.html')
def music():
    return {'title': 'Thalassocracy', 'author': 'Frank Black'}
</code></pre>

<p>The new decorator means you get the default keyword arguments wherever you use <code>@view</code> while permitting any function to override those defaults in the dictionary it returns.</p>

<p>And if you wanted to get really lazy you could even pass in a template name when wrapping the decorator with <code>functools.partial</code>, however you would not be able to use your wrapped decorator to change the template name because it is a positional argument (like what <a href="http://docs.python.org/library/functools.html#functools.partial">it explains here in the functools documentation</a>). You would also have to call the decorator with no arguments like <code>'@defaultview()'</code>. So forget I mentioned it.</p>

<p>I&#8217;m not saying you are lazy.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/08/curried-bottle-views/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Django-style routing for Bottle</title>
		<link>http://reliablybroken.com/b/2010/07/django-style-routing-for-bottle/</link>
		<comments>http://reliablybroken.com/b/2010/07/django-style-routing-for-bottle/#comments</comments>
		<pubDate>Mon, 26 Jul 2010 21:57:40 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[bottle]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=510</guid>
		<description><![CDATA[Bottle provides the @route decorator to associate URL paths with view functions. This is very convenient, but if you are a Django-reject like me then you may prefer having all your URLs defined in one place, the advantage being it is easy to see at a glance all the different URLs your application will match. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bottle.paws.de/">Bottle</a> provides the <a href="http://bottle.paws.de/docs/0.8/api.html#bottle.route"><code>@route</code> decorator</a> to associate URL paths with view functions. This is very convenient, but if you are a <a href="http://www.djangoproject.com/">Django</a>-reject like me then you may prefer having all your URLs defined in one place, the advantage being it is easy to see at a glance <a href="http://docs.djangoproject.com/en/1.2/topics/http/urls/#example">all the different URLs your application will match</a>.</p>

<p><em>Updated: I have re-written this post and the example to make it simpler following Marcel Hellkamp&#8217;s comments (Marcel is the primary author of Bottle). My original example was needlessly complicated.</em></p>

<p>It is possible to have <a href="http://docs.djangoproject.com/en/dev/topics/http/urls/">a Django-style urlpatterns stanza</a> with a Bottle app. Here&#8217;s how it can work:</p>

<pre><code>from bottle import route

# Assuming your *_page view functions are defined above somewhere
urlpatterns = (
    # (path, func, name)
    ('/', home_page, 'home'),
    ('/about', about_page, 'about'),
    ('/contact', contact_page, 'contact'),
)

for path, func, name in urlpatterns:
    route(path, name=name)(func)
</code></pre>

<p>Here we run through a list where each item is a triple of URL path, view function and a name for the route. For each we simply call the <code>route</code> method and then invoke it with the function object. Not as flexible as using the decorator on a function (because the <code>@route</code> decorator can take additional keyword arguments) but at least you can have all the routes in one place at the end of the module.</p>

<p>Then again if you have so many routes that you need to keep them in a pretty list you probably aren&#8217;t writing the simple application that Bottle was intended for.</p>

<p>(This was tested with Bottle&#8217;s 0.8 and 0.9-dev branches.)</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/07/django-style-routing-for-bottle/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>More Python features that I really like</title>
		<link>http://reliablybroken.com/b/2010/05/more-python-features-that-i-really-like/</link>
		<comments>http://reliablybroken.com/b/2010/05/more-python-features-that-i-really-like/#comments</comments>
		<pubDate>Fri, 28 May 2010 15:00:00 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Ben Dodd]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=446</guid>
		<description><![CDATA[Another thing that makes using Python pleasing is decorators. A decorator is a wrapper for a function (or method) that takes a function (or method) as an argument and returns a new function (or&#8230;) which is then bound to the name for the original function. The newly-decorated function can then do things like checking the [...]]]></description>
			<content:encoded><![CDATA[<p>Another thing that makes using <a href="http://www.python.org">Python</a> pleasing is decorators. <a href="http://docs.python.org/reference/compound_stmts.html#function">A decorator is a wrapper for a function</a> (or method) that takes a function (or method) as an argument and returns a new function (or&#8230;) which is then bound to the name for the original function.</p>

<p>The newly-decorated function can then do things like checking the called arguments before invoking the original un-decorated function.</p>

<p><a href="http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.decorators.user_passes_test">Django provides decorators for authentication</a> so that you can wrap a view function with a check for client credentials before deciding whether to return the original response or a deny access.</p>

<p>In this manner Django&#8217;s authentication decorators encourage orthogonal code: the logic for displaying a view is separated from the logic for deciding whether you should be permitted to see the view&#8217;s output. By keeping them separate, it becomes simpler to re-use the authentication logic and apply it to other views.</p>

<p>Suppose you have a view that accepts <a href="http://docs.djangoproject.com/en/dev/ref/request-response/">a Django request object</a> and checks whether the user is signed in:</p>

<pre><code>def administration_page(request):
    if request.user.is_authenticated():
        return HttpResponse("Welcome, dear user.")
    else:
        return HttpResponseRedirect("/signin/")
</code></pre>

<p>With a decorator you can simplify and clarify things:</p>

<pre><code>@login_required
def administration_page(request):
    return HttpResponse("Welcome, dear user.")
</code></pre>

<p>For older versions of Python (pre 2.4) <a href="http://docs.python.org/whatsnew/2.4.html#pep-318-decorators-for-functions-and-methods">which don&#8217;t understand the <code>@</code> operator</a> one must explicitly decorate the view function like so:</p>

<pre><code>def administration_page(request):
    return HttpResponse("Welcome, dear administrator.")

administration_page = login_required(administration_page)
</code></pre>

<p>Note in the example that the original <code>administration_page</code> function is passed to the decorator. The <code>@</code> syntax in the first example makes that implicit but the two are equivalent.</p>

<p>The implementation of a decorator is interesting. It takes the function itself as an argument and returns a new function which does the actual checking. Here is how the decorator used above might do its stuff:</p>

<pre><code>def login_required(view_function):
    def decorated_function(request):
        if request.user.is_authenticated():
            return view_function(request)
        else:
            return HttpResponseRedirect("/signin/")

    return decorated_function
</code></pre>

<p><em>The actual <a href="http://code.djangoproject.com/browser/django/tags/releases/1.2.1/django/contrib/auth/decorators.py">implementation of Django&#8217;s <code>login_required</code> decorator</a> is considerably less idiotic. Python&#8217;s <a href="http://docs.python.org/library/functools.html">functools module</a> has helpers for writing well-behaved decorators.</em></p>

<p>Because functions in Python are themselves objects the decorator can accept a function reference, construct a new function that checks for authentication and then return a reference to that new function.</p>

<p>Simples!</p>

<p>(Simples gets less simples when you want to write a decorator that accepts configuration arguments because you then need either another layer of nested function definitions or a class whose instances can be called directly, but I&#8217;m going to ignore you for a bit and <em>wow is that Concorde&#8230;?</em>)</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/05/more-python-features-that-i-really-like/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Split a file on any character in Python</title>
		<link>http://reliablybroken.com/b/2010/04/split-a-file-on-any-character-in-python/</link>
		<comments>http://reliablybroken.com/b/2010/04/split-a-file-on-any-character-in-python/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 10:38:12 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=437</guid>
		<description><![CDATA[I need to split a big text file on a certain character. I expect I am being thick about this, but split doesn&#8217;t quite do what I want because it includes the matching line, whereas I want to split right on the matching character. My Python answer: def readlines(filename, endings, chunksize=4096): """Returns a generator that [...]]]></description>
			<content:encoded><![CDATA[<p>I need to split a big text file on a certain character. I expect I am being thick about this, but <a href="http://developer.apple.com/Mac/library/documentation/Darwin/Reference/ManPages/man1/split.1.html"><code>split</code></a> doesn&#8217;t quite do what I want because it includes the matching line, whereas I want to split right on the matching character.</p>

<p>My Python answer:</p>

<pre><code>def readlines(filename, endings, chunksize=4096):
    """Returns a generator that splits on lines in a file with the given
    line-ending.
    """
    line = ''
    while True:        
        buf = filename.read(chunksize)
        if not buf:
            yield line
            break

        line = line + buf

        while endings in line:
            idx = line.index(endings) + len(endings)
            yield line[:idx]
            line = line[idx:]

if __name__ == "__main__":
    import sys, os

    FORMFEED = chr(12) # ASCII 12
    basename = os.path.basename(sys.argv[1])
    for num, data in enumerate(readlines(open(sys.argv[1]), endings=FORMFEED)):
        filename = basename + '-' + str(num)
        open(filename, 'wb').write(data)
</code></pre>

<p>This is also useful when reading data exported from some old-fashioned Mac application like <a href="http://www.filemaker.com/support/downloads/downloads_prev_versions.html">Filemaker 5</a> where the line-endings are ASCII 13 not ASCII 10.</p>

<p>This post was inspired by <a href="http://www-01.ibm.com/software/lotus/products/notes/">Lotus Notes</a> version 8.5, which is so advanced that to save a message in a file on disk you have to export it as structured text. And if you want to save a whole bunch of messages as individual files you must forget that <a href="http://www.mactech.com/articles/mactech/Vol.10/10.06/DragAndDrop/index.html">drag-and-drop was introduced with System 7</a>, that would be too obvious.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/04/split-a-file-on-any-character-in-python/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Django AdminForm objects and templates</title>
		<link>http://reliablybroken.com/b/2010/04/django-adminform-objects-and-templates/</link>
		<comments>http://reliablybroken.com/b/2010/04/django-adminform-objects-and-templates/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 21:21:54 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=425</guid>
		<description><![CDATA[I can&#8217;t find documentation for the context of a Django admin template. In particular, where is the form and how does one access the fields? This post describes the template context for a generic admin model for Django 1.1. Django uses an instance of ModelAdmin (defined in django.contrib.admin.options) to handle the request for a model [...]]]></description>
			<content:encoded><![CDATA[<p>I can&#8217;t find documentation for the context of a Django admin template. In particular, where is the form and how does one access the fields? This post describes the template context for a generic admin model for <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1">Django 1.1</a>.</p>

<p>Django uses an instance of <code>ModelAdmin</code> (defined in <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/options.py#L175"><code>django.contrib.admin.options</code></a>) to handle the request for a model object add / change view in the admin site. <code>ModelAdmin.add_view</code> and <code>ModelAdmin.change_view</code> are responsible for populating the template context when rendering the add object and change object pages respectively.</p>

<p>Here are the keys common to add and change views:</p>

<ul>
<li><strong>title</strong>, &#8216;Add &#8216; or &#8216;Change &#8216; + your model class&#8217; <code>_meta.verbose_name</code></li>
<li><strong>adminform</strong> is an instance of <code>AdminForm</code></li>
<li><strong>is_popup</strong>, a boolean which is true when <code>_popup</code> is passed as a request parameter</li>
<li><strong>media</strong> is an instance of <a href="http://docs.djangoproject.com/en/dev/topics/forms/media/"><code>django.forms.Media</code></a></li>
<li><strong>inline_admin_formsets</strong> is a list of <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L102"><code>InlineAdminFormSet</code></a> objects</li>
<li><strong>errors</strong> is an instance of <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L198"><code>AdminErrorList</code></a></li>
<li><strong>root_path</strong> is the <code>root_path</code> attribute of the <code>AdminSite</code> object</li>
<li><strong>app_label</strong> is your model class&#8217; <code>_meta.app_label</code> attribute</li>
</ul>

<p>The way that Django renders a form in the admin view is to iterate over the <code>adminform</code> instance and then iterate over each <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L50"><code>FieldSet</code></a> which in turn yield <a href="http://code.djangoproject.com/browser/django/tags/releases/1.1/django/contrib/admin/helpers.py#L82"><code>AdminField</code></a> instances. All I want to do is layout the form fields, ignoring the fieldset groupings which may or may not be defined in the model&#8217;s <code>ModelAdmin.fieldset</code> attribute.</p>

<p>This turns out to be easy once you know how. The regular form is an attribute of the <code>adminform</code> object. So if your model has a field named &#8220;<code>king_of_pop</code>&#8221; you can refer to the form field in your template like so:</p>

<pre><code>{{ adminform.form.king_of_pop.label_tag }}: {{ adminform.form.king_of_pop }}
</code></pre>

<p>Or if you want to save your finger tips you can use the <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/#with"><code>with</code> template tag</a>:</p>

<pre><code>{% with adminform.form as f %}
{{ f.king_of_pop.label_tag }}: {{ f.king_of_pop }}
{% endwith %}
</code></pre>

<p>Delving through the Django source while I tried to understand all of this I was struck by how <a href="http://docs.python.org/reference/datamodel.html#emulating-container-types">Python defines hook functions for iteration and accessing attributes</a>. Half of Python&#8217;s attraction is in how easy it is from the program author&#8217;s point of view to treat objects as built-in types like lists, dicts, etc.; the other half is the responsibility of the author of a Python module to encourage that same ease of use by implementing the related iteration protocols. It is harder to write a good Python module than it is to write a good Python program that uses a good module.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/04/django-adminform-objects-and-templates/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using MacPorts behind a firewall</title>
		<link>http://reliablybroken.com/b/2010/03/using-macports-behind-a-firewall/</link>
		<comments>http://reliablybroken.com/b/2010/03/using-macports-behind-a-firewall/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 11:37:39 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[macports]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=420</guid>
		<description><![CDATA[I failed to persuade MySQLdb to build on a Mac OS X Server 10.5.8 install using the system Python + MySQL installation. So I turned to MacPorts where I know I can get Django + all the bits working without much hassle (but with much patience). The next problem was that MacPorts couldn&#8217;t update because [...]]]></description>
			<content:encoded><![CDATA[<p>I failed to persuade <a href="http://mysql-python.sourceforge.net/MySQLdb.html">MySQLdb</a> to build on a <a href="http://www.apple.com/server/macosx/">Mac OS X Server 10.5.8</a> install using the system <a href="http://www.python.org/">Python</a> + <a href="http://www.mysql.com/">MySQL</a> installation. So I turned to <a href="http://www.macports.org/">MacPorts</a> where I know I can get <a href="http://www.djangoproject.com/">Django</a> + all the bits working without much hassle (but with much patience).</p>

<p>The next problem was that MacPorts couldn&#8217;t update because <a href="http://samba.anu.edu.au/rsync/">rsync</a> was blocked by the corporate access policy. Fortunately plain HTTP is permitted outbound. Here&#8217;s how to use a local ports tree.</p>

<p>Install MacPorts using the disk image for 10.5.</p>

<pre><code>curl -O http://distfiles.macports.org/MacPorts/MacPorts-1.8.2-10.5-Leopard.dmg
hdiutil attach MacPorts-1.8.2-10.5-Leopard.dmg
sudo installer -pkg /Volumes/MacPorts-1.8.2/MacPorts-1.8.2.pkg -target /
hdiutil detach /Volumes/MacPorts-1.8.2
</code></pre>

<p>If the MacPorts install directories are not in your $PATH environment, you can add them to your <code>.profile</code>. This change will not take effect until you start a new terminal session.</p>

<pre><code>cat &gt;&gt; ~/.profile &lt;&lt;EOF
PATH=/opt/local/bin:/opt/local/sbin:${PATH}
MANPATH=/opt/local/share/man:${MANPATH}
EOF
</code></pre>

<p>After you have installed MacPorts, create a directory for the ports tree and check it out using <a href="http://subversion.tigris.org/">Subversion</a>.</p>

<pre><code>sudo mkdir -p /opt/local/var/macports/sources/svn.macports.org/trunk/dports
cd /opt/local/var/macports/sources/svn.macports.org/trunk/dports
sudo svn co http://svn.macports.org/repository/macports/trunk/dports/ .
</code></pre>

<p>N.B. In the last line beginning <code>svn co ...</code> the trailing directory separator is significant!</p>

<p>Now tell MacPorts to use the local checkout rather than rsync. Edit <code>/opt/local/etc/macports/sources.conf</code> and add a new line to the end with the path to the ports tree, then comment out the previous line that uses rsync. Here are the last lines from my configuration:</p>

<pre><code>#rsync://rsync.macports.org/release/ports/ [default]
file:///opt/local/var/macports/sources/svn.macports.org/trunk/dports/ [default]
</code></pre>

<p>Finally you must create an index for the tree (otherwise you will see messages saying &#8220;Warning: No index(es) found!&#8221;).</p>

<pre><code>cd /opt/local/var/macports/sources/svn.macports.org/trunk/dports
sudo portindex
</code></pre>

<p>Now go do great things.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/03/using-macports-behind-a-firewall/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>ModelForms good for importing too</title>
		<link>http://reliablybroken.com/b/2010/01/modelforms-good-for-importing-too/</link>
		<comments>http://reliablybroken.com/b/2010/01/modelforms-good-for-importing-too/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 20:36:25 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=395</guid>
		<description><![CDATA[If you have exported data from one database in plain text format and you want to import it to Django, you should use a ModelForm class to do a lot of the heavy lifting for you. A suitable ModelForm for your Django model will consume each row and do the conversion of each field to [...]]]></description>
			<content:encoded><![CDATA[<p>If you have exported data from one database in plain text format and you want to import it to <a href="http://www.djangoproject.com">Django</a>, you should use a <a href="http://docs.djangoproject.com/en/dev/topics/forms/modelforms/"><code>ModelForm</code> class</a> to do a lot of the heavy lifting for you.</p>

<p>A suitable <code>ModelForm</code> for your Django model will consume each row and do the conversion of each field to an appropriate Python type. Much simpler than explicitly converting each value yourself before creating a new model instance.</p>

<p>Suppose you have a model for an address book entry and its associated <code>ModelForm</code> (this works for Django 1.1):</p>

<pre><code># myapp/models.py
from django.db import models
from django import forms

class Contact(models.Model):
    first_name = models.CharField(max_length=100)
    second_name = models.CharField(max_length=100)
    telephone = models.CharField(max_length=50, blank=True)
    email = models.EmailField(blank=True)

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
</code></pre>

<p>Here&#8217;s a script to run through a comma-separated list of contacts where each line looks something like &#8220;Smits, Jimmy, jimmy@example.com, 555-1234&#8243;:</p>

<pre><code>from myapp.models import ContactForm

# Map columns to fields, adjusting the order as necessary
column_map = (
    'second_name',
    'first_name',
    'email',
    'telephone',
)

for line in open('tab-separated-data.txt'):
    row = dict(zip(column_map, (field.strip() for field in line.split(','))))
    form_obj = ContactForm(row)
    try:
        form_obj.save()
    except ValueError:
        for k, v in form_obj.errors.items():
            print k, row[k], ', '.join(map(unicode, v))
</code></pre>

<p>If a line doesn&#8217;t validate the script prints the validation errors and moves to the next line. If your data has columns you want to ignore then just name them in the <code>column_map</code> &#8211; the form class will ignore extra keys in the dictionary.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/01/modelforms-good-for-importing-too/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Notes on Radmind&#8217;s checksum</title>
		<link>http://reliablybroken.com/b/2010/01/radminds-checksum/</link>
		<comments>http://reliablybroken.com/b/2010/01/radminds-checksum/#comments</comments>
		<pubDate>Fri, 01 Jan 2010 12:04:05 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[radmind]]></category>
		<category><![CDATA[watchedinstall]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=376</guid>
		<description><![CDATA[It would be nice to do a pure-Python implementation of Radmind&#8216;s fsdiff output for watchedinstall, which consists of several white-space separated fields describing the filename&#8217;s attributes and an optional checksum for the file. These are notes on how Radmind generates checksums for files on Mac OS X. The fsdiff format is documented, however for files [...]]]></description>
			<content:encoded><![CDATA[<p>It would be nice to do a <a href="http://www.python.org/">pure-Python</a> implementation of <a href="http://rsug.itd.umich.edu/software/radmind/">Radmind</a>&#8216;s fsdiff output for <a href="http://bitbucket.org/ptone/watchedinstall/">watchedinstall</a>, which consists of several white-space separated fields describing the filename&#8217;s attributes and an optional checksum for the file.</p>

<p>These are notes on how Radmind generates checksums for files on <a href="http://www.apple.com/macosx/">Mac OS X</a>.</p>

<p>The <a href="http://linux.die.net/man/1/fsdiff">fsdiff format is documented</a>, however for files with Mac Finder info or a resource fork the checksum is for an <a href="http://users.phg-online.de/tk/netatalk/doc/Apple/v2/AppleSingle_AppleDouble.pdf">AppleSingle</a>-encoded representation of the file, which means a Python implementation needs to produce an equivalent AppleSingle-encoded byte stream for the file. Bummer.</p>

<p>Python 2.6 on Mac OS X includes a <a href="http://www.python.org/doc/2.6.2/library/undoc.html#module-applesingle">(deprecated) applesingle module</a> that can read the format but cannot write it (and the module has been removed for Python 3). Therefore a pure Python implementation of Radmind&#8217;s checksum has to implement a compatible AppleSingle encoding routine too.</p>

<p>Radmind&#8217;s fsdiff command is written in C, which I can just about get the gist of, but I am missing something because my attempts at emulating Radmind&#8217;s checksums are wrong.</p>

<p>The meat of Radmind&#8217;s checksum is the <a href="http://radmind.cvs.sourceforge.net/viewvc/radmind/radmind/cksum.c"><code>do_acksum()</code> function in <code>cksum.c</code></a>. The algorithm appears to be as follows:</p>

<ol>
<li>Initialize a digest using the default cipher (<a href="http://www.openssl.org/docs/crypto/md5.html">MD5</a> I think).</li>
<li>Add the AppleSingle header, consisting of a magic number and version number and some padding.</li>
<li>Add the AppleSingle entry table, which has 3 entries for the Finder info, the resource fork info and the data fork info (in that order). Each entry is 12 bytes &#8211; an unsigned long for the entry type, an unsigned long for an offset into the file where the data will start and an unsigned long for the data length.</li>
<li>Add the Finder info data.</li>
<li>Add the resource for data.</li>
<li>Add the data fork data.</li>
<li>Return a base64 encoded version of the final digest.</li>
</ol>

<p>Because the entry table in the AppleSingle header specifies data offsets and lengths you need to know the size of the Finder info data (always 32 bytes) and the size of the resource fork and the size of the data fork before you pass that data to the digest function.</p>

<p>So a working Python implementation needs to know the size of the resource fork and data fork before feeding that same data to the digest. It seems to me that this requirement might imply huge memory allocations while slurping file data &#8211; my wrong attempt tried counting bytes and later feeding the same data to the digest in manageable chunks.</p>

<p>Anyway&#8230;</p>

<p>Advice much appreciated. The workaround is to leave it to fsdiff to generate the checksum and parse the value from the output.</p>

<p>David</p>

<p>P.S. I still intend running <a href="http://www.aux-penelope.com/">A/UX 3.0.1</a> on my Centris 660av one day.</p>

<p>Update: using my eyes and brains and the <code>fsdiff -V</code> command I was able to read the fsdiff man page and deduce the preferred checksum cipher is actually sha1. My code is still wrong.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2010/01/radminds-checksum/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Context managers</title>
		<link>http://reliablybroken.com/b/2009/12/context-managers/</link>
		<comments>http://reliablybroken.com/b/2009/12/context-managers/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 15:10:45 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[with]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=367</guid>
		<description><![CDATA[I was re-writing the exellent watchedinstall tool and needed to simplify a particularly gnarly chunk of code that required three sub-proceses to be started and then killed after invoking another process. It occurred to me I could make these into context managers. Previously the code was something like&#8230; start(program1) try: start(program2) except: stop(program1) raise try: [...]]]></description>
			<content:encoded><![CDATA[<p>I was re-writing the exellent <a href="http://bitbucket.org/ptone/watchedinstall/">watchedinstall</a> tool and needed to simplify a particularly gnarly chunk of code that required three sub-proceses to be started and then killed after invoking another process. It occurred to me I could make these into context managers.</p>

<p>Previously the code was something like&#8230;</p>

<pre><code>start(program1)
try:
    start(program2)
except:
    stop(program1)
    raise

try:
    start(program3)
except:
    stop(program2)
    stop(program1)
    raise

try:
    mainprogram()
finally:
    stop(program3)
    stop(program2)
    stop(program1)
</code></pre>

<p>Of course that could have been written with nested try / except / else / finally blocks as well, which I did start with but found not much shorter while almost incomprehensible.</p>

<p><a href="http://docs.python.org/library/stdtypes.html#typecontextmanager">With context managers</a> the whole thing was written as&#8230;</p>

<pre><code># from __future__ import with_statement, Python 2.5

with start(program1):
    with start(program2):
        with start(program3):
            mainprogram()
</code></pre>

<p>So much more comprehensible! Here&#8217;s the implementation of the context manager (using the <code>contextlib.contextmanager</code> decorator for a triple word score):</p>

<pre><code>import contextlib
import os
import signal
import subprocess


@contextlib.contextmanager
def start(program_args):
    prog = subprocess.Popen(program_args)
    if prog.poll(): # Anything other than None or 0 is BAD
        raise subprocess.CalledProcessError(prog.returncode, program_args[0])

    try:
        yield
    finally:
        if prog.poll() is None:
            os.kill(prog.pid, signal.SIGTERM)
</code></pre>

<p>For bonus points I might have used <a href="http://docs.python.org/library/contextlib.html"><code>contexlib.nested()</code></a> to put the three <code>start()</code> calls on one line but then what would I do for the rest of the day?</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/12/context-managers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I am very bad at writing tests</title>
		<link>http://reliablybroken.com/b/2009/11/i-am-very-bad-at-writing-tests/</link>
		<comments>http://reliablybroken.com/b/2009/11/i-am-very-bad-at-writing-tests/#comments</comments>
		<pubDate>Sun, 22 Nov 2009 08:00:29 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=280</guid>
		<description><![CDATA[&#8230; but I think I might be getting a little better. At least these days when I am writing some script (almost certainly in Python) I start out by intending to write tests. I usually fail because I haven&#8217;t learnt to think in terms of writing code that can be easily tested. Mark Pilgrim&#8216;s Dive [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230; but I <em>think</em> I might be getting a little better.</p>

<p>At least these days when I am writing some script (almost certainly in <a href="http://www.python.org/">Python</a>) I start out by intending to write tests. I usually fail because I haven&#8217;t learnt to think in terms of writing code that can be easily tested.</p>

<p><a href="http://diveintomark.org/">Mark Pilgrim</a>&#8216;s <a href="http://www.diveintopython.org/">Dive Into Python</a> has great stuff on how to approach a problem by <a href="http://diveintopython.org/unit_testing/stage_1.html">defining the tests first and gradually filling in the code</a> that satisfies the test suite. One day I may be able to work like that, until then I work by writing a concise docstring, then stubbing out the function. Once the function is in a state where it might actually return a meaningful result I can play with it in the Python interpreter and start adding useful <a href="http://docs.python.org/library/doctest.html">doctests</a> to the <a href="http://www.python.org/dev/peps/pep-0257/">docstring</a>.</p>

<p>What really helps is to break the logic out into tiny pieces where ideally each piece returns the result of transforming the input (which I think is known as a <a href="http://en.wikipedia.org/wiki/Functional_programming">functional approach</a>). By doing this I can have tests for most of the code and those functions that have a lot of conditional logic, those functions that are harder to write tests for, will at least be relying on sub-routines that are themselves well tested.</p>

<p>I can dream.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/11/i-am-very-bad-at-writing-tests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Crazy Acrobat installers love Python</title>
		<link>http://reliablybroken.com/b/2009/11/crazy-acrobat-installers-love-python/</link>
		<comments>http://reliablybroken.com/b/2009/11/crazy-acrobat-installers-love-python/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 22:06:02 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[hateful]]></category>
		<category><![CDATA[installer]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=331</guid>
		<description><![CDATA[Looking through the updaters for Adobe Acrobat 9 for Mac I came across a bunch of scripts written in Python. My favourte was called FindAndKill.py: #!/usr/bin/python """ Search for and kill app. """ import os, sys import commands import signal def main(): if len(sys.argv) != 2: print 'Missing or too many arguments.' print 'One argument [...]]]></description>
			<content:encoded><![CDATA[<p>Looking through the updaters for <a href="http://www.adobe.com/products/acrobatpro/">Adobe Acrobat</a> 9 for Mac I came across a bunch of scripts written in <a href="http://www.python.org">Python</a>. My favourte was called <code>FindAndKill.py</code>:</p>

<pre><code>#!/usr/bin/python
"""
    Search for and kill app. 
"""
import os, sys
import commands
import signal


def main():
    if len(sys.argv) != 2:
        print 'Missing or too many arguments.'
        print 'One argument and only one argument is required.'
        print 'Pass in the app name to find and kill (i.e. "Safari").'
        return 0

    psCmd = '/bin/ps -x -c | grep ' + sys.argv[1]
    st, output = commands.getstatusoutput( psCmd )

    if st == 0:
        appsToKill = output.split('\n')
        for app in appsToKill:
            parts = app.split()
            killCmd = 'kill -s 15 ' + parts[0]
            #print killCmd
            os.system( killCmd )

if __name__ == "__main__":
    main()
</code></pre>

<p>(You can <a href="http://www.adobe.com/support/downloads/detail.jsp?ftpID=4538">download the Acrobat 9.1.3 update</a> and find this script at <code>Acrobat 9 Pro Patch.app/Contents/Resources/FindAndKill.py</code>.)</p>

<p>Was the author not aware of the <code>killall</code> command for sending a kill signal to a named process? The <a href="http://www.manpagez.com/man/1/killall/"><code>killall</code> man page</a> says it appeared in <a href="http://www.freebsd.org/releases/2.1R/announce.html">FreeBSD 2.1, which was released in November 1995</a>. Adobe CS4 was <a href="http://www.adobe.com/aboutadobe/pressroom/pressreleases/200809/092308AdobeCS4Family.html">released about 14 years later</a>. How is it Adobe&#8217;s product managers approve these things for release?</p>

<p>What is particularly galling about Adobe&#8217;s Acrobat 9 updaters is that they seem to  re-implement so much of what the Apple installer application does, even down to their use of gzipped cpio archives for the payload.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/11/crazy-acrobat-installers-love-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Migrating a Filemaker database to Django</title>
		<link>http://reliablybroken.com/b/2009/11/migrating-a-filemaker-database-to-django/</link>
		<comments>http://reliablybroken.com/b/2009/11/migrating-a-filemaker-database-to-django/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 08:00:48 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[filemaker]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=320</guid>
		<description><![CDATA[At work we have several Filemaker Pro databases. I have been slowly working through these, converting them to Web-based applications using the Django framework. My primary motive is to replace an overly-complicated Filemaker setup running on four Macs with a single 2U rack-mounted server running Apache on FreeBSD. At some point in the process of [...]]]></description>
			<content:encoded><![CDATA[<p>At work we have several <a href="http://www.filemaker.com/">Filemaker Pro</a> databases. I have been slowly working through these, converting them to Web-based applications using <a href="http://www.djangoproject.com/">the Django framework</a>. My primary motive is to replace an overly-complicated Filemaker setup running on four Macs with a single 2U rack-mounted server running <a href="http://httpd.apache.org/">Apache</a> on <a href="http://www.freebsd.org/">FreeBSD</a>.</p>

<p>At some point in the process of re-writing each database for use with Django I have needed to convert all the records from Filemaker to Django. There exist good <a href="http://www.python.org/">Python</a> libraries for <a href="http://code.google.com/p/pyfilemaker/">talking to Filemaker</a> but they rely on the XML Web interface, meaning that you need Filemaker running and set to publish the database on the Web while you are running an import.</p>

<p>In my experience <a href="http://www.filemaker.com/support/technologies/xml">Filemaker&#8217;s built-in XML publishing interface</a> is too slow when you want to migrate tens of thousands of records. During development of a Django-based application I find I frequently need to re-import the records as the new database schema evolves &#8211; doing this by communicating with Filemaker is tedious when you want to re-import the data several times a day.</p>

<p>So my approach has been to export the data from Filemaker as XML using <a href="http://www.filemaker.com/help/html/import_export.16.30.html#1029660">Filemaker&#8217;s FMPXMLRESULT</a> format. The Filemaker databases at work are <em>old</em> (Filemaker 5.5) and perhaps things have improved in more recent versions but Filemaker 5/6 is a very poor XML citizen. When using the FMPDSORESULT format (which has been dropped from more recent versions) it will happily generate invalid XML all over the shop. The FMPXMLRESULT format is better but even then it will emit invalid XML if the original data happens to contain funky characters.</p>

<p>So here is <a href="http://reliablybroken.com/b/wp-content/uploads/2009/11/filemaker.py">filemaker.py, a Python module for parsing an XML file produced by exporting to FMPXMLRESULT</a> format from Filemaker.</p>

<p>To use it you create a sub-class of the <code>FMPImporter</code> class and over-ride the <code>FMPImporter.import_node</code> method. This method is called for each row of data in the XML file and is passed an XML node instance for the row. You can convert that node to a more useful dictionary where keys are column names and values are the column values. You would then convert the data to your Django model object and save it.</p>

<p>A trivial example:</p>

<pre><code>import filemaker

class MyImporter(filemaker.FMPImporter):
    def import_node(self, node):
        node_dict = self.format_node(node)
        print node['RECORDID'], node_dict

importer = MyImporter(datefmt='%d/%m/%Y')
filemaker.importfile('/path/to/data.xml', importer=importer)
</code></pre>

<p>The <code>FMPImporter.format_node</code> method converts values to an appropriate Python type according to the Filemaker column type. Filemaker&#8217;s <code>DATE</code> and <code>TIME</code> types are converted to Python <a href="http://docs.python.org/library/datetime.html#date-objects"><code>datetime.date</code></a> and <a href="http://docs.python.org/library/datetime.html#time-objects"><code>datetime.time</code></a> instances respectively. <code>NUMBER</code> types are converted to Python <code>float</code> instances. Everything else is left as strings, but you can customize the conversion by over-riding the appropriate methods in your sub-class (see the source for the appropriate method names).</p>

<p>In the case of Filemaker <code>DATE</code> values you can pass the <code>datefmt</code> argument to your sub-class to specify the date format string. See Python&#8217;s <a href="http://docs.python.org/library/time.html#time.strftime">time.strptime documentation</a> for the complete list of the format specifiers.</p>

<p>The code uses <a href="http://docs.python.org/library/xml.sax.html">Python&#8217;s built-in SAX parser</a> so that it is efficent when importing huge XML files (the process uses a constant 15 megabytes for any size of data on my Mac running Python 2.5).</p>

<p>Fortunately I haven&#8217;t had to deal with Filemaker&#8217;s repeating fields so I have no idea how the code works on repeating fields. Please let me know if it works for you. Or not.</p>

<p><a href="http://reliablybroken.com/b/wp-content/uploads/2009/11/filemaker.py">Download filemaker.py</a>. This code is released under a 2-clause BSD license.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/11/migrating-a-filemaker-database-to-django/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Working with Active Directory FILETIME values in Python</title>
		<link>http://reliablybroken.com/b/2009/09/working-with-active-directory-filetime-values-in-python/</link>
		<comments>http://reliablybroken.com/b/2009/09/working-with-active-directory-filetime-values-in-python/#comments</comments>
		<pubDate>Mon, 07 Sep 2009 16:27:16 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[active directory]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=282</guid>
		<description><![CDATA[How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME: Under Win32 platforms, file times are maintained primarily in the form of a 64-bit FILETIME structure, which represents the number of 100-nanosecond intervals since January 1, 1601 UTC (coordinate universal time). UPDATED New version with fixes by Tim Williams for preserving microseconds. See [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://support.microsoft.com/kb/167296">How To Convert a UNIX time_t to a Win32 FILETIME or SYSTEMTIME</a>:</p>

<blockquote>
  <p>Under Win32 platforms, file times are maintained primarily in the form of
  a 64-bit FILETIME structure, which represents the number of 100-nanosecond
  intervals since January 1, 1601 UTC (coordinate universal time).</p>
</blockquote>

<p><strong><em>UPDATED</em> New version with fixes by Tim Williams for preserving microseconds. See <a href="http://reliablybroken.com/b/2011/09/free-software-ftw-updated-filetimes-py/">here for details</a>.</strong></p>

<p>It just so happens that <a href="http://www.microsoft.com/windowsserver2008/en/us/active-directory.aspx">Microsoft Active Directory</a> uses the same 64-bit value to store some time values. For example <a href="http://msdn.microsoft.com/en-us/library/ms675098(VS.85).aspx">the <code>accountExpires</code> attribute</a> is in this format. Linked below is a module for Python with utility functions for converting between <a href="http://docs.python.org/library/datetime.html">Python&#8217;s datetime instances</a> and Microsoft&#8217;s FILETIME values.</p>

<p>Very handy if you enjoy querying Active Directory for login accounts that are due to expire. And who wouldn&#8217;t enjoy that? On a Monday.</p>

<p><a href="/b/wp-content/filetimes.py">Download filetimes.py module for converting between FILETIME and <code>datetime</code> objects.</a> This code is released under a 2-clause BSD license.</p>

<p>Example usage:</p>

<pre><code>&gt;&gt;&gt; from filetimes import filetime_to_dt, dt_to_filetime, utc
&gt;&gt;&gt; filetime_to_dt(116444736000000000)
datetime.datetime(1970, 1, 1, 0, 0)
&gt;&gt;&gt; filetime_to_dt(128930364000000000)
datetime.datetime(2009, 7, 25, 23, 0)
&gt;&gt;&gt; "%.0f" % dt_to_filetime(datetime(2009, 7, 25, 23, 0))
'128930364000000000'
&gt;&gt;&gt; dt_to_filetime(datetime(1970, 1, 1, 0, 0, tzinfo=utc))
116444736000000000L
&gt;&gt;&gt; dt_to_filetime(datetime(1970, 1, 1, 0, 0))
116444736000000000L
</code></pre>

<p>I even remembered to write tests for once!</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/09/working-with-active-directory-filetime-values-in-python/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>BBC iCalendar schedules</title>
		<link>http://reliablybroken.com/b/2009/08/bbc-icalendar-schedules/</link>
		<comments>http://reliablybroken.com/b/2009/08/bbc-icalendar-schedules/#comments</comments>
		<pubDate>Fri, 07 Aug 2009 20:18:42 +0000</pubDate>
		<dc:creator>david</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[bbc]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[time zone]]></category>

		<guid isPermaLink="false">http://reliablybroken.com/b/?p=262</guid>
		<description><![CDATA[Jon Udell recently wrote about accessing the BBC programming schedules but was put-off by the lack of time zone information in the iCalendar feeds, which prompted me to fix the quick-and-dirty script I have that generates iCalendar files for the BBC. (I wrote the first, time zone-blind version of my script in England&#8217;s Winter and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.jonudell.net/">Jon Udell</a> recently <a href="http://blog.jonudell.net/2009/08/05/curation-meta-curation-and-live-net-radio/">wrote about accessing the BBC programming schedules</a> but was put-off by the lack of time zone information in the iCalendar feeds, which prompted me to fix the quick-and-dirty script I have that generates <a href="http://reliablybroken.com/guide/">iCalendar files for the BBC</a>. (I wrote the first, time zone-blind version of my script in England&#8217;s Winter and it worked just perfick back then!)</p>

<p>So <a href="http://reliablybroken.com/guide/bbcguidetz.py">I fix it</a>. The updated iCalendar files have events with time zone information.</p>

<p>Everyone&#8217;s happy.</p>

<p>Jon Udell&#8217;s use of Python to explore data manipulation on the Web was one of the reasons I thought I really ought to get stuck into <a href="http://www.python.org/">Python</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://reliablybroken.com/b/2009/08/bbc-icalendar-schedules/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

