<?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/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule">

<channel>
	<title>yergler.net &#187; python</title>
	<atom:link href="http://yergler.net/blog/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://yergler.net</link>
	<description>Because eventually I&#039;ll be right. Theoretically.</description>
	<lastBuildDate>Wed, 23 May 2012 01:10:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>hieroglyph: Easy, Beautiful Slides with Restructured Text</title>
		<link>http://yergler.net/blog/2012/03/13/hieroglyph/</link>
		<comments>http://yergler.net/blog/2012/03/13/hieroglyph/#comments</comments>
		<pubDate>Wed, 14 Mar 2012 05:31:16 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[projects]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rst]]></category>
		<category><![CDATA[slides]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=2028</guid>
		<description><![CDATA[I was happy to have my talk proposal accepted for PyCon this year, and happy with the feedback I received on my talk (Django Forms Deep Dive). But as I was putting my talk together the distracting question was not, &#8220;what should I say&#8221;, but &#8220;what should I say it with&#8221;. As a mentor once [...]]]></description>
			<content:encoded><![CDATA[<p>I was happy to have my talk proposal accepted for <a href="https://us.pycon.org/2012/">PyCon</a> this year, and happy with the feedback I received on my talk (<a href="https://us.pycon.org/2012/schedule/presentation/420/">Django Forms Deep Dive</a>). But as I was putting my talk together the distracting question was not, &#8220;what should I say&#8221;, but &#8220;what should I say it with&#8221;. As a mentor once pointed out, &#8220;it&#8217;s more fun to write programs to help you write programs than it is to write programs.&#8221; The corollary I found over the past couple weeks: &#8220;it&#8217;s more fun to write programs to help you write slides than it is to write slides.&#8221;</p>
<p><a href="http://yergler.net/media/2012/03/Screen-Shot-2012-03-14-at-8.49.28-AM.png"><img src="/media/2012/03/Screen-Shot-2012-03-14-at-8.49.28-AM-300x187.png" alt="" title="hieroglyph slides" width="300" height="187" class="aligncenter size-medium wp-image-2052" /></a></p>
<p>I was putting together notes using <a href="http://docutils.sourceforge.net/">reStructured Text</a> and kept thinking that it&#8217;d be nice to generate both slides and longer written documentation from the same source. I&#8217;ve used docutils&#8217; <a href="http://docutils.sourceforge.net/docs/user/slide-shows.html">S5 generator</a> in the past, but was looking for something a little more polished looking. Something like the <a href="http://code.google.com/p/html5slides/">HTML5 Slides</a>. </p>
<p><a href="http://yergler.net/media/2012/03/Screenshot_2012-03-14-08-47-22.png"><img src="/media/2012/03/Screenshot_2012-03-14-08-47-22-168x300.png" alt="" title="Mobile hieroglyph" width="168" height="300" class="alignright size-medium wp-image-2053" /></a>So I wrote a <a href="http://yergler.net/projects/hieroglyph/"><strong>hieroglyph</strong></a>, a <a href="http://sphinx.pocoo.org/">Sphinx</a> builder for generating HTML5 Slides. I presented <strong>hieroglyph</strong> at the Sunday morning lightning talks at PyCon: you can see the <a href="http://yergler.net/projects/hieroglyph/slides/">slides</a>, the <a href="https://github.com/nyergler/hieroglyph/blob/master/docs/index.rst">reStructured Text source</a>, as well as the <a href="http://yergler.net/projects/hieroglyph/">HTML documentation</a> generated from the same source.</p>
<p>I&#8217;m really happy with the output &#8212; it looks great in the browser, projects well, and because I&#8217;m using the html5slides CSS, looks great on mobile devices, too. I&#8217;m even happier that I&#8217;m able to work on my content in plain text. You can find the source <a href="https://github.com/nyergler/hieroglyph">on github</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2012/03/13/hieroglyph/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>super(self.__class__, self) # end of the line for subclassing</title>
		<link>http://yergler.net/blog/2011/07/04/super-self/</link>
		<comments>http://yergler.net/blog/2011/07/04/super-self/#comments</comments>
		<pubDate>Tue, 05 Jul 2011 03:44:23 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[super]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1990</guid>
		<description><![CDATA[I&#8217;ve learned (and remembered) a lot in the past two months as I&#8217;ve gotten back to coding as my primary job. One thing that I guess I never quite internalized before is how super works. I have been bitten by code that looks something like the following a few times in the past month: class [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve learned (and remembered) a lot in the past two months as I&#8217;ve gotten back to coding as my primary job. One thing that I guess I never quite internalized before is how <code>super</code> works. I have been bitten by code that looks something like the following a few times in the past month:</p>
<pre><code>
class A(object):
    def __init__(self):
        super(self.__class__, self).__init__()

class B(A):
    def __init__(self):
        super(B, self).__init__()
</code></pre>
<p>The surprise comes when I try to use my sub-class, <code>B</code>. Instantiating <code>B()</code> blows up the stack with: </p>
<p><code>RuntimeError: maximum recursion depth exceeded while calling a Python object</code>.</p>
<p>What? </p>
<p>According to the <a href="http://docs.python.org/library/functions.html#super">Python 2.7.2 standard library documentation</a>, <code>super</code> &#8220;return[s] a proxy object that delegates method calls to a parent or sibling class of type.&#8221; So in the case of single inheritance, it delegates access to the super class, it does not return an instance of the super class. In the example above, this means that when you instantiate B, the follow happens:</p>
<ol>
<li>enter <code>B.__init__()</code></li>
<li>call <code>super</code> on B and call <code>__init__</code> on the proxy object</li>
<li>enter <code>A.__init__()</code></li>
<li>call <code>super</code> on <code>self.__class__</code> and call <code>__init__</code> on the proxy object</li>
</ol>
<p>The problem is that when we get to step four, <code>self</code> still refers to our instance of <code>B</code>, so calling <code>super</code> points back to <code>A</code> again. In technical terms: Ka-bloom.</p>
<p><strong>TL;DR:</strong> <code>super(self.__class__, self)</code> may look like a neat trick, but it&#8217;s the end of the line for sub-classing.</p>
<p><strong>Further reading:</strong> Raymond Hettinger&#8217;s excellent <a href="http://rhettinger.wordpress.com/2011/05/26/super-considered-super/">blog post on super</a> provides a great overview of <code>super</code> and shows off the improved Python 3 syntax, which removes the need to write the class name as part of the <code>super</code> statement. I was really pleased to find the Python standard library documentation links directly to it.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2011/07/04/super-self/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>CI at CC</title>
		<link>http://yergler.net/blog/2010/08/20/ci-at-cc/</link>
		<comments>http://yergler.net/blog/2010/08/20/ci-at-cc/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 17:37:43 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[cc]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[coverage]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sanity]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1734</guid>
		<description><![CDATA[I wrote about our roll-out of Hudson on the CC Labs blog. I wanted to note a few things about deploying that, primarily for my own reference. Hudson has some great documentation, but I found Joe Heck&#8217;s step by step instructions on using Hudson for Python projects particularly helpful. We&#8217;re using nose for most of [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote about <a href="http://labs.creativecommons.org/2010/08/12/welcome-hudson-to-creative-commons/">our roll-out</a> of <a href="http://hudson-ci.org">Hudson</a> on the <a href="http://labs.creativecommons.org/">CC Labs blog</a>.  I wanted to note a few things about deploying that, primarily for my own reference.  Hudson has some great documentation, but I found Joe Heck&#8217;s <a href="http://www.rhonabwy.com/wp/2009/11/04/setting-up-a-python-ci-server-with-hudson/">step by step instructions</a> on using Hudson for Python projects particularly helpful.  We&#8217;re using <a href="http://pypi.python.org/pypi/nose">nose</a> for most of our projects, and <a href="http://pypi.python.org/pypi/zc.buildout">buildout</a> creates a <code>nosetest</code> script wrapper that Hudson runs to generate pass/fail reports.  </p>
<p><a href="http://code.creativecommons.org/issues/issue653">Setting up coverage</a> is on the <a href="http://code.creativecommons.org/issues/">todo list</a>, but it appears that our particular combination of libraries has at least one strange issue: when <a href="http://code.creativecommons.org/viewgit/cc.license.git">cc.license</a> uses <a href="http://jinja.pocoo.org/2/">Jinja2</a> to load a template, coverage thinks it&#8217;s a Python source file (maybe it uses an import hook or something? haven&#8217;t looked) and tries to tokenize it when generating the xml report. <a href="https://groups.google.com/group/coveragepy-dev/browse_thread/thread/62f63eb9a2560b28">Ka-boom</a>. (This has apparently already been <a href="http://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report">reported</a>.)</p>
<p>Another item in the &#8220;maybe/someday&#8221; file is using <a href="http://codespeak.net/tox">Tox</a> to run the tests using multiple versions of Python (example configuration for <a href="http://codespeak.net/tox/example/hudson.html">Tox + Hudson</a> exists).  I can see that this is a critical part of the process when releasing libraries for others to consume.  We have slightly less surface area &#8212; all the servers run the same version of Python &#8212; but it&#8217;d be great to know exactly what our possible deployment parameters are.</p>
<p>Overall Hudson already feels like it&#8217;s adding to our sanity.  I just received my copy of <a href="http://continuousdelivery.com/">Continuous Delivery</a>, so I think this is the start of something wonderful.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/08/20/ci-at-cc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Batteries Included (or, Maildir to mbox, again)</title>
		<link>http://yergler.net/blog/2010/06/06/batteries-included-or-maildir-to-mbox-again/</link>
		<comments>http://yergler.net/blog/2010/06/06/batteries-included-or-maildir-to-mbox-again/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 20:04:29 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[geek]]></category>
		<category><![CDATA[maildir]]></category>
		<category><![CDATA[mbox]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1707</guid>
		<description><![CDATA[UPDATE 7 June 2010: Added usage information to docstring. UPDATE 30 January 2012: Frédéric Grosshans has provided an updated version that supports nested maildirs; you can find it at github. YMMV. My script for converting maildir to mbox continues to be one of the most popular pages on yergler.net (according to Google Analytics). Of course, [...]]]></description>
			<content:encoded><![CDATA[<p class="update"><strong>UPDATE 7 June 2010:</strong> Added usage information to docstring.</p>
<p class="update"><strong>UPDATE 30 January 2012:</strong> Frédéric Grosshans has provided an updated version that supports nested maildirs; you can <a href="https://gist.github.com/1709069">find it at github</a>. YMMV.</p>
<p>My <a href="http://yergler.net/projects/one-off/maildir-to-mbox/">script for converting maildir to mbox</a> <a href="http://yergler.net/blog/2010/02/03/most-popular-erroneous-post/">continues</a> to be one of the most popular pages on yergler.net (according to Google Analytics).  Of course, even after I <a href="http://yergler.net/blog/2010/02/03/most-popular-erroneous-post/">updated</a> it slightly in February, it still had a couple of bugs, likely introduced when I converted the page from MoinMoin to WordPress.  This afternoon I finally decided to clear out the pending comments about those bugs, and update it.  </p>
<p>While looking at the Python documentation for the <a href="http://docs.python.org/library/mailbox.html"><code>mailbox</code></a> package included in the standard library, I realized it could probably be simplified even further by using the library&#8217;s native <a href="http://docs.python.org/library/mailbox.html#mbox"><code>mbox</code></a> support.  I&#8217;m also more comfortable using the standard library&#8217;s implementation of <code>mbox</code> rather than my hacked up raw file implementation (who knows, the standard library may do exactly what my script did: I&#8217;m not an <code>mbox</code> expert by any stretch of the imagination).</p>
<p>The new script is below.  I should note that it&#8217;s received very little testing, and I make no guarantees.  I also should note that there is nothing creative or original about this.  It just uses Python&#8217;s excellent standard library.  As they say, &#8220;batteries included&#8221;.</p>
<div class="wp_syntax">
<div class="wp_syntax_download">
<div class="wp_syntax_download_filename"><a name="file-maildir2mbox.py" href="#file-maildir2mbox.py" title="maildir2mbox.py">maildir2mbox.py</a></div>
<div class="wp_syntax_download_actions">
<a href="http://yergler.net/wordpress/wp-content/plugins/wp-syntax-download-extension/wp-syntax-download-extension.php/1707/maildir2mbox.py">raw</a> <a href="http://yergler.net/wordpress/wp-content/plugins/wp-syntax-download-extension/wp-syntax-download-extension.php/1707/download/maildir2mbox.py">download</a>
</div>
</div>
<table><tr>
<td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td>
<td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">"""
maildir2mbox.py
Nathan R. Yergler, 6 June 2010
&nbsp;
This file does not contain sufficient creative expression to invoke
assertion of copyright.  No warranty is expressed or implied; use at
your own risk.
&nbsp;
---
&nbsp;
Uses Python's included mailbox library to convert mail archives from
maildir [http://en.wikipedia.org/wiki/Maildir] to 
mbox [http://en.wikipedia.org/wiki/Mbox] format.
&nbsp;
See http://docs.python.org/library/mailbox.html#mailbox.Mailbox for 
full documentation on this library.
&nbsp;
---
&nbsp;
To run, save as maildir2mbox.py and run:
&nbsp;
$ python maildir2mbox.py [maildir_path] [mbox_filename]
&nbsp;
[maildir_path] should be the the path to the actual maildir (containing new, cur, tmp);
&nbsp;
[mbox_filename] will be newly created.
"""</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">mailbox</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">email</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># open the existing maildir and the target mbox file</span>
maildir = <span style="color: #dc143c;">mailbox</span>.<span style="color: black;">Maildir</span><span style="color: black;">(</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span> <span style="color: black;">[</span>-<span style="color: #ff4500;">2</span><span style="color: black;">]</span>, <span style="color: #dc143c;">email</span>.<span style="color: black;">message_from_file</span><span style="color: black;">)</span>
mbox = <span style="color: #dc143c;">mailbox</span>.<span style="color: black;">mbox</span><span style="color: black;">(</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">[</span>-<span style="color: #ff4500;">1</span><span style="color: black;">]</span><span style="color: black;">)</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># lock the mbox</span>
mbox.<span style="color: black;">lock</span><span style="color: black;">(</span><span style="color: black;">)</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># iterate over messages in the maildir and add to the mbox</span>
<span style="color: #ff7700;font-weight:bold;">for</span> msg <span style="color: #ff7700;font-weight:bold;">in</span> maildir:
    mbox.<span style="color: black;">add</span><span style="color: black;">(</span>msg<span style="color: black;">)</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># close and unlock</span>
mbox.<span style="color: black;">close</span><span style="color: black;">(</span><span style="color: black;">)</span>
maildir.<span style="color: black;">close</span><span style="color: black;">(</span><span style="color: black;">)</span></pre></td>
</tr></table>
</div>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/06/06/batteries-included-or-maildir-to-mbox-again/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Preread: &#8220;Django 1.1 Testing and Debugging&#8221;, by Karen M. Tracey</title>
		<link>http://yergler.net/blog/2010/05/16/preread-django-1-1-testing-and-debugging-by-karen-m-tracey/</link>
		<comments>http://yergler.net/blog/2010/05/16/preread-django-1-1-testing-and-debugging-by-karen-m-tracey/#comments</comments>
		<pubDate>Mon, 17 May 2010 04:39:04 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[reading]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[pre-read]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1696</guid>
		<description><![CDATA[Another Packt Publishing title is on the way for review, Django 1.1 Testing and Debugging, by Karen M. Tracey. Django 1.2 ships tomorrow, and I&#8217;m looking forward to the book: testing is one of the things that helps software evolve, but it&#8217;s also one of the things that&#8217;s easiest to ignore on a project. I [...]]]></description>
			<content:encoded><![CDATA[<p>Another Packt Publishing title is on the way for review, <em><a href="http://www.packtpub.com/django-1-1-testing-and-debugging/book?utm_source=yergler.net&#038;utm_medium=bookrev&#038;utm_content=blog&#038;utm_campaign=mdb_003267">Django 1.1 Testing and Debugging</a></em>, by Karen M. Tracey.  Django 1.2 <a href="http://www.djangoproject.com/weblog/2010/may/15/release-schedule/">ships tomorrow</a>, and I&#8217;m looking forward to the book: testing is one of the things that helps software evolve, but it&#8217;s also one of the things that&#8217;s easiest to ignore on a project.  I say this to myself as much as anyone: even though I know tests will make my life better in the long run, when I start hacking, sometimes they&#8217;re the furthest thing from my mind.  Books about how to test, and how to do it effectively, are definitely a good thing for me.</p>
<p>The PDF preview of <a href="https://www.packtpub.com/sites/default/files/7566_Django%201.1%20Testing%20and%20Debugging_SampleChapter_1.pdf">chapter 3</a> (basic unit testing) looks good, and the table of contents looks like a good overview of basic tools and techniques.  I&#8217;m particularly looking forward to reading about integrating Django with other testing tools (chapter 5), and using Django with <code>pdb</code> (chapter 9).  I&#8217;m looking forward to learning more about testing my Django applications &#8212; and hopefully how I can form better habits around testing.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/05/16/preread-django-1-1-testing-and-debugging-by-karen-m-tracey/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Back to the Future: Desktop Applications</title>
		<link>http://yergler.net/blog/2010/03/30/back-to-the-future-desktop-applications/</link>
		<comments>http://yergler.net/blog/2010/03/30/back-to-the-future-desktop-applications/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 16:04:03 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[cc]]></category>
		<category><![CDATA[ccpublisher]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1517</guid>
		<description><![CDATA[One of the best prepared talks I saw at PyCon this year was on Phatch, a cross-platform photo processing application written in Python. Stani Michiels and Nadia Alramli gave a well rehearsed, compelling talk discussing the ins and outs of developing their application for Linux, Mac OS X, and Windows. The video is available from [...]]]></description>
			<content:encoded><![CDATA[<p>One of the best prepared talks I saw at PyCon this year was on <a href="http://photobatch.stani.be/">Phatch</a>, a cross-platform photo processing application written in Python.  Stani Michiels and Nadia Alramli gave a well rehearsed, compelling talk discussing the ins and outs of developing their application for Linux, Mac OS X, and Windows.  The <a href="http://python.mirocommunity.org/video/1595/pycon-2010-cross-platform-appl">video is available</a> from the excellent Python MiroCommunity.</p>
<p>The talk reminded of a blog post I saw late last year and never got around to commenting on, <a href="http://spin.atomicobject.com/2009/01/30/ruby-for-desktop-applications-yes-we-can">Ruby for Desktop Applications? Yes we can.</a>  Now I&#8217;m only a year late in commenting on it.  This post caught my eye for two reasons. First, the software they discuss was commissioned by the <a href="http://www.goldratt.com/">AGI Goldratt Institute</a>.  I had heard about Goldratt from my father, whose employer, <a href="http://trustedmfg.com/">Trusted Manufacturing</a>, was working on implementing constraints-based manufacturing as a way to reduce costs and distinguish themselves from the rest of the market.  More interesting, though, was their discussion of how they built the application, and how it seemed to resonate with some of the work I did in my early days at CC.  </p>
<p>Atomic wrote three blog posts (at least that I saw), and the one with the most text (as determined by my highly unscientific &#8220;page down&#8221; method) was all about how they &#8220;rolled&#8221; the JRuby application: how they laid out the source tree, how they compile Ruby source into Java JARs, and how they distribute a single JAR file with their application and its dependencies.  I thought this was interesting because even though it uses a different language (Python instead of Ruby), GUI framework (wx instead of Swing/Batik), and runtime strategy (bundled interpreter instead of bytecode archive), the thing I spent the most time on when I was developing <a href="http://wiki.creativecommons.org/CC_Publisher">CC Publisher</a> was deployment. </p>
<p>Like Atomic and Phatch, we had a single code base that we wanted to work across the major platforms (Windows, Linux, and Mac OS X in our case).  The presentation about Phatch has some great information about making desktop-specific idioms work in Python, so I&#8217;ll let them cover that.  Packaging and deployment was the biggest challenge, one we never quite got right.</p>
<p>On Windows, we used <a href="http://www.py2exe.org/">py2exe</a> to bundle our Python runtime with the source code and dependencies.  This worked most of the time, unless we forget to specify a sub-package in our manifest, in which case it blew up in amazing and spectacular ways (not really).  Like Atomic, we used <a href="http://nsis.sourceforge.net/">NSIS</a> for the Windows installer portion.  On Mac OS X, we used <a href="http://svn.pythonmac.org/py2app/py2app/trunk/doc/index.html">py2app</a> to do something similar, and distributed a disk image.  On Linux&#8230; well, on Linux, we punted.  We experimented with a <a href="http://cx-freeze.sourceforge.net/">cx-freeze</a> and <a href="http://yergler.net/blog/2005/08/17/packaging-applications-for-linux-with-autopackage/">flirted</a> with <a href="http://autopackage.org/">autopackage</a>.  But nothing ever worked quite right [enough], so we would up shipping tarballs. </p>
<p>The really appealing thing about Atomic&#8217;s approach is that by using a single JAR, you get to leverage a much bigger ecosystem of tools: the Java community has either solved, or has well defined idioms for, launching Java applications from JARs.  You get <a href="http://launch4j.sourceforge.net/">launch4j</a> and <a href="http://izpack.org/">izpack</a>, which look like great additions to a the desktop developer&#8217;s toolbox.</p>
<p>For better or for worse, we [Creative Commons] decided CC Publisher wasn&#8217;t the best place to put our energy and time.  This was probably the right decision, but it was a fun project to work on.  (We do have <a href="http://wiki.creativecommons.org/CC_Publisher_Refresh_and_Update">rebooting CC Publisher</a> listed as a <a href="http://wiki.creativecommons.org/Developer_Challenges">suggested project</a> for <a href="http://socghop.appspot.com/gsoc/org/show/google/gsoc2010/creativecommons">Google Summer of Code</a>, if someone else is interested in helping out.) Given the maturity of Java&#8217;s desktop tool chain, and the vast improvements in <a href="http://jython.org/">Jython</a> over the past year or two, I can imagine considering an approach very much like Atomic&#8217;s were I working on it today.  Even though it seems like the majority of people&#8217;s attention is on web applications these days, I like seeing examples of interesting desktop applications being built with dynamic languages.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/30/back-to-the-future-desktop-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using pip with buildout</title>
		<link>http://yergler.net/blog/2010/03/28/using-pip-with-buildout/</link>
		<comments>http://yergler.net/blog/2010/03/28/using-pip-with-buildout/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 20:05:22 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[dependencies]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[koucou]]></category>
		<category><![CDATA[pip]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scm]]></category>
		<category><![CDATA[zc.buildout]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1586</guid>
		<description><![CDATA[I&#8217;ve been asked to add a blog to koucou, and this has turned out to be more of a learning experience than I expected. My first instinct was to use WordPress &#8212; I&#8217;m familiar with it, like the way it works, and I&#8217;m not interested in building my own. The one wrinkle was that we [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been asked to add a blog to <a href="http://koucou.com/">koucou</a>, and this has turned out to be more of a learning experience than I expected.  My first instinct was to use <a href="http://wordpress.org/">WordPress</a> &#8212; I&#8217;m familiar with it, like the way it works, and I&#8217;m not interested in building my own.  The one wrinkle was that we wanted to integrate the blog visually with the rest of the site, which is built on <a href="http://djangoproject.com/">Django</a>.  I decided to give <a href="http://github.com/montylounge/django-mingus">Mingus</a> a try.  This post isn&#8217;t about Mingus &#8212; I&#8217;ll write about that shortly &#8212; but rather about <a href="http://pypi.python.org/pip">pip</a>, which Mingus uses to manage dependencies.  Mingus includes a <a href="http://pip.openplans.org/requirement-format.html">requirements file</a> with the stable dependencies for the application (one of its goals is application re-use, so there are a lot of them).  As I <a href="http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/">mentioned previously</a>, <code>pip</code> is the Python packaging/installation tool I have the least experience with, so I decided to try converting my existing project to pip as a starting point &#8212; to gain experience with pip, and to try and ease integration woes with Mingus.</p>
<p>When I started, the project used the following setup to manage dependencies and the build process:</p>
<ul>
<li>Dependencies which have an <a href="http://peak.telecommunity.com/DevCenter/EggFormats">egg</a> or <a href="http://peak.telecommunity.com/DevCenter/setuptools">setuptools</a>-compatible <a href="http://docs.python.org/distutils/sourcedist.html">sdist</a> available are specified in <a href="http://peak.telecommunity.com/DevCenter/setuptools#declaring-dependencies">install_requires</a> in setup.py
<pre><code>setup(
    name = "soursop",

    # ... details omitted

    install_requires = ['setuptools',
                        'zope.interface',
                        'zope.component',
                        'PILwoTK',
                        'flup',
                        ],

    )
</code></pre>
</li>
<li>A <a href="http://buildout.org/">buildout</a> configuration that uses <code><a href="http://pypi.python.org/pypi/djangorecipe">djangorecipe</a></code> to install Django, and <code><a href="http://pypi.python.org/pypi/zc.recipe.egg">zc.recipe.egg</a></code> to install the application egg and its dependencies<br />
<code>
<pre>[buildout]
develop = .
parts = django scripts
unzip = true
eggs = soursop

[django]
recipe = djangorecipe
version = 1.1.1
settings = settings
eggs = ${buildout:eggs}
project = soursop

[scripts]
recipe = zc.recipe.egg
eggs =
     ${buildout:eggs}
interpreter = python
dependent-scripts = true
extra-paths =
   ${django:location}
initialization =
   import os
   os.environ['DJANGO_SETTINGS_MODULE'] = '${django:project}.${django:settings}'
</pre>
<p></code></li>
<li>Dependencies that didn&#8217;t easily install using setuptools (either they didn&#8217;t have a sane source-tree layout or weren&#8217;t available from PyPI) are either specified as <a href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html">git submodules</a> or imported into the repository.</li>
</ul>
<p>All this worked pretty well (although I&#8217;ve never really loved git submodules).</p>
<p><code><a href="http://pypi.python.org/pypi/gp.recipe.pip">gp.recipe.pip</a></code> is a buildout recipe which allows you to install a set of Python packages using pip.  gp.recipe.pip builds on <a href="http://pypi.python.org/pypi/zc.recipe.egg">zc.recipe.egg</a>, so it inherits all the functionality of that recipe (installing dependencies declared in <code>setup.py</code>, generating scripts, etc).  So in that respect, I could simply replace the recipe line in the <code>scripts</code> part and start using pip requirements to install from source control, create editable checkouts, etc.</p>
<p>Previously, I used the <code>${buildout:eggs}</code> setting to share a set of packages to install between the <code>django</code> part (which I used to generate a Django management script) and the <code>scripts</code> part (which I used to resolve the dependency list and install scripts defined as entry points).  I didn&#8217;t spend much time looking into replicating this with gp.recipe.pip; it wasn&#8217;t immediately clear to me how to get a working set out of it that&#8217;s equivalent to an <code>eggs</code> specification (I&#8217;m not even sure it makes sense to expect such a thing).</p>
<p>Ignoring the issue of the management script, I simplified my buildout configuration, removing the <code>django</code> part and using <code>gp.recipe.pip</code>:</p>
<p><code>
<pre>
[buildout]
develop = .
parts = soursop
unzip = true
eggs = soursop
django-settings = settings
django-project = soursop

[soursop]
recipe = gp.recipe.pip
interpreter = python
eggs = ${buildout:eggs}
sources-directory = vendor

initialization =
   import os
   os.environ['DJANGO_SETTINGS_MODULE'] = '${buildout:django-project}.${buildout:django-settings}'
</pre>
<p></code></p>
<p>This allowed me to start specifying the resources I previously included as git submodules as pip requirements:</p>
<p><code>
<pre>
[soursop]
recipe = gp.recipe.pip
interpreter = python
install =
	-r requirements.txt
eggs = ${buildout:eggs}
sources-directory = vendor
</pre>
<p></code></p>
<p>The install parameter specifies a series of pip dependencies that buildout will install when it runs.  These can include version control URLs, recursive requirements (in this case, <a href="http://pip.openplans.org/#requirements-files">a requirements file</a>, <code>requirements.txt</code>), and editable dependencies.  In this case I&#8217;ve also specified a directory, <code>vendor</code>, in which editable dependencies will be installed.</p>
<p>That actually works pretty well: I can define my list of dependencies in a text file on its own, and I can move away from git submodules and vendor imports to specifying [D]VCS urls that pip will pull.  </p>
<p>Unfortunately, I&#8217;m still missing my manage script.  I wound up creating a small function and entry point to cause the script to be generated.  In <code>soursop/scripts.py</code>, I created the following function:</p>
<p><code>
<pre>def manage():
    """Entry point for Django manage command; assumes
    DJANGO_SETTINGS_MODULE has been set in the environment.

    This is a convenience for getting a ./bin/manage console script
    when using buildout."""

    from django.core import management
    from django.utils import importlib
    import os

    settings = importlib.import_module(os.environ.get('DJANGO_SETTINGS_MODULE'))

    management.execute_manager(settings)
</pre>
<p></code></p>
<p>In setup.py, I added an entry point:</p>
<p><code>
<pre>    entry_points = {
        'console_scripts' : [
            'manage = soursop.scripts:manage',
            ]
        },
</pre>
<p></code></p>
<p>Re-run buildout, and a <code>manage</code> script appears in the <code>bin</code> directory.  Note that I&#8217;m still using the environment variable, <code>DJANGO_SETTINGS_MODULE</code>, to specify which settings module we&#8217;re using.  I could specify the settings module directly in my manage script wrapper.  I chose not to do this because I wanted to emulate the behavior of <code>djangorecipe</code>, which lets you change the settings module in buildout.cfg (i.e., from development to production settings).  This is also the reason I have custom initialization code specified in my buildout configuration.</p>
<p>Generally I really like the way this works.  I&#8217;ve been able to eliminate the tracked vendor code in my project, as well as the git submodules.  I can easily move my pip requirements into a requirements file and specify it with -r in the install line, separating dependency information from build information.</p>
<p>There are a couple things that I&#8217;m ambivalent about.  Primarily, I now have two different places where I&#8217;ve declared some of my dependencies, <code>setup.py</code> and a requirements file, and each has advantages (which are correspondingly disadvantages for the other).  Specifying the requirements in the pip requirements file gives me more flexibility &#8212; I can install from subversion, git, or mercurial without even thinking about it.  But if someone installs my package from a source distribution using easy_install or pip, the dependencies won&#8217;t necessarily be satisfied<sup>1, 2</sup>.  And conversely, specifying the requirements in <code>setup.py</code> allows everyone to introspect them at installation time, but sacrifices the flexibility I&#8217;ve gained from pip.</p>
<p>I&#8217;m not sure that we&#8217;ll end up using Mingus for koucou, but I think we&#8217;ll stick with gp.recipe.pip.  The disadvantage is a small one (at least in this situation), and it&#8217;s not really any worse than the previous situation. </p>
<hr />
<p><sup>1</sup> I suppose I could provide a <a href="http://pip.openplans.org/#bundles">bundle</a> for pip that includes the dependencies, but the documentation doesn&#8217;t make that seem very appealing.</p>
<p><sup>2</sup> Inability to install my Django application from an sdist isn&#8217;t really a big deal: the re-use story just isn&#8217;t good enough (in my opinion) to have it make sense.  Generally, however, I like to be able to install a package and pull in the dependencies as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/28/using-pip-with-buildout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pre-read: Grok 1.0 Web Development</title>
		<link>http://yergler.net/blog/2010/03/16/pre-read-grok-1-0-web-development/</link>
		<comments>http://yergler.net/blog/2010/03/16/pre-read-grok-1-0-web-development/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 16:14:50 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[reading]]></category>
		<category><![CDATA[cc]]></category>
		<category><![CDATA[grok]]></category>
		<category><![CDATA[pre-read]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1567</guid>
		<description><![CDATA[Late last month I received an email from Packt Publishing (en.wp), asking if I&#8217;d be interested in reviewing one of their new titles, Grok 1.0 Web Development, by Carlos de la Guardia. I immediately said yes, with the caveat that I&#8217;m traveling a lot over the next 30 days, so the review will be a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.packtpub.com/grok-1-0-web-development/book?utm_source=yergler.net&amp;utm_medium=bookrev&amp;utm_content=blog&amp;utm_campaign=mdb_002632"><img src="/media//2010/03/Grok-1.0-image-243x300.jpg" alt="" title="Grok 1.0 Web Development" width="243" height="300" class="alignright size-medium wp-image-1568" /></a>Late last month I received an email from <a href="http://www.packtpub.com/">Packt Publishing</a> (<a href="http://en.wikipedia.org/wiki/Packt">en.wp</a>), asking if I&#8217;d be interested in reviewing one of their new titles, <em><a href="http://www.packtpub.com/grok-1-0-web-development/book?utm_source=yergler.net&#038;utm_medium=bookrev&#038;utm_content=blog&#038;utm_campaign=mdb_002632">Grok 1.0 Web Development</a></em>, by <a href="http://blog.delaguardia.com.mx/">Carlos de la Guardia</a>.  I immediately said yes, with the caveat that I&#8217;m traveling a lot over the next 30 days, so the review will be a little delayed (hence this pre-review).  I said &#8220;yes&#8221; because <a href="http://grok.zope.org/">Grok</a> is one of the Python web frameworks that&#8217;s most interesting to me these days.  It&#8217;s interesting because one of its underlying goals is to take concepts from <del datetime="2010-03-16T15:46:26+00:00">Zope 3</del><a href="http://docs.zope.org/zopetoolkit/">Zope Toolkit</a>, and make them more accessible and less daunting.  These concepts &#8212; the component model, pluggable utilities, and graph-based traversal &#8212; are some of the most powerful tools I&#8217;ve worked with during my career.  And of course, they can also be daunting, even to people with lots of experience; making them more accessible is a good thing.</p>
<p>I&#8217;ve read the first four chapters of <em>Grok 1.0 Web Development</em>, and so far there&#8217;s a lot to like.  It&#8217;s the sort of documentation I wish I&#8217;d had when I ported the Creative Commons <a href="http://creativecommons.org/choose/">license chooser</a> to Grok<sup>1</sup>.  I&#8217;m looking forward to reading the rest, and will post a proper review when I return from Nairobi.  In the mean time, check out <a href="http://grok.zope.org/">Grok</a>, Zope 3 for cavemen.</p>
<p><em>You can download a preview from Grok 1.0 Web Development, <a href="http://yergler.net/media/2010/03/7481-grok-1-0-Web-development-sample-chapter-5-forms.pdf">Chapter 5: Forms</a>.</em></p>
<hr />
<p><sup>1</sup> The CC license chooser has evolved a lot over the years; shortly after Grok was launched we adopted many of its features as a way to streamline the code.  Grok&#8217;s simplified support for custom traversal, in particular, was worth the effort.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/16/pre-read-grok-1-0-web-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>For Some Definition of &#8220;Reusable&#8221;</title>
		<link>http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/</link>
		<comments>http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 02:38:54 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1539</guid>
		<description><![CDATA[I read &#8220;Why I switched to Pylons after using Django for six months&#8221; yesterday, and it mirrors something I&#8217;ve been thinking about off and on for the past year or so: what is the right level of abstraction for reuse in web applications? I&#8217;ve worked on two Django-based projects over the past 12-18 months: CC [...]]]></description>
			<content:encoded><![CDATA[<p>I read <a href="http://www.mutualinformation.org/2010/03/why-i-switched-to-pylons-after-using-django-for-six-months/">&#8220;Why I switched to Pylons after using Django for six months&#8221;</a> yesterday, and it mirrors something I&#8217;ve been thinking about off and on for the past year or so: what is the right level of abstraction for reuse in web applications?  I&#8217;ve worked on two <a href="http://djangoproject.com/">Django</a>-based projects over the past 12-18 months: <a href="https://creativecommons.net/">CC Network</a> and <a href="http://koucou.com/">koucou</a>.  Neither is what I&#8217;d call &#8220;huge&#8221;, but in both cases I wanted to re-use existing apps, and in both cases it felt&#8230; awkward.</p>
<p>Part of this awkwardness is probably the impedance mismatch of the framework and the toolchain: Django applications are Python packages.  The Python tools for packaging and installing (<a href="http://www.python.org/doc/current/library/distutils.html">distutils</a>, <a href="http://pypi.python.org/pypi/setuptools">setuptools</a>, <a href="http://pypi.python.org/pypi/distribute">distribute</a>, and <a href="http://pip.openplans.org/">pip</a>, I think, although I have the least experience with it) work on &#8220;<a href="http://www.python.org/doc/current/distutils/introduction.html#distutils-specific-terminology">module distributions</a>&#8220;<sup>1</sup>: some chunk of code with a <code>setup.py</code>.  This is as much a &#8220;social&#8221; issue as a technology one: the documentation and tools don&#8217;t encourage the &#8220;right&#8221; kind of behavior, so talk of re-usable applications is often just hand waving or, at best, reinvention<sup>2</sup>. </p>
<p>In both cases we consciously chose Django for what I consider its killer app: the <a href="http://docs.djangoproject.com/en/1.1/ref/contrib/admin/">admin interface</a>. But there have been re-use headaches.  [NB: What follows is based on our experience, which is <a href="http://pypi.python.org/pypi/setuptools">setuptools</a> and <a href="http://buildout.org/">buildout</a> based] The first one you encounter is that not every developer of a reusable app has made it available on <a href="http://pypi.python.org/">PyPI</a>.  If they&#8217;re using Subversion you can still use it with setuptools, but when re-using with git, we have some additional work (a submodule or another buildout recipe).  I understand pip just works with the most commons [D]VCS, but haven&#8217;t used it myself.  Additionally, they aren&#8217;t all structured as projects, and those that are don&#8217;t always declare their dependencies properly<sup>3</sup>.  And finally there&#8217;s the &#8220;real&#8221; issues of templates, URL integration, etc.</p>
<p>I&#8217;m not exactly sure what the answer is, but it&#8217;s probably 80% human (as opposed to technology).  Part of it is practicing good hygiene: writing your apps with <a href="http://www.chipx86.com/blog/2008/04/03/django-development-with-djblets-unrooting-your-urls/">relocatable URLs</a>, using proper <a href="http://docs.djangoproject.com/en/1.1/topics/http/urls/#reverse">URL reversal</a> when generating intra-applications URLs, and making sure your templates are somewhat self-contained.  But even that only gets you so far.  Right now I have to work if I want to make my app easily consumable by others; work, frankly, sucks.</p>
<p>Reuse is one area where I think <a href="http://en.wikipedia.org/wiki/Zope_3">Zope 3</a> (and it&#8217;s derived frameworks, <a href="http://grok.zope.org/">Grok</a> and <a href="http://bfg.repoze.org/">repoze.bfg</a>) have an advantage: if you&#8217;re re-using an application that provides a particular type of model, for example, all you need to do is register a view for it to get a customized template.  The liberal use of interfaces to determine context also helps smooth over some of the URL issues<sup>4</sup>.  Just as, or more, importantly, they have a strong culture of writing code as small &#8220;projects&#8221; and using tools like buildout to assemble the final product.</p>
<p>Code reuse matters, and truth in advertising matters just as much or more.  If we want to encourage people to write reusable applications, the tools need to support that, and we need to be explicit about what the benefits we expect to reap from reuse are.  </p>
<hr />
<p><sup>1</sup> Of course you never actually see these referred to as <em>module distributions</em>; always projects, packages, eggs, or something else. </p>
<p><sup>2</sup> Note that I&#8217;m not saying that <a href="http://pylonshq.com/">Pylons</a> gets the re-use story much better; the author admits choosing Django at least in part because of the perceived &#8220;vibrant community of people writing apps&#8221; but found himself more productive with Pylons.  Perhaps he entered into that with different expectations?  I think it&#8217;s worth noting that we chose Django for a project, in part, for the same reason, but with different expectations: not that the vibrant community writing apps would generate reusable code, but that they would education developers we could hire when the time came.</p>
<p><sup>3</sup> This is partially due to the current state of Python packaging: setuptools and distribute expect the dependency information to be included in setup.py; pip specifies it in a requirements file.</p>
<p><sup>4</sup> At least when dealing with graph-based traversal; it could be true in other circumstances, I just haven&#8217;t thought about it enough.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>We called it &#8220;magic&#8221;</title>
		<link>http://yergler.net/blog/2010/01/06/we-called-it-magic/</link>
		<comments>http://yergler.net/blog/2010/01/06/we-called-it-magic/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 03:04:13 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[aside]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[magic]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1317</guid>
		<description><![CDATA[Just under ten years ago I started working at Canterbury School doing a variety of things. One thing I wound up doing was building the new Intro to Computer curriculum, based on Python. When Vern and I presented our approach at PyCon in 2003, we were asked what advantages we thought Python had over its [...]]]></description>
			<content:encoded><![CDATA[<p>Just under ten years ago I started working at <a href="http://canterburyschool.org">Canterbury School</a> doing a variety of things.  One thing I wound up doing was building the new Intro to Computer curriculum, based on <a href="http://en.wikipedia.org/wiki/Python_(programming_language)">Python</a>.  When Vern and I <a href="http://yergler.net/talks/2003/teaching-programming-with-python-and-pygame/">presented our approach at PyCon</a> in 2003, we were asked what advantages we thought Python had over its predecessor in the curriculum, <a href="http://en.wikipedia.org/wiki/Java_(programming_language)">Java</a>.  The first answer was always, &#8220;Magic; a lack thereof.&#8221;  There was less boilerplate, fewer incantations, a much shorter list of things you have to wave your hands about and say, &#8220;Don&#8217;t worry, we&#8217;ll talk about this later in the semester. For right now, it&#8217;s magic, just do it.&#8221;  Magic distracts students, and makes them wonder what you&#8217;re hiding.</p>
<p>Seeing a <a href="http://www.bestinclass.dk/index.php/2009/09/java-vs-clojure-lets-talk-ceremony/">comparison between Java and Clojure</a> (albeit one you can read as more about succinctness than clarity), I was reminded that this lack of magic &#8212; boilerplate, ceremony, whatever &#8212; is still important.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/01/06/we-called-it-magic/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

