<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" version="2.0">
  <channel>
    <title>Let’s Discuss the Matter Further</title>
    <link>http://rhodesmill.org/brandon</link>
    <description>Thoughts and ideas from Brandon Rhodes</description>
    <pubDate>Sat, 19 May 2012 10:05:06 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/LetsDiscussTheMatterFurther" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="letsdiscussthematterfurther" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
      <title>Moving home directory version control out of your way</title>
      <link>http://rhodesmill.org/brandon/2012/home-directory-vc/</link>
      <pubDate>Mon, 07 May 2012 22:01:40 EDT</pubDate>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2012/home-directory-vc/</guid>
      <description>Moving home directory version control out of your way</description>

      <content:encoded><![CDATA[<div class="document">
<p>If you keep your home directory under version control,
then you may know the sinking feeling
that comes from sitting down at work after a late night,
looking for that brilliant fix you made right before bed,
and finding that your commit is nowhere to be found.
What happened?</p>
<p>Upon arriving home,
you discover that your final conscious act the previous night
was an accidental commit of your home directory —
you committed, say, a tiny experimental change to your <tt class="docutils literal"><span class="pre">~/.profile</span></tt>
from last week
when you really meant to be committing a patch to <tt class="docutils literal">~/big/project</tt>
to resolve the latest show-stopping bug.
You were too tired to notice
that the version control system listed the wrong files
as you typed the commit message into your editor.</p>
<p>This can, of course, happen if you run <tt class="docutils literal">git</tt> or <tt class="docutils literal">hg</tt>
while you are sitting in the wrong directory.
But, more subtly, this can happen
if you are sitting in the <em>correct</em> directory
but call the wrong <em>command</em>.
If <tt class="docutils literal">~/big/project</tt> was, for example,
checked out using Mercurial or Subversion,
then a <tt class="docutils literal">git</tt> <tt class="docutils literal">commit</tt> in that directory
will patiently search up the directory tree,
find your <tt class="docutils literal"><span class="pre">~/.git</span></tt> directory,
and look for changed dotfiles or commands to commit instead.</p>
<p>For those of us with several version control systems going at once,
in fact, it is a bad idea to have <em>any</em> two projects be “concentric” —
where a directory under the control of one version control system
wraps another project under different control.
I really prefer for each directory in the file system
to have exactly one version-control directory
in its tree of ancestors.</p>
<p>So how can you safely version control your dotfiles?
The solution is to keep your <tt class="docutils literal"><span class="pre">~/.git</span></tt> or <tt class="docutils literal"><span class="pre">~/.hg</span></tt> directory
out of the way during normal operation —
for example, by appending <tt class="docutils literal">.off</tt> to its name —
then moving it back into place
when you explicitly want to perform a version control operation
on your dotfiles.
One approach would be to create a shell script like this:</p>


<div class="pygments_murphy"><pre><span class="c"># ~/bin/homedir-git</span>
<span class="c"># Like git, but turns your homedir &quot;on&quot; first</span>

mv ~/.git.off ~/.git
git <span class="s2">&quot;$@&quot;</span>
mv ~/.git ~/.git.off
</pre></div>



<p>However, I found this approach unwieldy.
For one thing, the name of the command was always difficult to type
because I am so strongly conditioned to type the plain, unadorned
version control command instead.
Another problem is that my shell's command-line completion
suddenly did not know to offer the usual version-control subcommands
because <tt class="docutils literal"><span class="pre">homedir-git</span></tt> or <tt class="docutils literal"><span class="pre">homedir-hg</span></tt>
is not a command it recognized.</p>
<p>So my actual solution has been to create a command
to <em>toggle</em> home directory version control on and off.
That way, I can turn it on;
let my normal muscle memory take over
as I craft and execute version-control operations;
and then turn it off again:</p>


<div class="pygments_murphy"><pre><span class="c"># ~/bin/home-toggle</span>

<span class="k">if</span> <span class="o">[</span> -d .git.off <span class="o">]</span> ;<span class="k">then</span>
<span class="k">    </span>mv ~/.git.off ~/.git <span class="o">||</span> <span class="nb">exit </span>1
    <span class="nb">echo </span>Home directory version control activated
<span class="k">else</span>
<span class="k">    </span>mv ~/.git ~/.git.off <span class="o">||</span> <span class="nb">exit </span>1
    <span class="nb">echo </span>Home directory version control deactivated
<span class="k">fi</span>
</pre></div>



<p>Actually, I named my own copy of this shell script <tt class="docutils literal">,home</tt>
because — as you might remember — I
<a class="reference external" href="http://rhodesmill.org/brandon/2009/commands-with-comma/">name my shell scripts starting with a comma</a>.
But you get the idea.
And, of course, I check this shell script into version control
along with the rest of the suite of customizations
that I need on every system where I type.</p>
<p>This whole idea is trivial, obvious,
and so simply implemented as to be hardly worth mentioning.
But those of us who have been using a Unix environment for decades
know that these kinds of tiny micro-customizations
for making our lives easier,
while they are each so simple,
accumulate together into a really amazing result:
an environment that offers very little friction
because, each time your dotfiles are checked out
to your account on a new machine,
it instantly becomes an environment
where every annoyance —
every stone that has ever made you stumble —
has already been accounted for and worked around.</p>
<p>The lack of friction at a well-customized command line
can be really astounding if you have been putting up
with the defaults your entire life.
I&nbsp;hope that this simple example
encourages you to stop in your tracks
the next time something gets in your way for the third,
fourth, or hundredth time, and that you will ask:
“Could I solve this with a simple shell script?”</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Introspect Python logging with logging_tree</title>
      <link>http://rhodesmill.org/brandon/2012/logging_tree/</link>
      <pubDate>Fri, 13 Apr 2012 07:05:36 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2012/logging_tree/</guid>
      <description>Introspect Python logging with logging_tree</description>

      <content:encoded><![CDATA[<div class="document">
<p>It is frustrating that Python's <tt class="docutils literal">logging</tt> module
cannot display the tangled tree of configured loggers
that often result from combining your own application code
with several libraries and frameworks.
So I have released a new Python package named
<a class="reference external" href="http://pypi.python.org/pypi/logging_tree">logging_tree</a>,
which I announced last month during the
<a class="reference external" href="https://us.pycon.org/2012/">PyCon 2012</a>
<a class="reference external" href="http://pyvideo.org/video/721/sunday-afternoon-lightning-talks-90-minutes">closing lightning talks</a>.
My package displays the current <tt class="docutils literal">logging</tt> tree to help debugging,
and its output looks something like this:</p>
<pre class="literal-block">
&lt;--&quot;&quot;
   Level WARNING
   Handler Stream &lt;open file '&lt;stderr&gt;', mode 'w' at ...&gt;
   |
   o&lt;--[cherrypy]
       |
       o&lt;--&quot;cherrypy.access&quot;
       |   Level INFO
       |   Handler Stream &lt;open file '&lt;stdout&gt;', mode 'w' ...&gt;
       |
       o&lt;--&quot;cherrypy.error&quot;
           Level INFO
           Handler Stream &lt;open file '&lt;stderr&gt;', mode 'w' ...&gt;
</pre>
<p>The configuration shown by this tree, it turns out, causes a bug.
This diagram helped me fix a real-life application
for Atlanta startup <a class="reference external" href="http://roverapps.com/">Rover Apps</a>,
who generously let me open-source <tt class="docutils literal">logging_tree</tt>
after I wrote the first version while helping them fix this bug.</p>
<p>In this post I am going to reproduce the problem
using a simple 10-line CherryPy application,
and then show how I used this <tt class="docutils literal">logging_tree</tt> diagram
to craft a solution.
But, first, you need to know three things
about the Python <tt class="docutils literal">logging</tt> module —
and I would like to thank Marius Gedminas for his
<a class="reference external" href="http://mg.pov.lt/blog/logging-levels">recent post about logging levels</a>
that helped me correct something I had misunderstood.</p>
<p><a href="http://rhodesmill.org/brandon/2012/logging_tree/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Adventure in Python 3</title>
      <link>http://rhodesmill.org/brandon/2012/adventure/</link>
      <pubDate>Fri, 06 Apr 2012 03:02:10 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2012/adventure/</guid>
      <description>Adventure in Python 3</description>

      <content:encoded><![CDATA[<div class="document">
<p>I have just released
<a class="reference external" href="http://pypi.python.org/pypi/adventure/1.2/">adventure&nbsp;1.2</a>
on the Python Package Index,
an update of my Python&nbsp;3 port
of the original Colossal Cave Adventure game
that I announced more than a year ago during the final round of
<a class="reference external" href="http://pyvideo.org/video/357/pycon-2011--sunday-afternoon-lightning-talks">PyCon 2011 lightning talks</a>.</p>
<a class="reference external image-reference" href="http://www.flickr.com/photos/brandonrhodes/6115627693/"><img alt="http://rhodesmill.org/brandon/2012/adventure-heathkit-h19.jpg" src="http://rhodesmill.org/brandon/2012/adventure-heathkit-h19.jpg" /></a>
<p>Written in the late 1970s,
“Adventure” was the first game
to offer players a virtual world to explore at their own pace,
driven by their own curiosity.
The player directs the game with simple one- and two-word commands
like <tt class="docutils literal">ENTER</tt> <tt class="docutils literal">BUILDING</tt> and <tt class="docutils literal">GET</tt> <tt class="docutils literal">LAMP</tt>,
together with the cardinal directions —
which can, mercifully, be typed as abbreviations
(<tt class="docutils literal">N</tt>, <tt class="docutils literal">NE</tt>, <tt class="docutils literal">E</tt>, <tt class="docutils literal">SE</tt>, and so forth,
with <tt class="docutils literal">U</tt> and <tt class="docutils literal">D</tt> for up and down).
Based on a real-life section
of the Flint-Mammoth cave system in Kentucky
that the original author helped map,
“Adventure” invites you to start collecting treasures from the cave
in a quest that eventually involves danger, magic,
and even encounters with a few computer-controlled characters,
who rustle in the darkness beyond the light of your lamp
before finally pouncing.</p>
<p>Keep reading if you want to learn
about several discoveries that I made
while porting “Adventure” to Python!
If you want to know more about the history of the original game itself,
I recommend Dennis G.&nbsp;Jerz's admirably thorough paper
“<a class="reference external" href="http://www.digitalhumanities.org/dhq/vol/001/2/000009/000009.html">Somewhere Nearby is Colossal Cave: Examining Will Crowther's Original ‘Adventure’ in Code and in Kentucky</a>”
from the Summer 2007 issue of the Digital Humanities Quarterly.</p>
<div class="section" id="playing-at-the-prompt">
<h2>Playing at the prompt</h2>
<p>I was inspired to write the <tt class="docutils literal">adventure</tt> package
when I realized that typing a name at the Python prompt
could invoke an action if the object it referenced
did something useful inside of its <tt class="docutils literal">__repr__()</tt> method.</p>
<p><a href="http://rhodesmill.org/brandon/2012/adventure/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>One sentence per line, please</title>
      <link>http://rhodesmill.org/brandon/2012/one-sentence-per-line/</link>
      <pubDate>Tue, 03 Apr 2012 01:25:09 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[document processing]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2012/one-sentence-per-line/</guid>
      <description>One sentence per line, please</description>

      <content:encoded><![CDATA[<div class="document">
<p>I give some advice each year
in my annual <a class="reference external" href="http://sphinx.pocoo.org/">Sphinx</a> tutorial
at <a class="reference external" href="https://us.pycon.org/">PyCon</a>.
A&nbsp;grateful student asked where I myself had learned the tip.
I&nbsp;have done some archæology and finally have an answer.
Let me share what I teach them about “semantic linefeeds,”
then I will reveal its source —
which turns out to have been written
when I was only a few months old!</p>
<p>In the tutorial,
I ask students whether or not
the Sphinx text files in their project will be read by end-users.
If not, then I encourage students to treat the files
as private “source code” that they are free to format semantically.
Instead of fussing with the lines of each paragraph
so that they all end near the right margin,
they can add linefeeds anywhere
that there is a break between ideas.</p>
<p>The result can be spectacular.</p>
<p><a href="http://rhodesmill.org/brandon/2012/one-sentence-per-line/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Counting, without counting, in Python</title>
      <link>http://rhodesmill.org/brandon/2012/counting-without-counting/</link>
      <pubDate>Fri, 30 Mar 2012 23:34:38 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2012/counting-without-counting/</guid>
      <description>Counting, without counting, in Python</description>

      <content:encoded><![CDATA[<div class="document">
<p>It often irks me
that the normal Python pattern for running the body of a loop <em>n</em> times
results in the allocation and destruction of <em>n</em> integer objects,
even if the body of the loop does not need them.</p>


<div class="pygments_murphy"><pre><span class="c"># Creates one million integers</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1000000</span><span class="p">):</span>
    <span class="k">print</span>

<span class="c"># Creates them one at a time</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="mi">1000000</span><span class="p">):</span>
    <span class="k">print</span>
</pre></div>



<p>Yes, I know, you will rightly complain that I am too easily irked.
The <tt class="docutils literal">range()</tt> pattern is standard.
The pattern is simple.
The pattern is easy to read.
The implementation is really quite fast
compared to any real work that I might do in the loop.
And, in the bright future when we all use PyPy,
the extra million integer objects will be optimized away anyway.</p>
<p><a href="http://rhodesmill.org/brandon/2012/counting-without-counting/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Walking to PyCon on your own two feet</title>
      <link>http://rhodesmill.org/brandon/2012/walking-to-pycon/</link>
      <pubDate>Tue, 13 Mar 2012 02:59:10 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <guid>http://rhodesmill.org/brandon/2012/walking-to-pycon/</guid>
      <description>Walking to PyCon on your own two feet</description>

      <content:encoded><![CDATA[<div class="document">
<p>Before arranging for a cab ride or airport shuttle,
have you considered that your own body is designed
for traveling long distances under load?</p>
<p>Last Tuesday I simply walked the 5&nbsp;miles (8&nbsp;km)
from the San Jose Airport
to the <a class="reference external" href="https://us.pycon.org/2012/">PyCon 2012</a> venue.
My route included a stream lined with willow trees,
a beautiful nature preserve whose educational displays
used wonderful words like “chaparral,”
and a glimpse at the games that employees get to play
in the back yards of Silicon Valley companies.</p>
<a class="reference external image-reference" href="http://www.flickr.com/photos/brandonrhodes/6980374449/"><img alt="http://rhodesmill.org/brandon/2012/guadalupe-river.jpg" src="http://rhodesmill.org/brandon/2012/guadalupe-river.jpg" /></a>
<p>What could happen next year,
if more people were interested in walking —
could we designate a meeting place at the airport,
and have a group of PyCon walkers leaving every hour
to enjoy the journey together?</p>
<div class="section" id="mile-nature-route-from-sjc-to-pycon">
<h2>5.1-mile nature route from SJC to PyCon</h2>
<p>Several people have expressed interest in my walk,
so here is a map and details about the route.
I&nbsp;will be walking back to the airport on Wednesday morning —
probably, judging from the forecast, in my wet-weather gear!</p>
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps/ms?msa=0&amp;msid=202077053206811834443.0004bb22a1b15ecd9f7e5&amp;ie=UTF8&amp;t=m&amp;ll=37.388448,-121.953469&amp;spn=0.037596,0.048357&amp;output=embed"></iframe><br /><small>View <a href="http://maps.google.com/maps/ms?msa=0&amp;msid=202077053206811834443.0004bb22a1b15ecd9f7e5&amp;ie=UTF8&amp;t=m&amp;ll=37.388448,-121.953469&amp;spn=0.037596,0.048357&amp;source=embed" style="color:#0000FF;text-align:left">Walking to PyCon in Santa Clara</a> in a larger map</small><ul class="simple">
<li>Exit the airport, walk across both lanes of Airport Boulevard,
and you should find a bicycle trail that runs alongside it.
Turn left (north) and start walking along this trail.</li>
<li>When you get to the sign that forbids you from walking farther,
you are ready to turn off of Airport Boulevard.
There should be a bridge to your right
that crosses the Guadalupe River
and then enters a gated parking lot.
Cross the bridge and, instead of entering the parking lot,
take the ramp to your right that descends the bank toward the river,
doubles back, and heads north under the bridge
along the east riverbank.</li>
</ul>
<iframe width="425" height="350" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="http://maps.google.com/maps/ms?msa=0&amp;msid=202077053206811834443.0004bb22a1b15ecd9f7e5&amp;ie=UTF8&amp;t=m&amp;source=embed&amp;ll=37.388448,-121.953469&amp;spn=0.037596,0.048357&amp;layer=c&amp;cbll=37.372909,-121.932852&amp;panoid=nenoPhwA46NeRw114_FKlA&amp;cbp=12,4.01,,1,2.7&amp;output=svembed"></iframe><br /><small>The bridge that turns right off of Airport Drive, crosses the Guadalupe River, and connects to the Guadalupe River Trail. You can see the Trail running right to left beneath the bridge.</small><ul class="simple">
<li>The first stretch of the trail is a bit bleak —
there is some green, but also many views of concrete.
You will pass under several bridges as cars roar above you,
including both bridges for US-101.
When you reach the bridge at Trimble Road,
you will learn a pattern that continues for the rest of the trail:
at each road crossing the bicycle trail
splits, with the right fork climbing to meet (and cross) the road,
while the left fork passes under the bridge
so bicycles can avoid dodging traffic.
Unless there is high water, always go under the bridges.</li>
<li>The long stretch between Trimble Road and the Montague Expressway
is more scenic — here, at last, is where I really relaxed
and something deep inside of me cried, “California!”
Mountains should be visible in the distance to either side.
Closer at hand you will see the landscaped campuses
of several technology companies.
If you are there around lunchtime, as I was,
you will see employees playing volleyball, basketball,
throwing frisbees, and running on well-manicured trails.
It will all look very idyllic.
Again, “California!”</li>
<li>But the real treat comes as you reach the pedestrian bridge
where River Oaks Parkway dead-ends into the river.
Turn left and cross the Guadalupe on this bridge,
turn turn right to continue your hike north past Thamien Park.
Soon, you will approach the Ulistac Natural Area.
The area around the river becomes even greener,
with numerous willow trees swaying in the breeze.
(The photo earlier in the article is from this section of the trail.)</li>
<li>Entering the Ulistac Natural Area was tricky.
There was construction,
with only a narrow path cutting down to the left
between chain-link fences,
from the height of the bicycle trail
to the level of the river bottoms.
But I found my way down,
and Ulistac is was really wonderful —
there are educational displays about the natural habitat,
and several areas where native plants were being grown
and protected.
If you have time, walk slowly and learn more
about the natural landscape in this area of California.</li>
<li>Wind your way through Ulistac
until you come to Lick Mill Boulevard,
turn right, and you will finally reach Tasman Drive.</li>
<li>The last segment of the walk is less scenic.
Turn left and walk west along Tasman Drive
until you reach the Hyatt and Convention Center.
Keep your eyes out for the restaurants on the north side of Tasman;
you might be walking back here during PyCon to have dinner!
As you climb the overpass where Tasman crosses Lafayette,
you will see the Santa Clara golf course ahead to your right
and the roller coasters of Great America against the sky to your left —
and, of course, yet another great view
of the mountains behind and in front of you.
The front entrance of the Convention Center on your right
will be the first PyCon venue that you reach
once you are past the golf course,
and the Hyatt and Hilton themselves come next.</li>
</ul>
<p>Attempt the hike
only if you are familiar with walking similar distances at home,
if you are sure that you can carry your luggage,
and if you bring a water bottle or snack if you will need one.
My
<a class="reference external" href="http://www.amazon.com/dp/B003JZCQV4/ref=asc_df_B003JZCQV41934945">Rick Steves Convertible Carry On</a>
has built-in shoulder straps that convert it into a backpack,
which was ideal.
But if your bag has wheels you will probably find the trail
unmanageable, since most of it is surfaced with gravel.
Remember that even if you take more conventional transport to PyCon,
you can always take a break later,
walk east along Tasman to the Ulistac Natural Area,
and enjoy this bit of beauty that Santa Clara offers!</p>
</div>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>JavaScript Breaks Math</title>
      <link>http://rhodesmill.org/brandon/2012/js/</link>
      <pubDate>Sun, 15 Jan 2012 02:59:10 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2012/js/</guid>
      <description>JavaScript Breaks Math</description>

      <content:encoded><![CDATA[<div class="document">
<p>Why do we Python programmers
stay so annoyed with JavaScript's broken <tt class="docutils literal">this</tt> keyword?
After all, every programming language has rough edges.
The problem with <tt class="docutils literal">this</tt> even turns out to be easy to work around
once you learn the knack.
So why does it feel like JavaScript has committed a fresh offense
every time we trip over&nbsp;it?</p>
<p>The answer, I suggest, is that JavaScript manages to disturb
very deep mental scaffolds
with the behavior of the <tt class="docutils literal">this</tt> keyword.
Not all programming language annoyances are created equal.
Some involve inconsistency within a language itself,
when a pattern set up by one feature is broken by another
(think of method names in the Python Standard Library).
More serious issues can involve hassles with a language's syntax
or poor behaviors within its type system.
But in this case JavaScript decided
that it would abandon a key property
of the system that lies <em>beneath</em> it —
that it would break the conventions that,
in fact, underlie all programming languages.</p>
<p>JavaScript decided that it would break <em>mathematics.</em></p>
<p>Let me explain by starting with a simple example.
You are already familiar with operator precedence,
and how multiplication binds more tightly than
addition when both operators appear in the same expression.
In the following expression,
<em>a</em> will first be multiplied with <em>b</em>,
then the result of that operation will be added to <em>c</em>.</p>
<div class="line-block">
<div class="line">(1)</div>
<div class="line"><em>n</em> = <em>a</em> × <em>b</em> + <em>c</em></div>
</div>
<p>There is, in other words,
a hidden intermediate result inside of this equation:
the result of the multiplication.
So&nbsp;(1) is, in fact, a shorthand
for writing this sequence of two separate binary operations:</p>
<div class="line-block">
<div class="line">(2)</div>
<div class="line"><em>x</em> = <em>a</em> × <em>b</em></div>
<div class="line"><em>n</em> = <em>x</em> + <em>c</em></div>
</div>
<p>Note that our ability to transform (1) into the pair of lines (2)
does not involve any special properties of the operators themselves.
This does <em>not</em> illustrate some special feature
of multiplication or addition,
like the Distributive Property!
Instead, we are working down at the lower and more fundamental level
of asking what a complex math expression even <em>means</em>.
So while we must use argument and proof
to learn that addition is commutative,
the operators and their precedence are simply
a matter of <em>definition</em> —
of what we decide it means when we string symbols together
to form an expression in the first place.</p>
<p>Now it turns out that the familiar programming language idiom
of calling a method in a language like Python or JavaScript
is quite precisely analogous to expression&nbsp;(1),
because it separates three symbols
with a pair of binary operators,
where the left operator binds most tightly:</p>


<div class="pygments_murphy"><pre><span class="p">(</span><span class="mi">3</span><span class="p">)</span>   <span class="n">n</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">b</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
</pre></div>



<p>Until a programmer really grasps what it means
for a language to have “first-class functions” —
functions that can themselves be manipulated as values —
it might be difficult to see that <tt class="docutils literal">a.b</tt>
makes quite good sense simply standing by itself.
It means “take the <tt class="docutils literal">a</tt> object,
look and see whether it has an attribute named <tt class="docutils literal">b</tt>,
and resolve the value of that attribute.”
And so <tt class="docutils literal">a.b</tt> works perfectly in front of <tt class="docutils literal">(c)</tt>
so long as the result of the attribute lookup
happens to return a callable.</p>
<p>So expression (3) can be decomposed like expression (1),
and in Python the following two steps are
exactly equivalent to statement (3) —
except, of course, for defining an extra local variable <tt class="docutils literal">fn</tt>:</p>


<div class="pygments_murphy"><pre><span class="p">(</span><span class="mi">4</span><span class="p">)</span>    <span class="n">fn</span> <span class="o">=</span> <span class="n">a</span><span class="o">.</span><span class="n">b</span>
       <span class="n">n</span> <span class="o">=</span> <span class="n">fn</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
</pre></div>



<p>This is, again, simply a property of how expressions work in math —
of the fact that you ought to be able to compute intermediate results
by pulling an expression apart into its constituent binary operations.
But, alas, JavaScript decided to break this property of expressions,
and makes extra invisible magic happen
when the two operators are used in combination —
magic that does not happen when they are separated into separate steps.
Or, perhaps there is a more interesting way to think about it:</p>


<div class="pygments_murphy"><pre><span class="cm">/* In JavaScript this is NOT a pair of binary operations. It is a SINGLE</span>
<span class="cm">   ternary operator that, to sow confusion among programmers, happens to</span>
<span class="cm">   use the same symbols as two well-known binary operations. */</span>

<span class="nx">a</span><span class="p">.</span><span class="nx">b</span><span class="p">(</span><span class="nx">c</span><span class="p">);</span>

<span class="cm">/* This ternary operator is roughly equivalent to: */</span>

<span class="kd">var</span> <span class="nx">fn</span> <span class="o">=</span> <span class="nx">a</span><span class="p">.</span><span class="nx">b</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">old_this</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">this</span> <span class="o">=</span> <span class="nx">a</span><span class="p">;</span>
<span class="nx">fn</span><span class="p">(</span><span class="nx">c</span><span class="p">);</span>
<span class="k">this</span> <span class="o">=</span> <span class="nx">old_this</span><span class="p">;</span>
</pre></div>



<p>Younger programmers,
for whom <tt class="docutils literal">a.b(c)</tt> is simply a gesture,
may find our distaste for JavaScript's behavior inexplicable.
The problem is worst
for the experienced programmer or mathematician,
who — every time she types it —
remembers what the dot and parentheses really mean
as clean and separate operations,
but has to remember that their meanings change
when they appear in combination.
This semantic instability flaunts a very long tradition
of defining math operators
so that expressions can be composed together
and broken down again
without changing their meaning.</p>
<p>And that, I think, is why it annoys us:
because from early grade school through college
we have learned that math expressions compose and decompose cleanly,
and JavaScript takes that symmetry away.</p>
<p>One last note for newer Python programmers reading this:
you might be suspecting that Python itself has some kind of magic
involved here, because how else could it remember later
whether you had pulled method <tt class="docutils literal">fn</tt>
off of the specific object <tt class="docutils literal">a</tt>
instead of off some other instance of that class?
The answer is that every lookup of an instance method
returns a new object, called a <em>bound method</em>,
that remembers the object on which the lookup took place.</p>
<pre class="doctest-block">
&gt;&gt;&gt; class C:
...     def __init__(self, n):
...         self.n = n
...     def __repr__(self):
...         return 'C%d' % self.n
...     def fn(self, m):
...         return self.n + m
...
&gt;&gt;&gt; a = C(100)
&gt;&gt;&gt; b = C(220)
&gt;&gt;&gt; a.fn
&lt;bound method C.fn of C100&gt;
&gt;&gt;&gt; b.fn
&lt;bound method C.fn of C220&gt;
&gt;&gt;&gt; b.fn(5)
225
</pre>
<p>What about your own least favorite language features,
whether in JavaScript, Python, or something else?
Are they all simply about scruples and inconvenience?
Or can you identify some deep-seated assumptions
of your own mental scaffolding
that keep ruining your experience with a specific language?
Let us know in the comments!</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Why am I going to CodeMash?</title>
      <link>http://rhodesmill.org/brandon/2012/codemash/</link>
      <pubDate>Tue, 10 Jan 2012 22:40:55 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2012/codemash/</guid>
      <description>Why am I going to CodeMash?</description>

      <content:encoded><![CDATA[<div class="document">
<p>By this time tomorrow I will doubtless be wearing swimming trunks —
in northern Ohio — <em>in winter</em> —
while listening to people rave about Java and C# and Ruby
and wondering what I have gotten myself into.
I&nbsp;will be at <a class="reference external" href="http://codemash.org/">CodeMash</a>,
a conference that was started by developers
who wanted an event that focused solely on the programmer
while including a wide range of languages and technologies.</p>
<a class="reference external image-reference" href="http://www.flickr.com/photos/irisphotos/6668819779/"><img alt="Kalahari Water Park in Sandusky, Ohio" src="http://farm8.staticflickr.com/7149/6668819779_081cc16758_m.jpg" style="width: 240px; height: 159px;" /></a>
<p>It was lucky that I signed up
the moment that CodeMash 2012 registration opened back in October,
because the 1,200 conference tickets
sold out in only <strong>20 minutes</strong> —
no event in the Python community
had prepared me for that kind of demand!</p>
<p>I&nbsp;learned about CodeMash conference from its co-founder
<a class="reference external" href="http://brianhprince.com/">Brian Prince</a>
when we were fellow speakers at <a class="reference external" href="http://pyohio.org/">PyOhio</a> last July.
So why did a Python programmer like me decide to attend?</p>
<ul class="simple">
<li>Even though the technologies that Brian chooses
are different from mine,
he is clearly animated by the same passion
for combining good code with good community.
If his co-founders are at all like him,
then I knew that a great event was in the works.</li>
<li>I want to learn another conference's culture.
For example, I was stunned to see strong suggestions
on the CodeMash mailing list
that attendees should <em>not</em> carry laptops —
instead, they recommend pencil, paper,
and something they call
<a class="reference external" href="http://www.dachisgroup.com/2011/12/the-sketchnote-revolution/">Sketchnotes</a>.
Since good teachers have a reflex
that makes them try to bring the whole audience along with them
as they make a point,
we could actually be slowing up PyCon speakers
when half the audience is face-down typing
and clearly a half step behind what is being said.</li>
</ul>
<a class="reference external image-reference" href="http://www.flickr.com/photos/alan_barber/4277666916/"><img alt="CodeMash 2010" src="http://farm3.staticflickr.com/2713/4277666916_9fd2ec0fb6_m.jpg" style="width: 180px; height: 240px;" /></a>
<ul class="simple">
<li>I could predict that moving to
<a class="reference external" href="http://en.wikipedia.org/wiki/Bluffton,_Ohio">Bluffton, Ohio</a>,
as winter descended
would leave me with very few opportunities
to meet other developers.
After several weeks of being the only programmer I know,
a&nbsp;large regional conference
will let me bask in the company
of other people who understand what I do for a living.</li>
<li>It is too easy to judge other languages
by what I think are drawbacks in their design,
or by the poor code that most programmers produce
whatever their language.
I&nbsp;want see what excites the real experts
who solve interesting problems using Java, Ruby, and C# —
people who use those languages to the hilt, and do a great job of&nbsp;it.</li>
<li>Being evangelized by smart people is interesting and humbling,
if you let down your guard and really listen.
And hearing Ruby and C# people explain the glories of their languages
will remind me of how I must sound
when I hold forth on the advantages of Python,
or <a class="reference external" href="http://www.gnu.org/software/emacs/">Emacs</a>,
or <a class="reference external" href="http://www.vibramfivefingers.com/">Vibram Fivefingers</a>.</li>
</ul>
<a class="reference external image-reference" href="http://www.flickr.com/photos/alan_barber/4277668868/"><img alt="CodeMash 2010" src="http://farm5.staticflickr.com/4055/4277668868_002df3fc6e_m.jpg" style="width: 240px; height: 180px;" /></a>
<ul class="simple">
<li>Brian wants to make CodeMash more popular for Python programmers —
and a few luminaries like Bruce Eckel, Mike Pirnat, and Mark Ramm
are already on the schedule this year.
Next year I might offer to speak.
But first I wanted to show up and just listen,
figure out the vibe of the conference,
and learn more about what is happening
outside of the Python community.</li>
<li>Finally, it does sound like great fun:
eating, drinking, and being merry
at an <a class="reference external" href="http://www.kalahariresorts.com/oh/">indoor water park resort</a>
in the middle of an Ohio winter.
Kalahari, here I come!</li>
</ul>
<p>(Images are Creative Commons licensed from Flickr photographers
<a class="reference external" href="http://www.flickr.com/photos/irisphotos/">iriskh</a>
and
<a class="reference external" href="http://www.flickr.com/photos/alan_barber/">Alan.Barber</a>.)</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Concentric CSS</title>
      <link>http://rhodesmill.org/brandon/2011/concentric-css/</link>
      <pubDate>Sat, 10 Sep 2011 02:22:46 EDT</pubDate>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2011/concentric-css/</guid>
      <description>Concentric CSS</description>

      <content:encoded><![CDATA[<div class="document">
<p>(My official Concentric CSS “style.css” is in a
<a class="reference external" href="https://github.com/brandon-rhodes/Concentric-CSS/">GitHub repository</a>)</p>
<p>Perhaps my mind is unusually visual,
but I have no idea how people clearly picture the effects of their CSS rules
when following the common advice
to sort their properties alphabetically within each declaration block
(as in the answers to
<a class="reference external" href="http://stackoverflow.com/questions/4878655/conventional-order-of-css-attributes">this Stack Overflow question</a>).</p>
<p>The main alternative to alphabetization seems to be a
<a class="reference external" href="http://fordinteractive.com/2009/02/order-of-the-day-css-properties/">CSS property order that claims to be based on the box model</a>
but which tackles properties in a sadly haphazard order.
It starts with <tt class="docutils literal">display</tt> and <tt class="docutils literal">position</tt>,
which are a great start,
but these are immediately followed by the <tt class="docutils literal">height</tt> and <tt class="docutils literal">width</tt> —
even though these dimensions only apply to the content,
which is nestled down inside the deepest level of the box!
The order then continues to skip around wildly,
jumping outside the box to talk about the margins,
then jumping almost all the way back inside
to talk about the padding.
Finally it gets to the borders,
even though they will actually be sandwiched
<em>between</em> the margins and the padding
when rendered by the browser.</p>
<p>For reference, here is the box model
as illustrated in the CSS standard itself:</p>
<img alt="http://www.w3.org/TR/CSS2/images/boxdim.png" src="http://www.w3.org/TR/CSS2/images/boxdim.png" />
<p>The fact that <tt class="docutils literal">width</tt> and <tt class="docutils literal">height</tt> apply only to the content,
and not to the padding or anything else,
is a crucial issue in CSS —
an issue that causes newcomers a lot of grief.
For everyone's sanity,
I&nbsp;need the order in which I declare properties
to reflect the structure of the box itself,
with the <tt class="docutils literal">width</tt> and <tt class="docutils literal">height</tt> coming after
the decorations that wrap around them.</p>
<p>I call the result <strong>Concentric CSS</strong>
and the basic template looks something like this:</p>


<div class="pygments_murphy"><pre><span class="p">{</span>
    <span class="k">display</span><span class="o">:</span> <span class="p">;</span>    <span class="c">/* Where and how the box is placed */</span>
    <span class="k">position</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">float</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">clear</span><span class="o">:</span> <span class="p">;</span>

    <span class="k">visibility</span><span class="o">:</span> <span class="p">;</span> <span class="c">/* Can the box be seen? */</span>
    <span class="k">opacity</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">z-index</span><span class="o">:</span> <span class="p">;</span>

    <span class="k">margin</span><span class="o">:</span> <span class="p">;</span>     <span class="c">/* Layers of the box model */</span>
    <span class="k">outline</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">border</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">background</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">padding</span><span class="o">:</span> <span class="p">;</span>

    <span class="k">width</span><span class="o">:</span> <span class="p">;</span>      <span class="c">/* Content dimensions and scrollbars */</span>
    <span class="k">height</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">overflow</span><span class="o">:</span> <span class="p">;</span>

    <span class="k">color</span><span class="o">:</span> <span class="p">;</span>      <span class="c">/* Text */</span>
    <span class="k">text</span><span class="o">:</span> <span class="p">;</span>
    <span class="k">font</span><span class="o">:</span> <span class="p">;</span>
<span class="p">}</span>
</pre></div>



<p>Are you surprised that I sandwiched <tt class="docutils literal">background</tt>
between the border and padding instead of saving it until later?
My reasoning is that the <tt class="docutils literal">padding</tt> is the first part of the box
that actually gets painted with the background color —
I have positioned <tt class="docutils literal">background</tt> so that everything beneath it
gets the background color, while everything above has its own
color (borders) or is transparent (margins).</p>
<p>I am not certain about my choice
of where to place the <tt class="docutils literal">overflow</tt> property.
Its current position is dictated by the fact that it is often triggered
by too small a height and width —
so it often serves as a kind of “else clause”
to say what should happen if the height and width
are too constraining, and so the property makes sense next to them.
But one of the consequences of <tt class="docutils literal">overflow</tt> can be
that scrollbars appear around the box,
and an argument could be made for putting <tt class="docutils literal">overflow</tt>
up between the borders and padding,
because that is exactly the place where
<a class="reference external" href="http://www.w3.org/TR/CSS2/visufx.html#propdef-overflow">the standard</a>
insists that scrollbars be drawn.</p>
<p>For the sake of completeness
I have written up my preferred property order —
with a much more exhaustive list of properties
than in the sketch shown above —
as a
<a class="reference external" href="https://github.com/brandon-rhodes/Concentric-CSS/blob/master/style.css">style.css</a>
file that lives in its own
<a class="reference external" href="https://github.com/brandon-rhodes/Concentric-CSS/">GitHub repository</a>.
I&nbsp;welcome comments and improvements,
especially ones that will make this ordering
an even better reflection of the box model.
I want my CSS to make as much sense as possible
both to the newcomer as well as the seasoned professional!</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Adding Compass to your project</title>
      <link>http://rhodesmill.org/brandon/2011/adding-compass/</link>
      <pubDate>Fri, 13 May 2011 10:09:46 EDT</pubDate>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2011/adding-compass/</guid>
      <description>Adding Compass to your project</description>

      <content:encoded><![CDATA[<div class="document">
<p>The <a class="reference external" href="http://compass-style.org/">Compass CSS authoring framework</a>
has become one of the standard tools
that gets installed when I start working on a new web application.
I&nbsp;always version-control
not only the <tt class="docutils literal">.scss</tt> Sass source files that I myself write,
but also the <tt class="docutils literal">.css</tt> CSS files that Compass compiles from them.
That way, anyone who checks out the project
immediately gets a working web site
without having to install Compass —
or even having to know that it exists,
if they are not themselves involved in writing the CSS.</p>
<p>But those of us who work on the CSS do need Compass,
so I have a standard technique that I copy from project to project
that installs Compass into a small, local Ruby environment,
providing the same kind of isolation and reproducibility
that Python has taught me to know and love
thanks to <a class="reference external" href="http://www.virtualenv.org/">virtualenv</a>.</p>
<p>The process goes like this.</p>
<p>First I create a <tt class="docutils literal">compass/</tt> directory,
typically up at the top level of the project,
that initially contains nothing but a pair of shell scripts.
The first script, <tt class="docutils literal">install.sh</tt>, knows how to get Compass
downloaded and installed:</p>


<div class="pygments_murphy"><pre><span class="c">#!/bin/bash</span>
<span class="c"># compass/install.sh - install Compass under the &quot;./Gem&quot; directory</span>

<span class="k">if</span> ! which gem &gt;/dev/null ;<span class="k">then</span>
<span class="k">    </span><span class="nb">echo</span> <span class="s1">&#39;Error: no &quot;gem&quot; command available&#39;</span>
    <span class="nb">echo</span> <span class="s1">&#39;Please &quot;sudo aptitude install rubygems1.8&quot; or &quot;ruby1.9.1&quot;&#39;</span>
    <span class="nb">exit </span>1
<span class="k">fi</span>
<span class="nv">BASE</span><span class="o">=</span><span class="k">$(</span>dirname <span class="k">$(</span>readlink -f <span class="k">$(</span>which <span class="s2">&quot;$0&quot;</span><span class="k">)))</span>
<span class="nb">cd</span> <span class="nv">$BASE</span>  <span class="c"># the directory where this script lives</span>
gem install -i Gem compass
gem install -i Gem compass-susy-plugin
</pre></div>



<p>When this shell script is run, a <tt class="docutils literal">compass/Gem/</tt> directory
gets created with the <tt class="docutils literal">compass</tt> command down inside of it.
To let me forget where the binary is located
and how it can be safely invoked,
a second shell script named <tt class="docutils literal">compass.sh</tt> wraps up the details:</p>


<div class="pygments_murphy"><pre><span class="c">#!/bin/bash</span>
<span class="c"># compass/compass.sh - properly invoke the &quot;Compass&quot; program</span>

<span class="nv">BASE</span><span class="o">=</span><span class="k">$(</span>dirname <span class="k">$(</span>readlink -f <span class="k">$(</span>which <span class="s2">&quot;$0&quot;</span><span class="k">)))</span>
<span class="nb">export </span><span class="nv">GEM_HOME</span><span class="o">=</span><span class="nv">$BASE</span>/Gem
<span class="nb">export </span><span class="nv">RUBYLIB</span><span class="o">=</span><span class="nv">$BASE</span>/Gem/lib
<span class="nv">$BASE</span>/Gem/bin/compass <span class="s2">&quot;$@&quot;</span>
</pre></div>



<p>I always tell my version-control system
to ignore the <tt class="docutils literal">compass/Gem/</tt> directory
and the 5,115 files that Ruby creates beneath it;
instead, I simply remember to re-run <tt class="docutils literal">install.sh</tt>
after each fresh checkout
when I want to get to work on the CSS.</p>
<p>When I first start a project,
I need an initial set of <tt class="docutils literal">.scss</tt> files to start editing,
which can be supplied through the Compass command <tt class="docutils literal">create</tt>.
Usually I want the CSS output to be written
somewhere outside of the <tt class="docutils literal">compass/</tt> directory,
so my initialization steps go something like this:</p>
<pre class="literal-block">
$ cd compass/
$ ./install.sh
$ ./compass.sh create
$ rm -r stylesheets/    # where Compass wanted the output CSS!
$ emacs config.rb
# There, I adjust the line: css_dir = &quot;../webapp/static/css&quot;
# Plus, I also tend to set: line_comments = false
# Of course, use your editor-of-choice for this step!
</pre>
<p>I check into version control the <tt class="docutils literal">config.rb</tt> file
and the <tt class="docutils literal">compass/src/</tt> directory of pristine <tt class="docutils literal">.scss</tt> files.
I tell my version-control system to ignore
the <tt class="docutils literal"><span class="pre">.sass-cache/</span></tt> directory that gets created inside of <tt class="docutils literal">compass/</tt>
each time the CSS is rebuilt.</p>
<p>Once those changes checked in,
I never need to run the <tt class="docutils literal">create</tt> command again
for the whole lifetime of the project.
Instead, whenever I am ready to work on the CSS,
I simply open the <tt class="docutils literal">.scss</tt> files in my editor
and in another window I do this:</p>
<pre class="literal-block">
$ cd compass/
$ ./compass.sh watch
</pre>
<p>Just as a good development web server
will auto-restart when you finish editing a file and hit <em>Save</em>,
the Compass <tt class="docutils literal">watch</tt> command will sit patiently all day
and re-compile your Sass files to CSS whenever it sees you change them.
By leaving it running, I can edit a <tt class="docutils literal">.scss</tt> file
and then hit <em>Reload</em> in my browser almost immediately to see the result
without having to stop and run any intermediate commands.</p>
<p>The files, therefore, that wind up in my version control are these:</p>
<pre class="literal-block">
compass/compass.sh
compass/config.rb
compass/install.sh
compass/src/_base.scss
compass/src/_defaults.scss
compass/src/ie.scss
compass/src/print.scss
compass/src/screen.scss
</pre>
<p>And, of course, I also version-control
the CSS files that Compass writes as output,
over where I put them in the “main directory” of my web application:</p>
<pre class="literal-block">
webapp/static/css/ie.css
webapp/static/css/print.css
webapp/static/css/screen.css
</pre>
<p>This all works out extremely well.
Normal developers and deployers look under the <tt class="docutils literal">webapp/</tt> directory
and see what looks like normal,
if preternaturally well-written and organized,
CSS files exactly where they expect to find them.
Only we CSS geeks on the project
know that they are written by shuffling over to the Compass directory
and firing up a program that compiles them from simpler source files.
And thanks to my handy little pair of shell scripts,
the Compass install itself is always completely automated.</p>
<p>Of course, as you can tell from the error message
that <tt class="docutils literal">install.sh</tt> prints if it cannot find Ruby,
these scripts are aimed at an audience using Ubuntu or Debian.
Please note in your comments to this post
how you might expand those instructions
to help people using Fedora, MacOS&nbsp;X, or other operating systems!</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Mounting WSGI Applications Under CherryPy</title>
      <link>http://rhodesmill.org/brandon/2011/wsgi-under-cherrypy/</link>
      <pubDate>Wed, 04 May 2011 23:00:28 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2011/wsgi-under-cherrypy/</guid>
      <description>Mounting WSGI Applications Under CherryPy</description>

      <content:encoded><![CDATA[<div class="document">
<p>Today I got stuck between a rock and hard place —
or, more specifically, stuck between the assumptions
of Robert Brewer and those of Ian Bicking.
In case you ever try mounting a WSGI application
underneath a larger CherryPy application,
here is the story.</p>
<div class="section" id="simple-wsgi-grafting">
<h2>Simple WSGI grafting</h2>
<p>Robert Brewer's <a class="reference external" href="http://www.cherrypy.org/">CherryPy</a> is a Python web framework
of the controllers-and-methods variety.
CherryPy has a long, solid track record,
and is especially well-known
for shipping with a built-in production-quality web server.
The server is so good that it is sometimes used standalone,
without the actual CherryPy framework behind it,
to serve other Python web applications through their WSGI callable:</p>


<div class="pygments_murphy"><pre><span class="c"># Easy: putting a WSGI `app` behind the CherryPy HTTP server</span>

<span class="n">server</span> <span class="o">=</span> <span class="n">CherryPyWSGIServer</span><span class="p">((</span><span class="s">&#39;0.0.0.0&#39;</span><span class="p">,</span> <span class="mi">8001</span><span class="p">),</span> <span class="n">app</span><span class="p">,</span> <span class="n">numthreads</span><span class="o">=</span><span class="mi">30</span><span class="p">)</span>
<span class="n">server</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</pre></div>



<p>Sometimes, however, it is nice to have the entire CherryPy
web framework running —
not merely its HTTP server —
in combination with an existing WSGI application.
This arrangement makes it easy to do things like
provide static resources
alongside more dynamic content generated in Python:</p>


<div class="pygments_murphy"><pre><span class="c"># More interesting: mounting `app` beneath a particular URL path</span>
<span class="c"># This works, but `app` gets no logging or error handling</span>

<span class="n">cherrypy</span><span class="o">.</span><span class="n">tree</span><span class="o">.</span><span class="n">graft</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="s">&#39;/api&#39;</span><span class="p">)</span>
<span class="n">cherrypy</span><span class="o">.</span><span class="n">tree</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="bp">None</span><span class="p">,</span> <span class="s">&#39;/static&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s">&#39;/&#39;</span> <span class="p">:</span> <span class="p">{</span>
    <span class="s">&#39;tools.staticdir.dir&#39;</span><span class="p">:</span> <span class="n">static_root</span><span class="p">,</span>
    <span class="s">&#39;tools.staticdir.on&#39;</span><span class="p">:</span> <span class="bp">True</span><span class="p">,</span>
    <span class="p">}})</span>
<span class="n">cherrypy</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">cherrypy</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">block</span><span class="p">()</span>
</pre></div>



<p>Although this arrangement works,
I soon received some unpleasant surprises.
When an exception was thrown inside of <tt class="docutils literal">app</tt>
the server never returned a response to the browser —
no <tt class="docutils literal">500 Internal Server Error</tt>,
no pretty traceback in development mode;
just a closed connection.
And neither errors nor successful requests inside of <tt class="docutils literal">app</tt>
resulted in access log messages;
CherryPy was completely silent about them.</p>
<p>This made it necessary for me to adjust my mental model
for how CherryPy operates.</p>
<p>I had always thought of the CherryPy framework
as having great big arms that wrapped around
my entire set of active controllers and applications,
so that it could catch exceptions and log HTTP requests
regardless of where in my tree they originated.
Now, however, I was forced to recognize
that the CherryPy <tt class="docutils literal">try…except</tt> exception catcher
and its logging handlers
must only get involved
when invoking a controller inside of a real CherryPy app.
If an HTTP request is instead being handed off
to a WSGI application of my own devising,
then CherryPy took no further responsibility
for what happened —
I was on my own.</p>
</div>
<div class="section" id="finding-wsgi-components">
<h2>Finding WSGI components</h2>
<p>Well, okay, I was not <em>really</em> on my own —
thanks to the wonderful Python community,
I sit surrounded by the rich and vibrant WSGI ecosystem
of well-supported interchangeable parts.
And logging and exception handling are standard features
that everyone needs, right?</p>
<p>Alas, the reality turned out to be far more murky.
After scouting about for some applicable WSGI
<a class="reference external" href="http://wsgi.org/wsgi/Middleware_and_Utilities">middleware and utilities</a>,
I started to sympathize with Python newbies
who complain about getting lost in the vast sea of broken software.
My long experience in the Python community
means that I often already know the “right tool” for the right situation,
which shields me from remembering what a mess Python newcomers face
when searching for even a simple solution.</p>
<p>For example, the popular <tt class="docutils literal">flup</tt> package's documentation
promised that <tt class="docutils literal">middleware.error</tt> contained an application
for catching WSGI application errors.</p>
<pre class="literal-block">
$ pip install flup
Downloading/unpacking flup...
$ python -c 'import flup.middleware'
Traceback (most recent call last):
  File &quot;&lt;string&gt;&quot;, line 1, in &lt;module&gt;
ImportError: No module named middleware
</pre>
<p>Drat, that must not be released yet.
What about this logging module listed on the WSGI wiki?</p>
<pre class="literal-block">
$ pip install wsgilog
Downloading/unpacking wsgilog...
ImportError: No module named ez_setup
</pre>
<p>Wow, it does not even install.
Well, what about Werkzeug?</p>
<p>Armin Ronacher's <a class="reference external" href="http://werkzeug.pocoo.org/">Werkzeug</a>
is renowned for its WSGI debugging middleware,
and it did actually install.
But when wrapped around my application,
it simply displayed a traceback of its <em>own</em> failure
to parse and display the error my application was encountering!</p>
<p>(If you want to know my guess as to the problem:
it appears that some of my Python code
is Unicode rather than plain ASCII.
To display it,
Werkzeug encodes it as UTF-8, prepends a BOM marker,
and passes it to the Standard Library's <cite>compiler.parse()</cite> function&nbsp;—
which then promptly explodes
because in Python&nbsp;2.7 the AST represents a BOM using a new node type,
304, which other Standard Library code is not yet prepared to accept.
I have
<a class="reference external" href="https://github.com/mitsuhiko/werkzeug/issues/51">opened an issue</a>
to see whether Armin thinks my guess makes sense
before I try reporting it in the Python bug tracker.)</p>
<p>And so I wound up using <a class="reference external" href="http://pythonpaste.org/">Python Paste</a>
which installs and works quite cleanly,
and which let me add both basic logging
and error catching using just a few lines of code:</p>


<div class="pygments_murphy"><pre><span class="c"># Transform bare `app` into one that logs and 500s on exceptions</span>

<span class="kn">from</span> <span class="nn">paste.exceptions.errormiddleware</span> <span class="kn">import</span> <span class="n">ErrorMiddleware</span>
<span class="kn">from</span> <span class="nn">paste.translogger</span> <span class="kn">import</span> <span class="n">TransLogger</span>

<span class="n">app</span> <span class="o">=</span> <span class="n">ErrorMiddleware</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="n">debug_flag</span><span class="p">)</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">TransLogger</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">setup_console_handler</span><span class="o">=</span><span class="n">debug_flag</span><span class="p">)</span>

<span class="c"># Now we proceed as before to build our CherryPy application.</span>

<span class="n">cherrypy</span><span class="o">.</span><span class="n">tree</span><span class="o">.</span><span class="n">graft</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="s">&#39;/api&#39;</span><span class="p">)</span>
<span class="o">...</span>
</pre></div>



<p>So far, so good.</p>
</div>
<div class="section" id="the-rock-and-the-hard-place">
<h2>The rock and the hard place</h2>
<p>The Paste error handler let me diagnose and repair
my WSGI application in development mode.
When I started to switch things back over to production,
however, I received a surprise:
exceptions were always printed to <tt class="docutils literal">sys.stderr</tt>
even if I turned on every single option I could find,
in both CherryPy and Paste, for logging to actual files.</p>
<p>What was going on?</p>
<p>It turns out that I had run into a pair of hard-coded assumptions
that could not be solved by mere configuration.</p>
<p>In Ian Bicking's Paste project,
the traceback is directed to the <tt class="docutils literal">wsgi.error</tt> file
provided in the WSGI environment:</p>


<div class="pygments_murphy"><pre><span class="c"># from paste/exceptions/errormiddleware.py</span>

<span class="k">class</span> <span class="nc">ErrorMiddleware</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
    <span class="o">...</span>
    <span class="k">def</span> <span class="nf">exception_handler</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_info</span><span class="p">,</span> <span class="n">environ</span><span class="p">):</span>
        <span class="o">...</span>
        <span class="k">return</span> <span class="n">handle_exception</span><span class="p">(</span>
            <span class="n">exc_info</span><span class="p">,</span> <span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.errors&#39;</span><span class="p">],</span>
            <span class="o">...</span><span class="p">)</span>
</pre></div>



<p>The logic within <tt class="docutils literal">handle_exception()</tt> unfortunately insists
on sending at least a little text
to the stream provided as its second argument,
even if you have turned on some of its other kinds of logging
(like sending an email or writing to a log).</p>
<p>And the identity of that <tt class="docutils literal">wsgi.errors</tt> stream —
one of the few “live” objects inside of the WSGI environment,
whose dictionary values are mostly immutable objects like strings —
is hard-coded by Robert Brewer
inside of the module that invokes WSGI applications:</p>


<div class="pygments_murphy"><pre><span class="c"># from cherrypy/wsgiserver/__init__.py</span>

<span class="k">class</span> <span class="nc">WSGIGateway_10</span><span class="p">(</span><span class="n">WSGIGateway</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">get_environ</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Return a new environ dict targeting the given wsgi.version&quot;&quot;&quot;</span>
        <span class="o">...</span>
        <span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
            <span class="o">...</span>
            <span class="s">&#39;wsgi.errors&#39;</span><span class="p">:</span> <span class="n">sys</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span>
            <span class="o">...</span>
            <span class="p">}</span>
         <span class="o">...</span>
         <span class="k">return</span> <span class="n">env</span>
</pre></div>



<p>His definition of WSGI 1.0, then, sets <tt class="docutils literal">wsgi.errors</tt>
without (so far as I can see) any hope of amendment or recourse.
Thus the rock and the hard place:
Robert insisted that the default stream be <tt class="docutils literal">stderr</tt>,
and Ian's logging module insisted that something be written there.</p>
</div>
<div class="section" id="cutting-the-gordian-knot">
<h2>Cutting the Gordian knot</h2>
<p>One of the great satisfactions of Python,
in the last analysis,
is that when you find yourself trapped in a situation like this
there are generally several ways to escape
and get back to more productive tasks,
like writing code of your own.</p>
<ul class="simple">
<li>An ugly possibility, always available as a last resort:
I could simply monkey-patch,
replacing one of the offending routines in Paste or CherryPy
with a slightly different version of my own.</li>
<li>I could update <tt class="docutils literal">cherrypy.wsgiserver.wsgi_gateways</tt>,
a global dictionary mapping versions of the WSGI protocol
to classes that implement them,
so it offers my own subclass of <tt class="docutils literal">WSGIGateway_10</tt> instead.</li>
<li>I could globally replace <tt class="docutils literal">sys.stderr</tt> when running as a daemon
so that errant error messages get written to a file,
and let Paste and CherryPy run without modification.</li>
</ul>
<p>But each of the above ideas
has the disadvantage of making me adjust something big and global
to fix a problem which, in my program, is small and specific.</p>
<p>At the moment, therefore, I have
added my own tiny piece of WSGI middleware
between Robert's class and Ian's code
which overwrites <tt class="docutils literal">wsgi.errors</tt> with something more appropriate:</p>


<div class="pygments_murphy"><pre><span class="c"># Adding three middlewares: error, logging, and my own</span>

<span class="n">app</span> <span class="o">=</span> <span class="n">ErrorMiddleware</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">debug</span><span class="o">=</span><span class="n">debug_flag</span><span class="p">)</span>
<span class="n">app</span> <span class="o">=</span> <span class="n">TransLogger</span><span class="p">(</span><span class="n">app</span><span class="p">,</span> <span class="n">setup_console_handler</span><span class="o">=</span><span class="n">debug_flag</span><span class="p">)</span>

<span class="n">errlog</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;http-tracebacks.log&#39;</span><span class="p">,</span> <span class="s">&#39;a&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">app2</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
    <span class="n">environ</span><span class="p">[</span><span class="s">&#39;wsgi.errors&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">errlog</span>
    <span class="k">return</span> <span class="n">app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">)</span>

<span class="n">cherrypy</span><span class="o">.</span><span class="n">tree</span><span class="o">.</span><span class="n">graft</span><span class="p">(</span><span class="n">app2</span><span class="p">,</span> <span class="s">&#39;/api&#39;</span><span class="p">)</span>
</pre></div>



<p>And my daemonized application is finally humming along
without the least desire to write to standard error!
To me, this is a great little example
of why a pluggable architecture like WSGI is so powerful
in a language like Python that makes it easy
to create and manipulate functions as first-class objects.</p>
<p>All of which leaves me with three thoughts.</p>
<p>First — looking at the install errors,
and how my attempt to use Werkzeug apparently revealed a bug
in Python's Standard Library itself —
I was painfully reminded of what a mess the Python ecosystem
must look like to those not familiar with its landscape.
If only we could communicate how rare experiences like this are,
once you develop a solid personal tool set
and learn your way around what works and what doesn't!</p>
<p>Second, I wish that CherryPy were willing to do logging
and exception handling for mounted WSGI applications.
I will have to ask Robert whether my approach here is even correct,
or whether there is some other way to call my own applications
without turning off so many features.</p>
<p>Finally, it occurs to me that instead of choosing Paste
and then spending far too long to make it work,
I should have tried out the competing middleware components
that Chris McDonough has produced as part of his
<a class="reference external" href="http://repoze.org/repoze_components.html">Repoze project</a>.
I&nbsp;had not even thought of Repoze until writing this blog entry,
probably because of an unconscious assumption
that installing anything from the Zope world
would probably install a half-dozen dependencies.
But I just tried installing <tt class="docutils literal">repoze.errorlog</tt>
and it only requires a small package called <tt class="docutils literal">meld3</tt>
and, oddly enough, its competitor <tt class="docutils literal">paste</tt> itself!
I&nbsp;should try it out before closing this issue.</p>
<p>Anyway, I hope this write-up helps someone else
who needs to use WSGI middleware
to backfill the features that are normally provided
as part of a large Python web framework.
And, of course, I look forward to comments from the community
about how my approach here could have been more elegant!</p>
</div>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Visible Indentation in Python Publishing</title>
      <link>http://rhodesmill.org/brandon/2011/visible-indentation/</link>
      <pubDate>Sun, 20 Feb 2011 23:00:28 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[document processing]]></category>
      <category><![CDATA[books]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2011/visible-indentation/</guid>
      <description>Visible Indentation in Python Publishing</description>

      <content:encoded><![CDATA[
<p>It suddenly occurred to me that I managed to write <a href="http://rhodesmill.org/brandon/2011/foundations-of-python-network-programming/">an entire blog post about my new book last month</a> without so much as mentioning that it represents a landmark, so far as I know, in Python publishing.</p>
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/2011/chevron-sample.png"
       alt="Sample Python code with indentation marked"
       width="320" height="296" />
</a>
<p>What was my big idea? That in printed Python code, indentation should be visible.</p>
<p>Any of you who have had to read many Python listings printed in books will immediately recognize the problem that I wanted solved. When a listing is long enough to run on to a second page, it is often less than clear whether the code there is continuing at the same level of indentation, or whether the page break has just happened to correspond to a point in the code where it dedented out to the previous level. Languages with braces or explicit “end” statements to close blocks never have to worry about this. But in Python — especially where a script or code snippet ends without ever returning to the outermost level of indentation — the last few lines of the script feel as though they are left hanging if they stand alone at the top of a new page of text.</p>
<p>Of course, there were several practical considerations that had to be settled. A symbol for indentation had to be chosen, for example. I selected the Unicode double-chevron because it is a character that is never valid in actual Python code. Then the publisher had to be convinced to try the experiment; it helped that I had the full support of my editor, <a href="http://www.liveandletwrite.com/">Laurin Becker</a>, who also prepared the layout people for the fact that these chevrons were <i>not</i> part of the code and would need to remain visually distinct from it. Finally — because I had no desire to insert and color each chevron by hand — I had to write an <a href="http://lxml.de/">lxml</a> script to insert the chevrons into my OpenOffice documents, then go back and ruefully remove by hand the chevrons that got nonsensically inserted into snippets of other languages like HTML.</p>
<p>But now I want to hear what readers think! I have not yet seen a review that mentions whether the visible indentation helps, hurts, or is simply irrelevant to the Python listings. If you happen to have seen the new edition of <a href="http://www.amazon.com/gp/product/1430230037?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1430230037">Foundations of Python Network Programming</a><img src="http://www.assoc-amazon.com/e/ir?t=letsdisthemat-20&l=as2&o=1&a=1430230037" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />, let me know what you think. While creating the effect cost some time and effort, I will happily do it again in my next book if turns out to have actually helped readers scan the program listings.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Grin and search it</title>
      <link>http://rhodesmill.org/brandon/2011/grin-and-search-it/</link>
      <pubDate>Wed, 26 Jan 2011 23:15:42 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2011/grin-and-search-it/</guid>
      <description>Grin and search it</description>

      <content:encoded><![CDATA[
<p>
I want to admit how much I am enjoying the
<a href="http://pypi.python.org/pypi/grin">grin search tool</a>
that lets you use Python regular expressions
in recursive searches across your filesystem,
automatically ignoring directories like <tt>.hg</tt>
and files with extensions like <tt>.pyc</tt> and <tt>.jpg</tt>.
</p>
<p>
Over the years I had already built a stable full
of shell functions for doing <i>grep(1)</i> and <i>find(1)</i>
in various combinations,
and my functions even defaulted to using <i>pcregrep(1)</i> when available
because Perl-style REs (which have nearly the same format used by Python)
seem to require so many fewer backslashes for common cases.
It hardly seemed worth the effort to move to another tool —
and the <i>grin</i> output format seemed glarish and offensive at first glance,
not at all like the austere output of traditional <i>grep</i>:
</p>
<pre>
$ pip install grin
$ cd Python-3.2b2
$ grin autoGIL
<span style="color: #080">./Doc/whatsnew/2.6.rst:</span>
 3167 :   :mod:`<span style="color: #990">autoGIL</span>`,
<span style="color: #080">./Misc/HISTORY:</span>
 5577 : - There's a new module called "<span style="color: #990">autoGIL</span>", which
</pre>
<p>
But I forced myself to try using it again a few weeks later,
and when actually doing real work I could not help but notice
that the results were far easier for my eyes to scan
than <i>grep</i> output.
This is an important point: so often, the issue of whether
something <i>looks</i> like it will be easy to read is a quite different matter
than whether it is actually difficult to read
the moment you stop looking <i>at</i> it
and start trying to look <i>through</i> it
to see your data!
Now I can clearly see where the output from one file ends
and the next begins — which traditionally is quite difficult
if you are looking through a series of files with very similar names.
Long file paths no longer push matching lines to the right,
splitting them across the right edge
of my standard 80-column terminal window.
In fact, one of my first objections to its layout
had been the line consumed by each stand-alone file name;
but in practice, I found, far more lines are gained
because of the matches that are not split across the right edge.
</p>
<p>
You can run <i>grin</i> against individual files or directories
by naming them on the command line;
adjust the set of files to which it pays attention;
and even revert its output to a traditional <tt>file:line</tt> format
if you want to pass the output to another program.
You can, in other words, ask it to behave more like traditional <i>grep</i>.
But its default behavior, I gradually realized
after running it several hundred times, is by far the most common
way that I had been using <i>grep</i> anyway —
to search the source files beneath my working directory for a pattern.
</p>
<p>
The author, Robert Kern, has answered emails promptly
and was happy to accept a few patches.
I now have a shell script that I run whenever I set up a new Unix account
that builds a virtual environment,
includes its <tt>bin</tt> directory in my <tt>PATH</tt>,
and installs <i>grin</i> as one of the most important
Python tools that I need always at my fingertips.
Try it out!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Foundations of Python Network Programming: A Last Hurrah For Python 2</title>
      <link>http://rhodesmill.org/brandon/2011/foundations-of-python-network-programming/</link>
      <pubDate>Mon, 24 Jan 2011 15:03:19 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[books]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2011/foundations-of-python-network-programming/</guid>
      <description>Foundations of Python Network Programming: A Last Hurrah For Python 2</description>

      <content:encoded><![CDATA[
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/static/2011/fopnp-cover280.jpg"
       alt="Book cover of Foundations of Python Network Programming"
       width="280" height="346" />
</a>
<p>
My long labor is at last at an end: Apress has
<a href="http://www.amazon.com/gp/product/1430230037?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1430230037">published my rewrite</a><img src="http://www.assoc-amazon.com/e/ir?t=letsdisthemat-20&l=as2&o=1&a=1430230037" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
of John Goerzen's
<i>Foundations of Python Network Programming</i> (2004)
and I have released the example programs
as both Python 2 and Python 3 code in
<a href="https://bitbucket.org/brandon/foundations-of-python-network-programming/">a Bitbucket repository</a>
and also as a zipfile on the Apress web site.
I can finally return to more casual writing —
this is my first blog post in many months! —
and can be more active in Python projects again.
</p>
<p>
I was amazed, as I studied the book's popular
<a href="http://www.amazon.com/gp/product/1590593715?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1590593715">first edition</a><img src="http://www.assoc-amazon.com/e/ir?t=letsdisthemat-20&l=as2&o=1&a=1590593715" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />,
at how far Python has come since 2004.
None of the modern Python web frameworks existed;
the book offered one chapter on CGI programming,
another on <a href="http://www.modpython.org/">mod_python</a>,
and never even mentioned Zope.
Python 2.3 was the most recent version of Python.
The book could cite FTP as one of the
“most widely used protocols on the Internet.”
Parsing HTML involved stepping through the markup with
<a href="http://docs.python.org/library/htmlparser.html">HTMLParser</a>
and the recommended approach to processing XML was the awkward
<a href="http://docs.python.org/library/xml.dom.html">xml.dom</a>.
JSON was not yet popular enough to even warrant mention.
The author recommended the dependable
<a href="http://docs.python.org/library/syslog.html">syslog</a> 
module over the newfangled
<a href="http://docs.python.org/library/logging.html">logging</a>
package in the Standard Library,
and remote administration tools like
<a href="http://www.lag.net/paramiko/">paramiko</a>
and <a href="http://docs.fabfile.org/0.9.3/">fabric</a>
either did not exist or were not yet on the radar.
</p>
<p>
Looking back, it appears that 2005 —
the year following the first edition's publication —
was a turning point for Python web technology in particular.
<a href="http://www.cherrypy.org/">CherryPy</a> saw
its first release in late 2004,
and over the next year we were introduced to
<a href="http://www.djangoproject.com/">Django</a>,
<a href="http://pylonshq.com/">Pylons</a>,
and <a href="http://turbogears.org/">Turbogears</a>,
all on the heels of the Ruby on Rails “framework” phenomenon.
And both of the web scraping technologies
covered in my new edition of the book,
<a href="http://www.crummy.com/software/BeautifulSoup/">BeautifulSoup</a>
and
<a href="http://codespeak.net/lxml/">lxml</a>,
also came out in 2005.
In the face of all these changes, the web chapters
received a full rewrite based on the latest technology.
</p>
<p>
I also rewrote the introductory chapters
so that UDP and TCP each get their own chapter,
focused on the protocol itself,
instead of leaving the information about each protocol split
between a client socket chapter and a server socket chapter.
I have replaced the separate chapters on forking, threading,
and event-driven servers with a single chapter
that takes an example network server,
rewrites that same server six different ways —
including Twisted and a raw polling event loop —
and then uses <a href="http://funkload.nuxeo.org/">funkload</a>
to study the resulting performance.
And even though an editor objected
that it lacked unity,
I insisted that a chapter be dedicated to
<a href="http://memcached.org/">memcached</a>,
message queues, and map-reduce,
since they are so important to scaling modern Internet services.
</p>
<p>
Apress had already slated the project for Python 2
based on the advice of a well-known Python programmer,
and I heartily supported his recommendation.
His wisdom is bourne out by the result:
as you can see from
<a href="https://bitbucket.org/brandon/foundations-of-python-network-programming/src"
   >the <tt>README.txt</tt> that I included with the source code bundle</a>,
fully one-quarter (22/86) of the programs
will simply not run today under Python 3 because of missing dependencies.
I see this new <i>Foundations of Python Network Programming</i>
as the perfect companion for Python 2.7 —
which was released as I was writing —
since the book will bring you up to date
with the final features of the Python 2 series
and the third party libraries that support it.
</p>
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/static/2011/apress-type-size.png"
       alt="Type size comparison"
       width="280" height="283" />
</a>
<p>
I enjoyed working with the Apress team;
<a href="http://www.liveandletwrite.com/">Laurin Becker</a> is a great
managing editor who was always on my side,
and <a href="http://www.michaelbernstein.com/">Michael Bernstein</a> as technical editor gave great feedback which made this an even better book.
There were only two annoyances that I encountered with the book's release.
First, as the accompanying image illustrates,
Apress used a much more compact layout than in the first edition.
This not only makes the book appear much shorter than its predecessor,
but also makes it (to my eyes) visually crowded and more tiring to read.
Second, Apress was not prompt about changing the project title
after their decision to target Python 2,
with the result that Amazon had “Python 3” in the title
all the way through the book's release in late December —
resulting in 1-star reviews for the first few weeks!
</p>
<p>
I will, by the way, soon be blogging
about my experience rewriting the book's
example code to work under Python 3.
This should help two groups of people:
anyone porting a Python 2 network application to Python 3
will probably run into the same issues I did;
and people who are already experimenting with Python 3
will want to know how to apply the book's techniques
to the newer version of the language.
</p>
<p>
Feel free to submit questions about the book
or its example programs to the
<a href="https://bitbucket.org/brandon/foundations-of-python-network-programming"
   >Bitbucket source code repository</a>
where the code is stored.
The revision took far more effort than I had expected,
but I am very happy to have found a format
into which I could distill so much of my own —
and the Python community's —
network programming experience,
so that it will help programmers for years to come.
Enjoy!</p>
]]></content:encoded>
    </item>
    <item>
      <title>CherryPy and running out of file descriptors during development</title>
      <link>http://rhodesmill.org/brandon/2010/cherrypy-and-running-out-of-file-descriptors-during-development/</link>
      <pubDate>Tue, 19 Oct 2010 22:45:44 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/cherrypy-and-running-out-of-file-descriptors-during-development/</guid>
      <description>CherryPy and running out of file descriptors during development</description>

      <content:encoded><![CDATA[
<p>
Well, that was interesting! A fellow developer complained that, following my recent introduction of <a href="http://www.zeromq.org/">ØMQ</a> into our project, he could only go through a few cycles of editing the source code, saving his changes, and watching <a href="http://www.cherrypy.org/">CherryPy</a> automatically restart before it would fail with:
</p>
<pre>
IOError: [Errno 24] Too many open files
</pre>
<p>
An <tt>lsof</tt> against the process confirmed that more files were open after every restart. My guess was that leftover references were keeping a few Python file objects alive from one CherryPy reload to the next, and I remembered having once used a neat utility for exploring the object heap. After some investigation I re-discovered that it was <a href="http://guppy-pe.sourceforge.net/">Heapy</a>. So I added a <tt>pdb</tt> breakpoint, did some investigating, and was puzzled to find that after each restart only four Python file objects existed — one for each log file in our application.
</p>
<p>
(I also tried using <a href="http://mg.pov.lt/objgraph/">objgraph</a>, which is far easier to use than Heapy, but it could not tell that there were file objects in memory at all.  I have no idea why.)
</p>
<p>
Well, this was a puzzle. How could the number of open file descriptors increase without bound when Python was clearly deleting all of the old file objects? The answer, once I finally tried reading the source code to the <tt>Autoreloader</tt> plug-in, was of course very simple: CherryPy performs each restart by doing an <tt>exec()</tt> to completely wipe out the process image and replace it with a new instance of the CherryPy application. Which is certainly a very thorough approach! Except for one thing: file descriptors in Unix are set, by default, to survive an <tt>exec()</tt> call, but the new instance of Python that spins up inside of the process does not know that they are there, so they never get closed. It appeared that suddenly calling ØMQ out of existence with an <tt>exec()</tt> also left a few sockets lying around.
</p>
<p>
Several possible solutions came to mind. What if a more thorough effort was made to delete all Python objects before running the <tt>exec()</tt> call? That sounded daunting, though — it might take a lot of effort to march through all of the application object trees closing everything down. I could have focused my efforts just on finding the file objects, but that approach felt fragile; what would happen the next time one of our developers wrote a new module that opened a log file?
</p>
<p>
Monkey patching the <tt>open()</tt> built-in to create files with their close-on-exec flag already set is, of course, too terrible a solution even to contemplate.
</p>
<p>
In the end, the simplest solution seemed to be the creation of a little CherryPy plug-in that, as the very last shutdown action, would loop over all existing file descriptors and set their close-on-exec flag. Here is the plug-in, in case the pattern helps anyone else:
</p>


<div class="pygments_murphy"><pre><span class="sd">&quot;&quot;&quot;Make sure file descriptors close when CherryPy exec&#39;s.&quot;&quot;&quot;</span>

<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">cherrypy.process.plugins</span> <span class="kn">import</span> <span class="n">SimplePlugin</span>

<span class="k">class</span> <span class="nc">CloexecPlugin</span><span class="p">(</span><span class="n">SimplePlugin</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">stop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">sys</span><span class="p">,</span> <span class="s">&#39;getwindowsversion&#39;</span><span class="p">):</span>
            <span class="k">return</span>
        <span class="kn">import</span> <span class="nn">fcntl</span>  <span class="c"># not available under Windows</span>
        <span class="nb">max</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">sysconf</span><span class="p">(</span><span class="s">&#39;SC_OPEN_MAX&#39;</span><span class="p">)</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">os</span><span class="p">,</span> <span class="s">&#39;sysconf&#39;</span><span class="p">)</span> <span class="k">else</span> <span class="mi">1024</span>
        <span class="k">for</span> <span class="n">fd</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="nb">max</span><span class="p">):</span>  <span class="c"># skip stdin/out/err</span>
            <span class="k">try</span><span class="p">:</span>
                <span class="n">flags</span> <span class="o">=</span> <span class="n">fcntl</span><span class="o">.</span><span class="n">fcntl</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">fcntl</span><span class="o">.</span><span class="n">F_GETFD</span><span class="p">)</span>
            <span class="k">except</span> <span class="ne">IOError</span><span class="p">:</span>
                <span class="k">continue</span>
            <span class="n">fcntl</span><span class="o">.</span><span class="n">fcntl</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">fcntl</span><span class="o">.</span><span class="n">F_SETFD</span><span class="p">,</span> <span class="n">flags</span> <span class="o">|</span> <span class="n">fcntl</span><span class="o">.</span><span class="n">FD_CLOEXEC</span><span class="p">)</span>

    <span class="n">stop</span><span class="o">.</span><span class="n">priority</span> <span class="o">=</span> <span class="mi">99</span>
</pre></div>



<p>
Of course, I suspect that this problem was happening all along, even before we added extra logging and then integrated ØMQ into our application. But back then, with maybe only one or two stray file descriptors surviving each restart, it would have taken five hundred or a thousand CherryPy restarts for the problem to be noticed — and, apparently, none of us developers ever reached that impressive total. Now we know to be careful!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Changed rules for Picasa tag searches</title>
      <link>http://rhodesmill.org/brandon/2010/picasa-tag-searches/</link>
      <pubDate>Tue, 15 Jun 2010 12:56:09 EDT</pubDate>
      <category><![CDATA[web notes]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/picasa-tag-searches/</guid>
      <description>Changed rules for Picasa tag searches</description>

      <content:encoded><![CDATA[
<p>
  Well, drat.
</p>
<p>
  Several images disappeared from the
  <a href="http://www.ourfreshworld.com/">Our Fresh World</a>
  green-building web site
  because Google changed their Picasa API recently —
  and I must not be subscribed to the proper mailing list or blog
  to have been warned ahead of time.
  Where are incompatible Google API tweaks announced?
</p>
<img src="http://rhodesmill.org/brandon/static/2010/solar-power.jpg"/>
<p>
  The site owner and his photographer use
  <a href="http://picasaweb.google.com/">Picasa web albums</a>
  to upload, edit, and maintain their image collection.
  They simply give special tags to their favorite photos,
  and my application code then knows
  that it is supposed to display those photos on the web site.
  I almost used <a href="http://flickr.com/">Flickr</a>
  for this application,
  both because I am an avid Flickr user myself
  and because I consider its web interface more usable.
  But, perhaps predictably, Picasa had the much stronger search API —
  whereas you can either ask Flickr for the photos in a particular set,
  <i>or</i> ask for all of someone's photos that share a particular tag,
  Picasa lets you can combine the two queries
  and ask for only the photos that are in a particular set
  <i>and</i> that also share a specific tag.
  And since search is what attaches pictures to this web site,
  Picasa was my choice.
</p>
<p>
  All was going well,
  with each page getting populated by searches like:
</p>
<pre>
http://picasaweb.google.com/data/feed/api/user/<i>name</i><br/>?kind=photo&tag=solar-power
</pre>
<p>
  Then I received an email from the site owner,
  complaining that many of the photographs had disappeared!
  After seeing some complaints in the Picasa forums
  about recent versions of the user interface
  treating certain “special characters” in tags as spaces instead,
  I suddenly wondered whether the hyphen in several of our tags
  (like the “solar-power” tag in the URL above)
  was the cause of our trouble.
  I adjusted my code so that this search became:
</p>
<pre>
http://picasaweb.google.com/…?kind=photo&tag=solar+power
</pre>
<p>
  And, voilà, the images returned and were again visible!
  Does anyone know what forum or blog I should have been following
  to be informed of this critical change by Google?
  It is dismaying to have a site break in front of a customer
  when the very reason that I chose a Google product
  was because of their powerful API for integrating my application.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Grok has book. Book good!</title>
      <link>http://rhodesmill.org/brandon/2010/grok-has-book-book-good/</link>
      <pubDate>Thu, 10 Jun 2010 22:32:52 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[books]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/grok-has-book-book-good/</guid>
      <description>Grok has book. Book good!</description>

      <content:encoded><![CDATA[
<p>
  I little suspected the great chasm that lies
  between the simple act of agreeing to review a book,
  and the actual exercise of sitting down later to write the review.
  It feels quite pleasant, really,
  to jot off a positive reply to the publisher's polite question.
  One feels magnanimous for agreeing to help advance our civilization
  by reviewing a book about Python,
  and for helping out the publisher in what,
  after all, are such hard economic times.
  It is fun when the free copy arrives,
  crisp and smartly bound.
</p>
<p>
  But then, eventually, one has to write the actual review.
</p>
<a class="image-reference" href="http://www.amazon.com/gp/product/1847197485?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1847197485"><img border="0" src="http://rhodesmill.org/brandon/static/2010/grok-book.jpg"></a><img src="http://www.assoc-amazon.com/e/ir?t=letsdisthemat-20&l=as2&o=1&a=1847197485" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
<p>
  And so,
  a full four months after that friendly email from Packt Publishing,
  it is time that I sit down
  and put together some thoughts
  about Carlos de la Guardia's first book,
  <a href="http://www.amazon.com/gp/product/1847197485?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=1847197485"
     >Grok 1.0 Web Development</a>.
  Carlos is a long-time veteran of the Zope and Plone communities,
  and <a href="http://grok.zope.org/">Grok</a>,
  of course,
  is the web framework
  that places a simple and agile convention-driven engine
  atop the otherwise notoriously XML-ridden Zope application framework.
  Grok is an important project,
  because it packages the technology of Python's oldest
  and most experienced community of web developers
  in a way that makes it easy to extend and use.
</p>
<p><a href="http://rhodesmill.org/brandon/2010/grok-has-book-book-good/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Mounting Windows shares in Linux userspace</title>
      <link>http://rhodesmill.org/brandon/2010/mounting-windows-shares-in-linux-userspace/</link>
      <pubDate>Wed, 09 Jun 2010 17:33:30 EDT</pubDate>
      <category><![CDATA[emacs]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/mounting-windows-shares-in-linux-userspace/</guid>
      <description>Mounting Windows shares in Linux userspace</description>

      <content:encoded><![CDATA[
<p>
  A current project has forced me into the clunky world of Windows,
  to verify that a Python program compiles and runs there
  just like it runs under Linux.
  Instead of trying to port my entire development environment to Windows —
  which includes two decades of customizations
  and a small empire of tools like
  <a href="http://www.gnu.org/software/emacs/"
     >Emacs</a>,
  <a href="http://pypi.python.org/pypi/pyflakes"
     >pyflakes</a>, and
  <a href="http://rope.sourceforge.net/"
     >Rope</a> —
  I want to simply mount my Windows home directory under Linux
  so that I can run my normal editor and version control tools
  in a more familiar environment.
</p>
<p>
  I have worked out an elegant solution
  by combining <i>two</i> of the powerful user-space filesystems
  available through the <a href="http://fuse.sourceforge.net/">FUSE</a>
  mechanism in the Linux kernel.
  Let me take you through the story of how I put them together!
</p>
<p><a href="http://rhodesmill.org/brandon/2010/mounting-windows-shares-in-linux-userspace/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Python multiprocessing is different under Linux and Windows</title>
      <link>http://rhodesmill.org/brandon/2010/python-multiprocessing-linux-windows/</link>
      <pubDate>Fri, 14 May 2010 12:27:05 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/python-multiprocessing-linux-windows/</guid>
      <description>Python multiprocessing is different under Linux and Windows</description>

      <content:encoded><![CDATA[
<p>
One of the great recent advances in the Python Standard Library
is the addition of the
<a href="http://docs.python.org/library/multiprocessing.html"
   >multiprocessing</a> module,
maintained by <a href="http://jessenoller.com/">Jesse Noller</a>
who has also blogged and written
about several other concurrency approaches for Python —
<a href="http://jessenoller.com/2009/01/29/a-gentle-overview-of-kamaelia-or-its-axon-stupid/"
   >Kamaelia</a>,
<a href="http://jessenoller.com/2009/01/31/circuits-event-driven-components/"
   >Circuits</a>,
and
<a href="http://jessenoller.com/2009/02/23/stackless-you-got-your-coroutines-in-my-subroutines/"
   >Stackless</a> Python.
</p>
<p>
I have wanted to try the multiprocessing module out for some time,
and now have a consulting project that will really benefit from multiple processes:
they will let our application run third-party plugins
without having to worry that any bugs or indiscretions which they commit
might damage or hang our main server,
which can remain safe in another process.
</p>
<p>
First, one can only stand in awe at the achievement —
and the amount of work —
that the multiprocessing module represents.
I cannot imagine the time that it would have taken our team
to figure out all of the differences between Linux and Windows
when it comes to processes, shared memory, and concurrency mechanisms.
In fact, the approach we are taking might not even have been feasible
under those circumstances.
By figuring out how to get locks, queues, and shared data structures
all working cleanly on such different architectures,
the multiprocessing authors
save Python programmers out on the street like me
from reinventing a dozen wheels
when we need to support multi-platform concurrency.
</p>
<p>
Well, <i>almost.</i>
</p>
<p>
There is one rather startling difference
which the multiprocessing module does <i>not</i> hide:
the fact that while every Windows process must spin up
independently of the parent process that created it,
Linux supports the <i>fork(2)</i> system call
that creates a child processes already in possession
of exactly the same resources as its parent:
every data structure, open file, and database connection
that existed in the parent process
is still sitting there, open and ready to use, in the child.
Consider this small program:
</p>


<div class="pygments_murphy"><pre><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Process</span>
<span class="n">f</span> <span class="o">=</span> <span class="bp">None</span>

<span class="k">def</span> <span class="nf">child</span><span class="p">():</span>
    <span class="k">print</span> <span class="n">f</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;mp.py&#39;</span><span class="p">,</span> <span class="s">&#39;r&#39;</span><span class="p">)</span>                                                      
    <span class="n">p</span> <span class="o">=</span> <span class="n">Process</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">child</span><span class="p">)</span>
    <span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
    <span class="n">p</span><span class="o">.</span><span class="n">join</span><span class="p">()</span>
</pre></div>



<p>
On Linux, the open file <tt>f</tt> keeps its value in the child process;
the child has inherited an open connection from its parent:
</p>
<pre>
$ python mp.py
&lt;open file 'mp.py', mode 'r' at 0xb7734ac8&gt;
</pre>
<p>
Under Windows, however, where the multiprocessing module
has to spawn a fresh copy of the Python interpreter
to which it gives special instructions
to just run the function <tt>f()</tt>,
the module is a clean slate without an open file inside:
</p>
<pre>
C:\Users\brandon\dev>python mp.py
None
</pre>
<p>
Now, my complaint is not exactly
that the multiprocessing documentation is misleading on this point;
under its section on
<a href="http://docs.python.org/library/multiprocessing.html#programming-guidelines"
   >Programming guidelines</a>,
it makes it quite clear that:
</p>
<blockquote>
On Unix a child process can make use of a shared resource created in a
parent process using a global resource. However, it is better to pass
the object as an argument to the constructor for the child process.
</blockquote>
<p>
I have no quarrel with this advice;
if I am careful to pass everything the child needs
in its list of arguments,
then I can be sure that my code will work under both Linux and Windows.
</p>
<p>
But I do wish that the multiprocessing module
provided more support for testing this condition
more rigorously under Linux.
In particular, I wish that there were some way of turning
the simple forking logic <i>off</i> —
of saying, “Yes, I know that Linux will let you create a child process
very simply using <i>fork(2)</i>, but for my sanity would you please
create the child process from scratch like you do under Windows so
that I can test whether my code accidentally depends on residual
state from the parent process that I did not see that I was using?”
I looked at the multiprocessing "forking.py" module
to see whether I could turn on the Windows-style process spawning
even from inside of Linux,
but the mechanism is chosen
by a bare module-level check of "sys.platform"
and if I overwrite that variable with 'win32'
the code then dies when it tries to import "msvcrt"
which is available only under Windows.
</p>
<p>
There is, thus, even in principle, no way
that I can test my multiprocessing application under Linux
which will give me any assurance that my child processes
are not accidentally taking advantage of data structures
and open connections left lying around by the parent process;
only by actually moving over to Windows itself
can I see how my child code really behaves on its own.
I have <a href="http://bugs.python.org/issue8713">created a feature request</a>
in the Python bug tracker to see whether this situation can be improved.
</p>
<p>
But even with this one inconvenience —
which is troubling me much less, now that I at least understand
why my application was behaving so differently under Windows —
the multiprocessing module is still a huge leap forwards
for Python programmers who need to run code
in heavyweight processes with all of the isolation and safety
that they provide.
Thanks again to Jesse and the multiprocessing team!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Sphinx + Mercurial = My favorite CMS</title>
      <link>http://rhodesmill.org/brandon/2010/sphinx-mercurial-cms/</link>
      <pubDate>Sun, 21 Mar 2010 22:58:28 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[document processing]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/sphinx-mercurial-cms/</guid>
      <description>Sphinx + Mercurial = My favorite CMS</description>

      <content:encoded><![CDATA[
<p>
Though I write and maintain some of the content for our <a href="http://pyatl.org/">Python Atlanta web site</a>, updates and additional content often come in from other users. For example, our Plone interest group — headed up by <a href="http://www.ifpeople.net/about/people/cjj">Christopher Johnson</a> — has their <a href="http://pyatl.org/plone">own page on our web site</a>. And the information about our <a href="http://pyatl.org/bookclub">book club</a> is both written and regularly updated by <a href="http://www.doughellmann.com/">Doug Hellmann</a>.
</p>
<a class="image-reference" href="http://pyatl.org/">
  <img src="http://rhodesmill.org/brandon/static/2010/pyatl-thumb.png"
       alt="Python Atlanta web site"
       width="240" height="135" />
</a>
<p>
How can a collaborative site like ours best be edited and updated? Well, I would like to report some modest initial success with an experimental approach: I now maintain the site as a <a href="http://sphinx.pocoo.org/">Sphinx-powered</a> documentation system stored in a <a href="http://bitbucket.org/brandon/pyatl.org/">BitBucket repository</a> into which I pull changes made by my collaborators. The advantages are several.
</p>
<ul>
<li>The change management tools supported by traditional CMS systems, even at their best, seem somehow anemic when compared to the toolkit provided by a good DVCS like <a href="http://mercurial.selenic.com/">Mercurial</a>. Where, for example, does even a capable CMS like Plone provide anything like Mercurial's “backout” or “blame” commands?
</li>
<li>Markup as well-designed as <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> is not only a lot of fun to use, bit it also very cleanly separates content from design. Authors working in plain text tend to produce clean, readable content without the messy markup often associated with visual HTML editors, or, worse yet, the disaster that is Microsoft Word.
</li>
<li>Staging — a feature I find essential, but which seems missing from many default CMS configurations — occurs automatically! Each author can see locally how the site will look with their changes, and after doing a pull I can review the site's appearance on my laptop before finally deploying the new content to the production site.
</li>
</ul>
<p>
To top it all off, authors get to use their own editor-of-choice when making contributions, and we all get extra practice cloning and merging in my favorite DVCS. I am optimistic about this direction, but I will post again if we wind up hitting snags in the future. Finally, of course, feel free to clone our repository if you want to see how Sphinx looks when running a generic web site.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Ubuntu Python: raise an exception, import 190 modules</title>
      <link>http://rhodesmill.org/brandon/2010/ubuntu-exception-190-modules/</link>
      <pubDate>Thu, 25 Feb 2010 23:16:32 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/ubuntu-exception-190-modules/</guid>
      <description>Ubuntu Python: raise an exception, import 190 modules</description>

      <content:encoded><![CDATA[
<p>
Imagine my surprise, while writing my first
<a href="http://www.python.org/dev/peps/pep-0302/">PEP 302</a>
compliant import hook this afternoon,
to carefully watch <tt>sys.modules</tt> for the results of my import
but see it suddenly grow by nearly two hundred modules!
What on earth had I done wrong?
Some quick experiments revealed that my only sin
was having the temerity to raise an exception.
Let's try raising a simple <tt>NameError</tt>:
</p>


<div class="pygments_murphy"><pre><span class="o">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">sys</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">)</span>
<span class="mi">35</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">foo</span>
<span class="o">...</span>
<span class="ne">NameError</span><span class="p">:</span> <span class="n">name</span> <span class="s">&#39;foo&#39;</span> <span class="ow">is</span> <span class="ow">not</span> <span class="n">defined</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">modules</span><span class="p">)</span>
<span class="mi">225</span>
</pre></div>



<p>
That's 190 extra modules —
merely importing them takes around 60 ms on my laptop!
Where are they all coming from?
And how could an exception cause so many imports,
including such illustrious modules as <tt>email</tt>,
<tt>mimetools</tt>, and <tt>xml</tt>?
</p>
<p>
After reading Ubuntu's <tt>sitecustomize.py</tt> file
and all of its consequences, the situation became clear.
Their <a href="https://wiki.ubuntu.com/Apport">apport</a>
crash-reporting subsystem instruments Python
with an exception hook that, when invoked,
discovers that my system says <tt>enabled=0</tt>
in my <tt>/etc/default/apport</tt> file
and so it undertakes no special crash logging.
But, on the way to loading the routine
that performs this simple check,
it performs two quite flagrant and unnecessary imports,
pulling in both <tt>apt</tt>
(that brings with it 83 packages)
and <tt>apport</tt>
(an additional 107 packages).
</p>
<p>
The solution?
I have removed the <tt>python-apport</tt> package,
along with the <tt>ubuntuone-client</tt> suite that depends on it.
After the uninstall, exceptions are — wonderfully enough —
not causing a <i>single</i> import of a new module!
Now, finally, I can continue writing my import hook in peace.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Opening tabs remotely in Google Chrome</title>
      <link>http://rhodesmill.org/brandon/2010/remote-tabs-google-chrome/</link>
      <pubDate>Wed, 24 Feb 2010 23:07:06 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[emacs]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2010/remote-tabs-google-chrome/</guid>
      <description>Opening tabs remotely in Google Chrome</description>

      <content:encoded><![CDATA[
<p>
Now that I use
<a href="http://www.google.com/chrome">Google Chrome</a>
almost exclusively,
I miss the fact
that a running <a href="http://www.firefox.com">Firefox</a> instance
could be controlled from the command line so that Emacs could call for a new tab
when I clicked on a URL.
It would run a command something like this:
</p>
<pre>
firefox -remote 'openURL(http://example.com/, new-tab)'
</pre>
<p>
But after a few months of manually cutting and pasting URLs into Chrome —
which wasn't actually <i>that</i> bad,
since the address bar in Chrome is such a convenient and large target —
I decided that I needed a real solution.
After not finding anything like a <tt>-remote</tt> option,
I discovered that Chrome can at least be run
with a debugging port open:
</p>
<pre>
google-chrome --remote-shell-port=9222
</pre>
<p>
The protocol that Chrome speaks is primitive enough
that it was quick work to implement a small client in Python.
Rather than merely cutting and pasting its code here on my blog,
or even be satisfied with
<a href="http://bitbucket.org/brandon/chrome_remote_shell/"
   >making it available on bitbucket</a>,
I decided to place the code inside of a new Python package
and make it generally available on PyPI as <a href="http://pypi.python.org/pypi/chrome_remote_shell/"
   >chrome_remote_shell</a>.
</p>
<p>
Thanks to this simple package,
a four-line program (not counting the shebang and comment)
is now all that I need to ask Google Chrome to open a new tab:
</p>


<div class="pygments_murphy"><pre><span class="c">#!/usr/bin/env python</span>
<span class="c"># Name this file &quot;google-chrome-open-url&quot;</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">chrome_remote_shell</span>
<span class="n">shell</span> <span class="o">=</span> <span class="n">chrome_remote_shell</span><span class="o">.</span><span class="n">open</span><span class="p">()</span>
<span class="n">shell</span><span class="o">.</span><span class="n">open_url</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</pre></div>



<p>
To teach Emacs to start using Google Chrome when I clicked on a link,
I only needed to supply it with two new settings:
</p>


<div class="pygments_murphy"><pre><span class="p">(</span><span class="nf">setq</span> <span class="nv">browse-url-browser-function</span>
      <span class="ss">&#39;browse-url-generic</span><span class="p">)</span>
<span class="p">(</span><span class="nf">setq</span> <span class="nv">browse-url-generic-program</span>
      <span class="s">&quot;google-chrome-open-url&quot;</span><span class="p">)</span>  
</pre></div>



<p>
And now everything works.
I hope that these notes prove useful to someone else.
Enjoy!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Leaving Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2010/leaving-python-magazine/</link>
      <pubDate>Mon, 01 Feb 2010 23:04:44 EST</pubDate>
      <category><![CDATA[python]]></category>
      <guid>http://rhodesmill.org/brandon/2010/leaving-python-magazine/</guid>
      <description>Leaving Python Magazine</description>

      <content:encoded><![CDATA[
<img src="http://rhodesmill.org/brandon/static/2010/pymag-logo.png"
     alt="Python Magazine logo"
     width="200" height="63" />
<p>
It was with regret that I tendered my resignation yesterday
as the Editor-in-Chief of Python Magazine.
While the publisher will keep producing the magazine
by distributing PDFs on the web site,
the transition to the new format has dragged on long enough —
both for both myself and our customers —
that I have run out of enthusiasm.
My last responsibility
will be to shepherd the February and March issues
through the publishing process
and safely on to the PDF readers of our subscribers.
</p>
<p>
I hope that the authors featured in the October issue will forgive me
for not writing my usual blog post last year touting their achievements;
I had just received the sad news that the publisher
could no longer afford the rising costs
of printing and shipping Python Magazine,
and I did not want to further advertise the magazine
until its fate was certain one way or the other.
</p>
<p>
I have by no means been a perfect editor.
In particular,
the publisher hoped that I would get the magazine —
which was running eight weeks late —
back on schedule.
Instead, my bumbling first month as editor
made the magazine an additional week late,
and by the time I hit my stride in May it was another week behind.
Although the schedule then stabilized at a steady ten weeks late,
I never did manage to start reeling the fish back in.
The only metric, I suppose, which I can really claim to my credit
is that I oversaw a nineteen-fold increase
in the number of em-dashes in the magazine —
247 appeared over the course of 2009,
up from only 13 the year before!
</p>
<p>
I should express thanks to my co-workers:
Arbi, Emanuela, and Cathleen are smart, helpful, and professional,
and were patient with me as I learned the ropes.
Doug Hellmann gave me ample training as he handed over the reins,
and also supported the magazine later as an acquisitions editor.
Several associate editors performed solid reviews of incoming articles.
And, of course, the greatest privilege of being Editor-in-Chief
was to help such a wide array of voices from the Python community
find their way into print —
from Steve Holden,
the illustrious chair of the Python Software Foundation,
to young Meran Cambpell-Hood,
an eleven-year-old from New Zealand
who described using Python for the first time
to process data for her science fair project.
</p>
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/static/2009/pymag-october.jpg"
       alt="Cover of October 2009 Python Magazine"
       width="200" height="260" />
</a>
<p>
Which reminds me:
the authors from the October issue
never got their moment in the spotlight!
The article by <b>Meran Campbell-Hood</b> about her science fair
project was the most fun to edit,
but every single article was interesting and taught me something.
Steve Holden interviewed <b>James Tauber</b>
about the secrets of a successful Python start-up;
<b>Yusdi Santoso</b> finished his two-part series
on the Python program he wrote to produce the PDF
for the beautiful EuroPython brochure last year;
the original editor of Python Magazine, <b>Brian Jones</b>,
returned to talk about why he now tends
to choose Django for web projects rather than PHP;
and <b>Joe Amenta</b> introduced his "3to2" project,
which will help Python programmers
support their old Python 2 users while still moving ahead
with the transition to Python 3.
Finally, <b>Greg Newman</b> explained how to turn Emacs
into a powerful Python IDE,
and <b>Steve Holden</b> and myself
rounded out the issue with our usual editorializing.
</p>
<p>
With many of the rest of you,
I am eager to see the debut of the new
<a href="http://pythonmagazine.com/">Python Magazine web site</a>.
And I look forward to seeing everyone
at PyCon 2010
in less than three weeks!
While I will not have the joy that I did last year
of walking the halls of PyCon as a newly-minted Editor-in-Chief,
able to make dreams come true
and grant the fame and fortune of being a published author,
I will at least enjoy being a developer among developers
in the best programming language community on Earth!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>The September 2009 issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-september/</link>
      <pubDate>Tue, 20 Oct 2009 01:41:07 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[document processing]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pymag-september/</guid>
      <description>The September 2009 issue of Python Magazine</description>

      <content:encoded><![CDATA[
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/static/2009/pymag-september.jpg"
       alt="Cover of September 2009 Python Magazine"
       width="200" height="258" />
</a>
<p>
  The September issue of Python Magazine
  appeared on the web late last week
  and only now, as a new week has started,
  am I finally sitting down to announce it!
  The articles range from technically heavy development topics
  to high-level thoughts about the whole Python community,
  with plenty in between.
</p>
<p>
  I have to say that our prettiest article this month
  is “Using Python to Create Beautiful Documents” by Yusdi Santoso,
  who shares the basic secrets to document generation
  that he learned when building the
  <a href="http://www.europython.eu/">EuroPython 2009</a> brochure
  using a Python program.
  Traditional typesetting and computer typography
  were both interests of mine when I was growing up,
  so it was fun to read Yusdi's introduction to using
  <a href="http://www.reportlab.org/">ReportLab</a>
  to generate PDF documents.
  I look forward to his follow-up article
  that we will soon be publishing,
  on the specific techniques that he used in creating
  the EuroPython booklet.
</p>
<p>
  The other technical articles are an introduction
  to using <a href="http://www.w3.org/TR/soap/">SOAP</a> in Python;
  a guide to displaying objects in a Mac OS X GUI created with PyObjC;
  an article introducing Python's own built-in
  <a href="http://docs.python.org/library/tkinter.html">Tkinter</a>
  GUI toolkit;
  and a small excursion of my own
  that attempts to explain the popular “trick”
  (well, it really confused <i>me</i> the first time I saw it!)
  of defining a decorator using a pair of nested functions.
  I should confess that my own article
  contains what is probably this issue's biggest mistake,
  as pointed out quite promptly by alert reader Emanuel Woiski:
  in the code sample that is its whole crux of my example,
  I somehow managed to omit one of the most crucial lines,
  shown here in bold:
</p>


<div class="pygments_murphy"><pre><span class="k">def</span> <span class="nf">log</span><span class="p">(</span><span class="n">function</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">log_wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
        <span class="k">print</span> <span class="s">&quot;called </span><span class="si">%s%s</span><span class="s">&quot;</span> <span class="o">%</span> <span class="p">(</span>
            <span class="n">function</span><span class="o">.</span><span class="n">__name__</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
            <span class="p">)</span>
        <span class="o">&lt;</span><span class="n">b</span><span class="o">&gt;</span><span class="k">return</span> <span class="n">function</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span><span class="o">&lt;/</span><span class="n">b</span><span class="o">&gt;</span>
    <span class="k">return</span> <span class="n">log_wrapper</span>
</pre></div>



<p>
  I suppose I will now need remedial cut-and-paste training of some sort.
</p>
<p>
  Finally, the issue is rounded out
  by three articles that move back from Python coding
  and step out to wider vantage points.
  Justin Lilly provides an excellent guide
  to customizing your Vim setup
  so that it becomes a powerful Python
  integrated development environment.
  Steve Holden muses about why diveristy is so difficult
  and reveals some of the recent goings-on
  surrounding the diversity statement
  that the Python Software Foundation has been working on.
  And my own editorial seeks to point any Python Magazine readers
  who do not yet have a strong connection with the wider community
  in the direction of greater engagement
  with the world of Python.
</p>
<p>
  All in all, I think the issue
  is a nice mix of fact, experience, and opinion.
  Please consider subscribing if you would like to hear more
  about what people are doing with Python, and how.
  I enjoy reading it; so might you.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Google Earth and Middle-earth</title>
      <link>http://rhodesmill.org/brandon/2009/google-earth-and-middle-earth/</link>
      <pubDate>Wed, 30 Sep 2009 00:11:21 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/google-earth-and-middle-earth/</guid>
      <description>Google Earth and Middle-earth</description>

      <content:encoded><![CDATA[
<div class="caption">
  <img src="http://rhodesmill.org/brandon/static/2009/google-middle-earth-distorted.jpg"
       alt="A Middle Earth overlay, too narrow at the top" />
  Importing a normal, rectangular map of Middle-earth
  as a Google Earth overlay is too narrow toward the north.
</div>
<p>
  I wanted to measure distances in Tolkien's Middle-earth.
  While a flat map distorts such measurements,
  it occured to me that Google Earth can correctly measure
  both lines and paths across the curved surface of the globe.
  I soon found excellent documentation for
  <a href="http://earth.google.com/userguide/v4/ug_imageoverlays.html"
     >using image overlays with Google Earth</a>,
  so I downloaded a map of Middle-earth
  and tried placing it on the globe.
</p>
<p>
  Imagine my disappointment when I saw the result shown in the above image!
  At first I made the mistake
  of not holding down the <tt>Shift</tt> key
  when resizing the image in Google Earth;
  the <tt>Shift</tt> key is absolutely critical
  for the image to maintain its aspect ratio
  as you stretch it to the right dimensions.
  But even after learning this habit,
  it was painfully clear that the Middle-earth map's projection
  was different from that expected by Google Earth:
  the map is far too narrow at the top.
</p>
<p>
  Obviously, it was time to pull out Python,
  my favorite programming language,
  and see whether the
  <a href="http://www.pythonware.com/products/pil/">Python Imaging Library</a>
  could help me make short work
  of converting a map from one projection to another.
</p>
<p><a href="http://rhodesmill.org/brandon/2009/google-earth-and-middle-earth/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Python at the 2009 Atlanta Linux Fest</title>
      <link>http://rhodesmill.org/brandon/2009/python-at-atlanta-linux-fest/</link>
      <pubDate>Mon, 21 Sep 2009 23:17:06 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[plone]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/python-at-atlanta-linux-fest/</guid>
      <description>Python at the 2009 Atlanta Linux Fest</description>

      <content:encoded><![CDATA[
<div class="caption" style="width: 100%;">
  <img src="http://rhodesmill.org/brandon/static/2009/alf2009-python-booth.jpg"
       />
  <p style="padding-left: 3em; padding-right: 3em; text-align: center;">
  My Python table at the Atlanta Linux Fest.
  You can
  <a href="http://rhodesmill.org/brandon/static/2009/alf2009-python-booth.mpg"
     >also watch a short video of me demonstrating a depth-first search</a>
  to some students who dropped by the table.
  (Thanks, Richard Davies, for the video!)
</div>
<p>
  Running the Python table at the
  <a href="http://atlantalinuxfest.org/">Atlanta Linux Fest</a>
  this past weekend was a really incredible experience.
</p>
<p>
  First, there was the great feeling
  that the pillars of the Python community were standing behind me
  as I stepped forward to represent my favorite programming language.
  It was <a href="http://www.amk.ca/">Andrew Kuchling</a>
  who noticed that exhibitor tables at the Fest were free
  for non-profits like the
  <a href="http://www.python.org/psf/">Python Software Foundation</a>,
  and <a href="http://holdenweb.com/">Steve Holden</a>
  who forwarded me a heads-up since I live in Atlanta
  (the Fest had not yet made it on to my radar).
  The inimitable <a href="http://rule6.info/">Aahz</a>
  personally shipped me the promotional kit,
  including a huge “Python” banner and stacks of brochures,
  that he himself had just used
  at <a href="http://en.oreilly.com/oscon2009">OSCON 2009</a>.
  And, completing the loop, it was Andrew who followed up
  to ask if there were any last things that I needed,
  and sent me a pile of over one hundred Python stickers
  that wound up being <i>very</i> popular at the Fest.
  (I returned home with exactly one,
  which is sitting next to me on my desk as I type this!)
</p>
<p>
  Here are some lessons that I learned from the experience:
</p>
<p><a href="http://rhodesmill.org/brandon/2009/python-at-atlanta-linux-fest/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>GetPaid needs customizable forms</title>
      <link>http://rhodesmill.org/brandon/2009/getpaid-needs-customizable-forms/</link>
      <pubDate>Thu, 10 Sep 2009 00:25:46 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[plone]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/getpaid-needs-customizable-forms/</guid>
      <description>GetPaid needs customizable forms</description>

      <content:encoded><![CDATA[
<div class="dropshadow alignright">
  <a href="http://www.plonegetpaid.com/">
    <img src="http://rhodesmill.org/brandon/static/2009/getpaid-logo.png"
         alt="GetPaid for Plone logo"
         width="330" height="83" />
  </a>
</div>
<p>
  I would like some advice from Zope and Plone folks
  about how to create forms
  that are not only easy for other developers to specialize,
  but which allow <i>several</i> specializations to be composed together.
  While I have used <tt>zope.formlib</tt> and <tt>z3c.form</tt> before
  for simple tasks,
  I have not yet been able to tell
  whether they support these more advanced kinds of operations.
</p>
<p>
  Some background:
  I am doing some work
  on <a href="http://www.plonegetpaid.com/">GetPaid for Plone</a>
  with the generous funding of Derek Richardson who,
  if his dreams had not carried him away from grad school
  at the end of the Spring semester,
  would have tackled this same work
  as part of the 2009 Google Summer of Code.
</p>
<p>
  The current mechanisms that GetPaid provides
  for customizing its checkout process are very primitive,
  and my task is to improve them.
  That is why I have been thinking about customizing forms.
</p>
<p><a href="http://rhodesmill.org/brandon/2009/getpaid-needs-customizable-forms/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>The August 2009 issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-august/</link>
      <pubDate>Mon, 07 Sep 2009 22:22:00 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pymag-august/</guid>
      <description>The August 2009 issue of Python Magazine</description>

      <content:encoded><![CDATA[
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/static/2009/pymag-august.jpg"
       alt="Cover of August 2009 Python Magazine"
       width="200" height="258" />
</a>
<p>
  The August issue of Python Magazine is out,
  and the cover issue is one of the most exciting
  that I have had the privilege to publish.
  Following up on his popular talk at PyCon 2009,
  professor of computer science
  <a href="http://www.cse.msu.edu/~punch/">Dr. Bill Punch</a>
  has written an article for us with his colleague
  <a href="http://www.cse.msu.edu/~enbody/">Dr. Richard Enbody</a>
  about replacing C++ with Python
  in Michigan State University's introductory programming class.
</p>
<p>
  The difficulty they faced
  was that the second and subsequent classes
  in Michigan State's curriculum have continued using the C++ language;
  only the initial course could change to Python.
  While non-majors taking the introductory course
  get to learn Python and leave,
  the computer science majors
  have to then start the second course
  without any specific knowledge of C++.
  How much, skeptics wondered, would it hurt the Python students
  to be a full semester behind in their C++ knowledge
  compared to students
  who took the “old” C++ version of the introductory course?
</p>
<p>
  The circumstances at Michigan State wound up being perfect
  for making the change to Python a full-fledged,
  statistically valid experiment
  to determine how much student grades would be hurt
  because of the switch.
  Read the article for the detailed results,
  but I can report — with great satisfaction —
  that the Python students
  proved themselves the equals of their C++ peers,
  and also that <i>very</i> exciting and unexpected results ensued
  among the students whom the study was <i>not</i> looking at:
  the non-majors, for which this was their only programming course,
  and the seasoned grad students,
  who rolled up their sleeves and learned Python
  in order to be able to TA the course.
  Again, see the article for all of the details!
</p>
<p>
  What else do we have this month?
  Articles about how easy concurrency becomes with
  <a href="http://www.stackless.com/">Stackless Python</a>;
  about documenting your software projects
  using the powerful <a href="http://sphinx.pocoo.org/"
                        >Sphinx documentation system</a>;
  about creating simple graphs with the industry-strength
  <a href="http://matplotlib.sourceforge.net/">matplotlib
  plotting library</a>;
  a guide to the details of hashing algorithms,
  and how they relate to the Python dictionary implementation;
  and, finally, the usual thoughts and ponderings
  from both myself and from
  <a href="http://holdenweb.com/"
     >Steve Holden</a> of the
  <a href="http://www.python.org/psf/"
     >Python Software Foundation</a>.
  Come join us!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Start all of your commands with a comma</title>
      <link>http://rhodesmill.org/brandon/2009/commands-with-comma/</link>
      <pubDate>Tue, 18 Aug 2009 01:40:06 EDT</pubDate>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/commands-with-comma/</guid>
      <description>Start all of your commands with a comma</description>

      <content:encoded><![CDATA[
<p>
  Like many Unix users,
  I long ago created a <tt>~/bin/</tt> directory in my home directory
  and added it to my <tt>PATH</tt>
  so that I could supplement
  the wonderfully rich set of basic Unix commands
  with some conveniences and shell scripts of my own devising.
</p>
<p>
  The problem, of course, was the chance of collision.
  Because my shell script names
  tended to be short and pithy collections of lowercase characters,
  just like the default system commands,
  there was no telling when Linux would add a new command
  that would happen to have the same name as one of mine.
  This was actually not very likely on,
  say, a System V Revision 3 workstation in the 1980s,
  but the trouble became quite a bit more acute
  when I moved into the world of Debian.
  Red Hat never really worried me,
  because they packaged (comparatively) so little software.
  But Debian today supports a huge number of commands;
  my modest Ubuntu laptop shows several thousand available:
</p>
<pre>$ apt-file search -x '^/usr/bin/[^/]*$' | wc -l
21733</pre>
<p>
  The solution was obviously to adjust my command names
  in such a way that they were still easy to type,
  but would never be chosen as system command names.
  For me, “easy to type” means not having to use the shift key,
  and very few characters turned out to be available,
  unshifted, on a modern keyboard.
  The lower-case letters
  are the very characters used in system commands;
  brackets, backslashes, the colon, the back-tick, and the single-tick
  all had a special meaning to the shell;
  and the slash and dot characters both mean something special
  in a filename.
  (The slash divides directory names from filenames,
  and thus cannot appear in a filename itself,
  while the dot means “hide this file from normal browsing”
  if it leads the name,
  and separates a file from its extension in many other cases.)
</p>
<p>
  There was but one character left: the simple, modest comma.
</p>
<p>
  A quick experiment revealed in a flash
  that the comma was <i>exactly</i> the character
  that I had been looking for!
  Every tool and shell that lay in arm's reach
  treated the comma as a perfectly normal
  and unobjectionable character in a filename.
  By simply prefixing each of my custom commands
  with a comma,
  they became completely distinct from system commands
  and thus free from any chance of a collision.
</p>
<p>
  And, best of all,
  thanks to the magic of tab-completion,
  it became very easy to browse my entire collection of commands.
  When trying to remember which of my commands
  are available in my <tt>~/bin/</tt> directory on a given system,
  or when simply trying to remember what
  some of my commands are called,
  I simply type a comma followed by <i>tab</i>
  and my list of commands appears:
</p>
<pre>$ ,<i>«tab»</i>
,complete-scp        ,go-thpgp            ,range
,complete-ssh        ,gr                  ,svn-store-password
,coreoff             ,hss                 ,umount
,coreon              ,mount-thpgp
,find                ,mount-twt</pre>
<p>
  I heartily recommend this technique
  to anyone with their own <tt>~/bin/</tt> directory
  who wants their command names kept clean, tidy,
  and completely orthogonal
  to any commands that the future might bring to your system.
  The approach has worked for me for something like a decade,
  so you should find it immensely robust.
  And, finally, it's just plain fun.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>The July 2009 issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-july/</link>
      <pubDate>Sat, 15 Aug 2009 03:50:14 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pymag-july/</guid>
      <description>The July 2009 issue of Python Magazine</description>

      <content:encoded><![CDATA[
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/static/2009/pymag-july.jpg"
       alt="Cover of July 2009 Python Magazine"
       width="200" height="258" />
</a>
<p>
  I am home from a relaxing vacation to the Midwest,
  and while I was gone last week my excellent publishing team
  released the July issue <i>Python Magazine</i> to the world.
  I am particularly pleased that two of the feature articles in this issue
  come from important segments of the Python world
  that we have not heard much from in previous issues.
</p>
<p>
  First,
  <a href="http://www.codeplex.com/IronPython"
     >IronPython, the .NET version of Python for Windows</a>,
  is the topic of Jonathan Hartley's article about acceptance testing.
  He illustrates that,
  regardless of the language
  in which you write your .NET application,
  you can deploy simple strategies
  to make your application testable
  through a Python test harness,
  and thereby bring Python's strong flexibility as a testing language
  to bear on a product
  that you might be writing in another .NET language.
</p>
<p>
  Second, Malthe Borch, a veteran of the Zope community,
  shares how he has written
  <a href="http://chameleon.repoze.org/">Chameleon,
  one of the fastest template language
  implementations available for Python</a>.
  By processing each template
  and turning it into Python bytecode
  before it is ever used to render a single page,
  Malthe eliminates a huge amount of redundant processing
  as that same code is used over and over again.
  His library is a key ingredient
  in the new high-efficiency web frameworks
  appearing in the Zope world.
  His work might even (fingers crossed) become one of the components
  that the Plone community uses
  as they streamline their framework
  and move towards a lighter and more agile “Plone 4”.
</p>
<p>
  Other technical topics covered are: the
  <a href="http://hadoop.apache.org/">Hadoop</a> map-reduce framework;
  the concept of hash functions, and how they apply to Python;
  and the new
  <a href="http://docs.python.org/library/string.html#format-string-syntax"
     >string formatting operator</a>
  which Guido hopes will replace all of the percent-signs
  that currently litter our code.
  Wrap it all up with an editorial by Steve Holden
  about <a href="http://www.europython.eu/">EuroPython 2009</a>
  and an editorial by me,
  and you have a complete issue!
  If you do not find Python Magazine
  sitting on your local newsstand,
  then I hope you will avail yourself of a subscription
  and, as always, let me know what topics
  you would like to see covered in future issues.
  Enjoy!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Installing "lxml" for Python under your WebFaction account</title>
      <link>http://rhodesmill.org/brandon/2009/installing-lxml-on-webfaction/</link>
      <pubDate>Sat, 01 Aug 2009 18:03:34 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[web notes]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/installing-lxml-on-webfaction/</guid>
      <description>Installing "lxml" for Python under your WebFaction account</description>

      <content:encoded><![CDATA[
<p>
  Well, drat.
</p>
<p>
  Thanks to more than an hour of work today,
  I have a pretty list of a few dozen commands
  that make it easy for a WebFaction account holder
  to install the powerful
  <a href="http://codespeak.net/lxml/">lxml</a> Python package
  for parsing HTML and XML under their hosting account.
  You can read Ian Bicking's wonderful blog post
  <a href="http://blog.ianbicking.org/2008/12/10/lxml-an-underappreciated-web-scraping-library/"
     >“lxml: an underappreciated web scraping library”</a>
  for more information on why you want to be using lxml
  instead of any of its alternatives.
</p>
<p>
  So, why do I say “drat”?
</p>
<p>
  First,
  because I just tried out my instructions on another
  of my WebFaction accounts,
  and there the extra steps weren't even necessary;
  this other server of theirs
  already had lxml's dependencies installed!
  I suppose, had I been a bit more patient, that
  <a href="http://forum.webfaction.com/viewtopic.php?id=2695"
     >this support ticket that I glanced over this morning</a>
  would have inspired me to ask WebFaction
  to install the libraries lxml needs
  on the server where I myself was working.
  But it felt like some sort of offense against symmetry
  to rely on something that WebFaction doesn't install everywhere,
  and I was perhaps just in too big of a hurry.
  Which, of course, cost more time in the end.
</p>
<p>
  The other reason I say “drat” is because,
  now that I look at Ian's post again after all these months,
  I see that he has instructions for making the package
  install its own dratted copies of the system libraries it needs!
  Too bad that
  <a href="http://codespeak.net/lxml/installation.html"
     >lxml's own installation instructions</a>
  omit this crucial piece of information.
</p>
<p>
  How typical, and how predictable.
  It turns out that I just needed to listen to Ian Bicking more carefully.
  How often we fail to do that,
  as individuals and as a Python community.
  Listen to Ian Bicking, everyone.
  Listen.
</p>
<p><a href="http://rhodesmill.org/brandon/2009/installing-lxml-on-webfaction/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>The Road to WebFaction</title>
      <link>http://rhodesmill.org/brandon/2009/the-road-to-webfaction/</link>
      <pubDate>Sat, 01 Aug 2009 16:48:59 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/the-road-to-webfaction/</guid>
      <description>The Road to WebFaction</description>

      <content:encoded><![CDATA[
<p>
  I am very happy with my first weeks of hosting sites at WebFaction.
  They have taken so much responsibility off of my shoulders.
  They run <a href="http://nginx.net/">nginx</a>
  in front of my web applications on my behalf.
  I fill out a simple form,
  placing Pylons under <tt>/</tt> and Wordpress under <tt>/blog</tt>,
  and they write all of the redirect rules to accomplish it.
  I list the domains and sub-domains on which my site should appear,
  and they configure the virtual hosting for me.
</p>
<p>
  WebFaction has even finally wrested domain name control from my fingers.
  Gone are the installations of
  <a href="http://en.wikipedia.org/wiki/BIND">bind</a>
  that used to be running everywhere,
  and the smattering of shell scripts with which I wrapped “nsupdate”
  to publish new host names.
  Now, I accomplish host name changes in a few moments
  through the control panel on WebFaction.
  This gives me more time to do creative things for my customers,
  and gives me one less daemon that I have to keep upgraded
  if I want to avoid security problems.
  (If you want to try them out for yourself,
  <a href="http://www.webfaction.com/?affiliate=rhodesmill"
     >using this WebFaction sign-up link</a>
  will credit me as the one who recommended them.)
</p>
<p>
  This move to making WebFaction
  my default choice for hosting new client projects
  is only the most recent chapter in the very long story
  of my devolving responsibilities on to other people.
  The previous steps went something like this:
</p>
<p><a href="http://rhodesmill.org/brandon/2009/the-road-to-webfaction/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Plone and IRC</title>
      <link>http://rhodesmill.org/brandon/2009/plone-and-irc/</link>
      <pubDate>Mon, 20 Jul 2009 17:05:53 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[zope]]></category>
      <guid>http://rhodesmill.org/brandon/2009/plone-and-irc/</guid>
      <description>Plone and IRC</description>

      <content:encoded><![CDATA[
<p><i>Hypothesis</i> — the vibrancy of a framework's IRC channel is proportional to the amount of time that the framework takes to start up each time you tweak your code or settings and need it reloaded.</p>
<p><i>Further hypothesis</i> — this relationship is non-linear. My guess is that frameworks which take, say, four seconds to restart probably get no more IRC attention than frameworks which take two seconds to restart, so adding mere seconds of delay to your framework's startup routine is not going to generate thriving community. There is, instead, a threshold — probably around ten or twelve seconds — above which the delay feels so long that the developer can, in good conscience towards their employer, switch over into IRC during a restart without feeling like they hurt their productivity.</p>
]]></content:encoded>
    </item>
    <item>
      <title>The terrible magic of setuptools</title>
      <link>http://rhodesmill.org/brandon/2009/eby-magic/</link>
      <pubDate>Wed, 15 Jul 2009 00:59:49 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/eby-magic/</guid>
      <description>The terrible magic of setuptools</description>

      <content:encoded><![CDATA[
<p>
  I am providing a bit of assistance to the wonderful
  <a href="http://www.nltk.org/">Natural Language Toolkit</a> Project,
  who have implemented a wide array
  of language processing algorithms in Python
  atop a common set of very sleek — and cleanly Pythonic —
  data structures for representing natural language.
  If you are at all interested,
  check out their recent book,
  <a href="http://www.amazon.com/gp/product/0596516495?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0596516495">Natural Language Processing with Python,</a><img class="inline" src="http://www.assoc-amazon.com/e/ir?t=letsdisthemat-20&l=as2&o=1&a=0596516495" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />
  which does a great job of showing how the NLTK works
  at the same time as it explains
  the computer science concepts of language processing.
</p>
<p>
  The NTLK project wants to support
  installing their package as a Python egg,
  so they asked me to tidy up their <tt>setup.py</tt> file
  and prepare everything for distribution via the Python Package Index.
</p>
<p>
  As usual,
  my desire for simple and reproducible behavior
  when distributing Python packages
  has run aground on the tangled magic
  for which <tt>setuptools</tt> is so justly famous.
</p>
<p><a href="http://rhodesmill.org/brandon/2009/eby-magic/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>The June 2009 issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-june/</link>
      <pubDate>Thu, 09 Jul 2009 19:38:22 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pymag-june/</guid>
      <description>The June 2009 issue of Python Magazine</description>

      <content:encoded><![CDATA[
<p>
The new issue of <i>Python Magazine</i> is out, and it's a technically hefty issue that, while lacking the kind of human-interest “what Python did for me” stories that I often use to balance the articles about programming, does do a really good job of showing the diverse kinds of problems that Python can tackle today.
</p>
<p>
Before detailing its content, I should apologize that the magazine keeps arriving later and later each month. Alert readers will have noticed that this “June” issue is actually appearing on July 9th. It is late because, in these inexperienced first few months as Editor-in-Chief, I have been treating magazine editing as a serial process, and have not <i>really</i> been starting work on an issue until the previous one is out the door. To fix things, I will start working more like an efficient, modern, pipelined microprocessor, and fetch articles for one issue while a second issue is being edited and yet a third is in layout to be published.
</p>
<p>
So, watch for a gradually improving schedule over the last half of this year! One reader wrote me to ask whether the late schedule was a sign that the publisher was losing interest in the publication. In fact, it is the person on staff who is <i>most</i> dedicated to Python — myself! — who is at fault, so no lack of interest in the publication is at all implied.
</p>
<p>
So, what does the “June” issue have to offer?
</p>
<p>
Plenty!
</p>
<p><a href="http://rhodesmill.org/brandon/2009/pymag-june/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>The Python language and poetry</title>
      <link>http://rhodesmill.org/brandon/2009/python-and-poetry/</link>
      <pubDate>Sat, 27 Jun 2009 16:26:29 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/python-and-poetry/</guid>
      <description>The Python language and poetry</description>

      <content:encoded><![CDATA[
<p>
If programming languages were poets,
which poet would the Python language be?
</p>
<p>
Obviously, Python would be
<a href="http://en.wikipedia.org/wiki/E._E._Cummings"
>e. e. cummings</a> —
the poet for whom whitespace was most truly significant!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>The May 2009 issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-may/</link>
      <pubDate>Fri, 05 Jun 2009 11:35:35 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pymag-may/</guid>
      <description>The May 2009 issue of Python Magazine</description>

      <content:encoded><![CDATA[
<p>
  The May issue of Python Magazine is now online!
  Obviously things fell a bit behind schedule this month,
  as I am writing this five days into the month of June.
  But with all of the excitement surrounding the publisher's
  flagship annual conference last month —
  php|tek 2009 in Chicago —
  it was certainly better that the magazine slip late
  than that delays interfere with an event
  which drew a couple of hundred people
  to learn more about quality software development.
</p>
<a class="image-reference">
  <img src="http://rhodesmill.org/brandon/static/2009/pymag-may.jpg"
       alt="Cover of May 2009 Python Magazine" />
</a>
<p>
  What can you look forward to reading?
  This issue worked out as a balance between community news
  and several sophisticated technical articles
  on using Python better.
  The technical articles include:
</p>
<p><a href="http://rhodesmill.org/brandon/2009/pymag-may/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>The April issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-april/</link>
      <pubDate>Sat, 02 May 2009 09:00:33 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pymag-april/</guid>
      <description>The April issue of Python Magazine</description>

      <content:encoded><![CDATA[
<p>
  It was back in the early 1990s,
  if memory serves me,
  that the Coca-Cola company —
  it may have been in one of their annual reports —
  decided to change their perspective.
  They declared that the soft drink market,
  of which they held more than 50%,
  was simply too small to remain their focus.
  Rather than wondering what marketing campaign
  might allow them to chip away a few more percentage points
  from their competitors,
  they drew attention to the fact
  that Coca-cola products represented only 2–3%
  of all fluids consumed, worldwide,
  and started thinking about how to increase <i>that</i> number.
  They decided, in other words, that their biggest competitor
  would no longer be Pepsi, but <i>water</i>.
</p>
<p>
  Now, think about the Python programming language,
  and try the same shift in perspective.
  Yes, we are all happy that readers of Linux Journal
  have selected
  <a href="http://www.linuxjournal.com/article/10451"
     >Python as their Favorite Programming Language</a>
  in this year's “Reader's Choice Awards”
  and we are pleased when we move up a few more percentage points
  in something like the
  <a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html"
     >TIOBE Programming Community Index</a>.
  But comparing our market share
  with that of other programming languages can,
  too often,
  fool us into thinking that we are playing a zero-sum game
  in which our own community can expand
  only by prying other programmers' fingers
  off of the languages they currently know and love.
</p>
<p>
  Try something else.
  Imagine <i>all</i> of the world's people, and ask:
  what percentage of <i>them</i> use Python?
  And what might it look like to increase <i>that</i> percentage?
  You will suddenly think of the grade school down the street,
  where you could volunteer one afternoon a week
  teaching Python programming at their computer club.
  You will realize that the local community college
  provides a simple IT curriculum,
  but gives their students no information
  about getting connected to a local programmer user's group.
  You will begin to wonder what difference simple Python skills
  might make in the hands of teenagers, college students,
  and young families raising children.
</p>
<p>
  You will, in other words,
  start thinking about how to change the world.
</p>
<p>
  And the reason that I'm excited about the
  April issue of Python Magazine
  is that our cover stories focus on Python programmers who,
  during the recent high-profile United States elections,
  made this kind of step outward
  into realizing what Python could do in their communities.
</p>
<ul>
  <li>
    <a href="http://www.mitchtrachtenberg.com/"
       >Mitch Trachtenberg</a> has written our feature article,
    about how his ballot scanning software
    helped election volunteers and officials
    in Humboldt County, California,
    discover that nearly 200 ballots had not been counted
    by their Premier Elections Solutions voting systems.
    Thanks to his efforts,
    California has now de-certified that particular software
    from being used in elections in their state.
  </li>
  <li>
    We also have an interview with
    <a href="http://bcn.boulder.co.us/~neal/"
       >Neal McBurnett</a>,
    whose <a href="http://www.electionaudits.org/"
             >ElectionAudits</a> software
    automated the statistical calculations in Boulder, Colorado,
    that allowed their election audits to focus on close races
    where more ballots have to be checked
    before a winner can be certified with confidence.
  </li>
  <li>
    To celebrate the fact that April 22nd was
    <a href="http://plone.org/events/wpd">World Plone Day</a>,
    we feature an <b>Introduction to Plone</b>
    with instructions for quickly downloading,
    installing, and customizing this popular Content Management System.
  </li>
  <li>
    Our more technical articles describe how to
    <b>create your own domain-specific language</b>
    with a parser that gets invoked
    when you run <tt>import</tt> on a file
    with an extension of your own choosing,
    and how to <b>create a protocol simulation framework</b>
    that lets you experiment
    with how packets will traverse a network.
    And Mark Mruss offers another Welcome to Python article
    that this time covers <b>Python dictionaries</b>,
    whose usefulness and elegant design were certainly a big part
    of my own adoption of the language.
  </li>
  <li>
    Finally,
    <a href="http://holdenweb.com/">Steve Holden</a>
    shares his perspective as head of the Python Software Foundation,
    this time reflecting on the wonderful
    <b>success of PyCon 2009</b> last month.
  </li>
</ul>
<p>
  I hope you'll take a look at this month's issue,
  and I hope that you learn as much from reading it
  as I myself learned from the process of editing.
  Enjoy!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>pyron: Making Python package development DRY to the point of no return</title>
      <link>http://rhodesmill.org/brandon/2009/pyron-no-return/</link>
      <pubDate>Wed, 22 Apr 2009 16:34:49 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pyron-no-return/</guid>
      <description>pyron: Making Python package development DRY to the point of no return</description>

      <content:encoded><![CDATA[
<p>
  I finally snapped last week.
</p>
<p>
  After years of writing verbose and repetitive <tt>setup.py</tt> files
  for my Python packages,
  I am unable to write another.
  Instead, I have started writing
  <a href="http://pypi.python.org/pypi/pyron/"
     >Pyron</a>,
  a tool that gathers the same information
  by inspecting a Python package itself.
  Not only does this mean that I get to
  <b>stop repeating myself</b>,
  but that my projects will become much more uniform
  because package metadata will be represented through
  <b>common conventions</b> instead of explicit (and repetitive) configuration.
  Though Pyron is still very primitive,
  it has already allowed me to reduce simple packages
  to only a <tt>README.txt</tt> plus their actual Python source code.
</p>
<p><a href="http://rhodesmill.org/brandon/2009/pyron-no-return/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Applying PDF watermarks upside down</title>
      <link>http://rhodesmill.org/brandon/2009/pdf-watermarks-upside-down/</link>
      <pubDate>Tue, 07 Apr 2009 23:49:33 EDT</pubDate>
      <category><![CDATA[document processing]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pdf-watermarks-upside-down/</guid>
      <description>Applying PDF watermarks upside down</description>

      <content:encoded><![CDATA[
<p>
Now that the excitement
of PyCon 2009 is over,
it is time for me to finish this brief series of blog posts
on watermarking PDF files.
In the
<a href="/brandon/2009/graphicsmagick-saved-the-day/"
   >first post I outlined how GraphicsMagick and Adobe Reader</a>
proved essential to the project
for their ability to produce correct PDF files
and then help me verify their correctness.
The
<a href="/brandon/2009/pdf-watermark-margins/"
   >second post showed how an image can be applied as a watermark</a>
using the <a href="http://www.pdfhacks.com/pdftk/">pdftk</a>
PDF Toolkit utility.
The resulting watermark,
after some margins had been added using a Python script,
looked rather attractive:
</p>
<div class="caption">
<a href="http://rhodesmill.org/brandon/static/2009/wmark2.pdf"
><img src="http://rhodesmill.org/brandon/static/2009/wmark2.png"
alt="Watermark with margins" />
</a><strong>Watermarked page (click for PDF).</strong>
The light blue design is a PDF file
that <tt>pdftk</tt> resizes and centers
on the target document.
</div>
<p>
My last challenge was that, on certain pages,
the watermark we were using
had to be turned upside down.
“Simple,” I thought, “I'll use <tt>pdftk</tt>
to turn the watermark over before applying it!”
I just had to process the watermark image
with the letter <tt>S</tt> (“south”),
which tells <tt>pdftk</tt> to rotate the image by 180°,
and then use the result as the watermark:
</p>
<pre>
$ pdftk arecibo2.pdf cat 1S output arecibo3.pdf
$ pdftk in.pdf background arecibo3.pdf output wmark3.pdf
</pre>
<div class="caption">
<a href="http://rhodesmill.org/brandon/static/2009/wmark3.pdf"
><img src="http://rhodesmill.org/brandon/static/2009/wmark3.png"
alt="Watermark with margins" />
</a><strong>Upside-down watermark (click for PDF).</strong>
Whoops! After turning the watermark upside down,
<tt>pdftk</tt> lost the ability to properly center it.
</div>
<p><a href="http://rhodesmill.org/brandon/2009/pdf-watermarks-upside-down/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>My first issue of Python Magazine</title>
      <link>http://rhodesmill.org/brandon/2009/pymag-marc/</link>
      <pubDate>Sat, 28 Mar 2009 12:18:16 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pymag-marc/</guid>
      <description>My first issue of Python Magazine</description>

      <content:encoded><![CDATA[
<p>
My first issue of Python Magazine is out!
</p>
<p>
After two months of being tutored in the arts of magazine publishing
by retiring editor Doug Hellmann,
March has been my first month in the Editor-in-Chief chair
of <a href="http://pythonmagazine.com/"><i>Python Magazine</i></a>.
It is exciting to have my first issue come out
while I am here at PyCon 2009
in Chicago.
I am talking with other programmers,
meeting new friends,
and, of course, eyeing everyone I meet
with the question of whether they might be suitable
author or technical editor material.
</p>
<p>
I am especially excited about our cover issue this month!
<b>“Commanding Robots with LEGO Mindstorms”</b> shows how simple it is
for a Python program to manipulate
both a binary on-the-wire protocol
<i>and</i> binary calls into a Windows DLL,
all without ever having to leave the Python standard library!
For me, this is the real magic of Python:
that it not only introduced an incomparably clean syntax
and tidy language feature set,
but that developers of both the standard library
and of third-party Python modules
are committed to creating vastly simple interfaces
for what in other languages can be very difficult problems.
The article is a great guide
to using best practices and powerful tools
when linking Python to other protocols and libraries.
</p>
<p>
Other articles include
<b>“Getting Started with Message Queues”</b>
which talks about how to arrange your application
around a central queue so that you can distribute expensive work
across dozens of machines;
<b>“Statically Analyzing Python Code”</b>
by the author of <a href="http://code.google.com/p/pysmell/">PySmell</a>
about how Python's built-in code parsing tools
can be used to start investigating powerful ideas
like type inferencing;
and <b>“Using Python for Pedigree Analysis”</b>
that is yet another success story from the world of science,
about how Python —
which began to be adopted very early in its history
by working scientists —
continues to move into new areas
wherever science needs a clean and powerful language
to replace the tangle of low-level code and temporary scripts
that traditionally characterize systems
written by those whose first expertise is not software design.
</p>
<p>
Throw in our several regular columns
and my own monthly editorial,
and you have a complete issue.
(I think it was while writing the editorial
that it really sank in that I am now an Editor-in-Chief!)
I hope you will consider subscribing,
and I especially hope you will subscribe to the print edition —
for only an extra dollar a month,
you will receive an actual, physical artifact
that you can leave in the breakroom at work,
share with a friend who wants to explore Python,
or leave at a client's site to expose their own employees
to the world of Python and its community.
And, say hello to me here at PyCon!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Adding margins to PDF watermarks</title>
      <link>http://rhodesmill.org/brandon/2009/pdf-watermark-margins/</link>
      <pubDate>Sun, 15 Mar 2009 23:24:26 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[document processing]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/pdf-watermark-margins/</guid>
      <description>Adding margins to PDF watermarks</description>

      <content:encoded><![CDATA[
<p>
This is the second article in my series
on adding “watermark” images to PDF files,
which sit behind any text and graphics that were already on the page.
Last week I outlined
<a
href="http://rhodesmill.org/brandon/2009/graphicsmagick-saved-the-day/"
>the first two lessons that I learned
while developing this watermark process</a>:
first, always use Adobe Acrobat
to verify that you are creating valid PDFs in your toolchain,
and second, the version of GraphicsMagick
that currently comes with Debian unstable
produces better PDF files
than the version of ImageMagick they ship.
</p>
<p>
Then I digressed with a blog entry on a slightly different topic,
<a href="http://rhodesmill.org/brandon/2009/nested-comprehensions/"
>nested list comprehensions in Python</a>,
because I happened to write one
while creating the image we will use as our sample watermark.
It shows the famous Arecibo space message,
and is a <a href="/brandon/static/2009/arecibo.png">tiny image</a>
of only 23×73 pixels
that looks like this when enlarged:
</p>
<div class="caption">
<img src="http://rhodesmill.org/brandon/static/2009/arecibo-big.png" alt="Arecibo message" />
</div>
<p>
The basic watermarking process itself is very simple
thanks to a wonderful tool that I discovered
called <a href="http://www.pdfhacks.com/pdftk/"><tt>pdftk</tt></a>
(short for “PDF toolkit”)
which, as usual, Debian has already packaged for me.
It can rotate documents,
extract pages,
concatenate several files together,
and help fill out PDF forms from data in a file.
Of particular interest here is its ability to either “stamp” an image
on top of each page of a document,
or to place one in the background as a watermark.
</p>
<p>
The watermark image itself has to be a PDF file —
<tt>pdftk</tt> does not deal in any other file formats —
which is why I needed GraphicsMagick
to convert the Arecibo image into a PDF in the first place.
Putting the two steps together,
one has a primitive but workable process
for using a PNG image as a watermark:
</p>
<pre>
$ gm convert arecibo.png arecibo.pdf
$ pdftk in.pdf background arecibo.pdf output wmark1.pdf
</pre>
<div class="caption">
<a href="http://rhodesmill.org/brandon/static/2009/wmark1.pdf"
><img src="http://rhodesmill.org/brandon/static/2009/wmark1.png"
alt="Letter with basic watermark" />
</a><strong>Hefty watermark (click for PDF).</strong>
A first attempt at watermarking results in a huge watermark
that reaches both to the top and bottom edges of the page.
</div>
<p>
As you can see,
<tt>pdftk</tt> automatically adjusts the size of the watermark image
to reach precisely to the edges of the page being marked —
which is a huge favor
given the difficulty I would have had
in resizing the watermark myself
to match the page size of the input file.
But, in the above case,
the result seems less than perfectly attractive;
watermarks usually sit tidily near the center of a page,
rather than running all the way against its edges.
</p>
<p>
Clearly, we want to add some margins to the watermark.
And though margins are easy to add to some image formats —
they would be simple to add
to the <tt>arecibo.png</tt> file that we are using
in this example —
in actual practice I need to support watermarks
that might be in vector formats like SVG or EPS.
While I could go through each possible input format
and contrive some way of adjusting its margins,
it would obviously be much more convenient
to convert everything to PDF first,
and then add margins directly to the PDFs.
</p>
<p>
I used Debian's <tt>apt-cache</tt> <tt>search</tt> command
to look for additional tools that might help me
(which is how I found <tt>pdftk</tt> in the first place!)
and found an old command called <tt>pdfcrop</tt>
that was part of the <tt>texlive</tt> series of packages;
it supports a <tt>--margins</tt> option
with which whitespace can be added around a PDF file.
But I found that it often would refuse to process
a perfectly good PDF file
with a horribly uninformative error message like:
</p>
<pre>
Error: Cannot move `tmp-pdfcrop-10631.pdf' to `out.pdf'!
</pre>
<p>
I tried to investigate the error message,
but discovered that <tt>pdfcrop</tt> is actually a Perl script
that writes LaTeX macros
which are then run against the target PDF file.
And it was last updated in 2004.
I have, alas, elected not to make it part of my toolchain.
</p>
<p>
Then I discovered that Python itself
has a <a href="http://pybrary.net/pyPdf/"
>quite serviceable PDF package named pyPdf</a>,
with the bonus that it is written in pure Python
and therefore requires no external libraries!
Thanks to its ability to adjust the “bounding box”
that defines the edges of an image in PDF coordinates,
adding margins was as simple as loading the image,
doing some addition and subtraction,
and then saving the result.
To add modest 10-point margins to the Arecibo message,
for example, we can create this <tt>wmargins.py</tt> script:
</p>


<div class="pygments_murphy"><pre><span class="kn">from</span> <span class="nn">pyPdf</span> <span class="kn">import</span> <span class="n">PdfFileWriter</span><span class="p">,</span> <span class="n">PdfFileReader</span>
<span class="n">pdf</span> <span class="o">=</span> <span class="n">PdfFileReader</span><span class="p">(</span><span class="nb">file</span><span class="p">(</span><span class="s">&#39;arecibo.pdf&#39;</span><span class="p">,</span> <span class="s">&#39;rb&#39;</span><span class="p">))</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">pdf</span><span class="o">.</span><span class="n">getPage</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">for</span> <span class="n">box</span> <span class="ow">in</span> <span class="p">(</span><span class="n">p</span><span class="o">.</span><span class="n">mediaBox</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">cropBox</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">bleedBox</span><span class="p">,</span>
                                    <span class="n">p</span><span class="o">.</span><span class="n">trimBox</span><span class="p">,</span> <span class="n">p</span><span class="o">.</span><span class="n">artBox</span><span class="p">):</span>
    <span class="n">box</span><span class="o">.</span><span class="n">lowerLeft</span> <span class="o">=</span> <span class="p">(</span><span class="n">box</span><span class="o">.</span><span class="n">getLowerLeft_x</span><span class="p">()</span> <span class="o">-</span> <span class="mi">10</span><span class="p">,</span>
                     <span class="n">box</span><span class="o">.</span><span class="n">getLowerLeft_y</span><span class="p">()</span> <span class="o">-</span> <span class="mi">10</span><span class="p">)</span>
    <span class="n">box</span><span class="o">.</span><span class="n">upperRight</span> <span class="o">=</span> <span class="p">(</span><span class="n">box</span><span class="o">.</span><span class="n">getUpperRight_x</span><span class="p">()</span> <span class="o">+</span> <span class="mi">10</span><span class="p">,</span>
                      <span class="n">box</span><span class="o">.</span><span class="n">getUpperRight_y</span><span class="p">()</span> <span class="o">+</span> <span class="mi">10</span><span class="p">)</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">PdfFileWriter</span><span class="p">()</span>
<span class="n">output</span><span class="o">.</span><span class="n">addPage</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">output</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">&#39;arecibo2.pdf&#39;</span><span class="p">,</span> <span class="s">&#39;wb&#39;</span><span class="p">))</span>
</pre></div>



<p>
You can test this yourself by installing pyPdf
in a convenient temporary directory with <tt>virtualenv</tt>,
running the above script, then calling <tt>pdftk</tt> on the result:
</p>
<pre>
$ virtualenv vpython
$ vpython/bin/easy_install pyPdf
$ vpython/bin/python wmargins.py
$ pdftk in.pdf background arecibo2.pdf output wmark2.pdf
</pre>
<div class="caption">
<a href="http://rhodesmill.org/brandon/static/2009/wmark2.pdf"
><img src="http://rhodesmill.org/brandon/static/2009/wmark2.png"
alt="Watermark with margins" />
</a><strong>Watermark with margins (click for PDF).</strong>
Margins prevent the watermark from reaching the page edges,
which allows the blocks of text to assume the role
of defining the visual shape of the page.
</div>
<p>
All pretty simple, right?
Well, it turns out that there was one final complication —
and that, before I was finished, I actually wound up spending
more than an hour reading the PDF specification
in order to understand what, exactly, was going wrong!
But that will be the topic for <a href="http://rhodesmill.org/brandon/2009/pdf-watermarks-upside-down/">my last blog post in this series.</a>
Stay tuned.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>I finally understand nested comprehensions</title>
      <link>http://rhodesmill.org/brandon/2009/nested-comprehensions/</link>
      <pubDate>Wed, 11 Mar 2009 16:22:47 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/nested-comprehensions/</guid>
      <description>I finally understand nested comprehensions</description>

      <content:encoded><![CDATA[
<p>
This entire blog post
can be summarized in the words of Guido himself
that I have just discovered down at the bottom of
<a href="http://www.python.org/dev/peps/pep-0202/">PEP-202</a>
(“List Comprehensions”):
</p>
<blockquote><p>
The form <tt>[... for x... for y...]</tt> nests, with the last index
varying fastest, just like nested for loops.
</p></blockquote>
<p>
Have you ever seen a Python list comprehension like that,
with <i>two</i> or more <tt>for</tt> loops inside?
I have just written my first one!
It was only recently that I discovered they were even possible,
when I encountered several in a draft of the upcoming
<a href="http://www.amazon.com/gp/product/0596516495?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596516495">Natural
Language Processing with Python</a> book.
(Which should be great — watch for O'Reilly to publish it!)
They almost never turn up in other code that I encounter,
and perhaps for good reason:
they were deeply confusing the first time I saw them!
</p>
<p>
The code I have just written is shown below.
It uses the
<a href="http://www.pythonware.com/products/pil/">Python Imaging Library</a>
to produce an image I will use
in the series of blog posts that
<a href="http://rhodesmill.org/brandon/2009/graphicsmagick-saved-the-day/"
   >I started yesterday on watermarking PDF files</a>.
The code requires a small
<tt><a href="/brandon/static/2009/arecibo.txt">arecibo.txt</a></tt>
file, detailing the radio message
that was sent from the Arecibo Observatory
in November 1974 to any other civilizations that might be listening.
As you can see, I have successfully used two <tt>for</tt> clauses
in the list comprehension that generates the image's pixels:
</p>


<div class="pygments_murphy"><pre><span class="sd">&quot;&quot;&quot;Draw the Arecibo message (blue on transparent).&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">PIL</span> <span class="kn">import</span> <span class="n">Image</span>
<span class="n">image</span> <span class="o">=</span> <span class="n">Image</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s">&quot;RGBA&quot;</span><span class="p">,</span> <span class="p">(</span><span class="mi">23</span><span class="p">,</span> <span class="mi">73</span><span class="p">))</span>
<span class="n">image</span><span class="o">.</span><span class="n">putdata</span><span class="p">([</span>
    <span class="p">(</span><span class="mi">192</span><span class="p">,</span><span class="mi">224</span><span class="p">,</span><span class="mi">255</span><span class="p">,</span><span class="mi">255</span><span class="p">)</span> <span class="k">if</span> <span class="n">char</span> <span class="o">==</span> <span class="s">&#39;1&#39;</span> <span class="k">else</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;arecibo.txt&#39;</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
    <span class="p">])</span>
<span class="n">image</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s">&#39;arecibo.png&#39;</span><span class="p">)</span>
</pre></div>



<p>
Each pixel is a four-value tuple, by the way,
because an RGBA image not only has a red, green, and blue
channel for each pixel,
but also an “A channel” specifying its opacity or transparency.
The colors in use here are a completely opaque light blue,
and a completely transparent color (the four zeros).
The result looks something like:
</p>
<div class="caption">
<img src="http://rhodesmill.org/brandon/static/2009/arecibo-big.png"
     alt="Arecibo message" />
</div>
<p>
My mistake in reading the multiple <tt>for</tt> clauses
was that, old C-language programmer that I am,
I was expecting the comprehension structure to be concentric.
That is, I thought that the last <tt>for</tt> must “enclose”
the ones above it,
creating a mess of lists inside of lists inside of lists.
But it turns out that they are much simpler to read than that.
<i>Just read them like normal loops,</i>
with the “big loop” described first
and the subsequent loops nested inside of it:
</p>


<div class="pygments_murphy"><pre><span class="c"># The list comprehension said:</span>
  <span class="p">[</span> <span class="o">&lt;</span><span class="n">i</span><span class="o">&gt;</span><span class="n">expression</span><span class="o">&lt;/</span><span class="n">i</span><span class="o">&gt;</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;arecibo.txt&#39;</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="p">]</span>

<span class="c"># It therefore meant:</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s">&#39;arecibo.txt&#39;</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">():</span>
        <span class="o">&lt;</span><span class="n">i</span><span class="o">&gt;</span><span class="nb">list</span><span class="o">&lt;/</span><span class="n">i</span><span class="o">&gt;.</span><span class="n">append</span><span class="p">(</span><span class="o">&lt;</span><span class="n">i</span><span class="o">&gt;</span><span class="n">expression</span><span class="o">&lt;/</span><span class="n">i</span><span class="o">&gt;</span><span class="p">)</span>
</pre></div>



<p>
So, to read the comprehension,
just picture colons appended to each <tt>for</tt> clause
and, finally, the <i><tt>expression</tt></i>
moved down inside of the innermost <tt>for</tt> loop.
</p>
<p>
Now that I have made this conceptual leap,
I can “picture” the normal <tt>for</tt> loops
each time I see a complicated list comprehension,
and they are trivial to read and write!
It still, I admit, feels odd that the <i><tt>expression</tt></i>,
which would be deep inside of normal <tt>for</tt> loops,
goes in front of them in a comprehension instead.
And I am not sure that double comprehensions
should become part of my normal coding style.
(How many other Python programmers understand them?
Has everyone else been using them without problems?)
But they are a neat trick to have up my sleeve
when I need to iterate over an image quickly
and want to pack everything into a single,
easily-bloggable expression.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>GraphicsMagick saved the day</title>
      <link>http://rhodesmill.org/brandon/2009/graphicsmagick-saved-the-day/</link>
      <pubDate>Tue, 10 Mar 2009 12:32:55 EDT</pubDate>
      <category><![CDATA[document processing]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/graphicsmagick-saved-the-day/</guid>
      <description>GraphicsMagick saved the day</description>

      <content:encoded><![CDATA[
<p>
I had never heard of
<a href="http://www.graphicsmagick.org/">GraphicsMagick</a> until yesterday,
when I discovered that the venerable, if clunky,
<a href="http://www.imagemagick.org/">ImageMagick</a> suite
was ruining one of my customer's print jobs
by producing invalid PDF files.
This is actually the third major failure
that this particular project has encountered
because of flaws in standard open-source document tools.
In this and my next two blog posts,
I will outline the bugs that I have encountered,
in the hopes of saving some future reader
the time that it took me to track them down.
</p>
<p>
But I will begin the series rather simply,
with the first two lessons that I learned during the project:
</p>
<dl>
<dt><b>1. Always verify PDF correctness with Adobe Acrobat.</b></dt>
<dd>
<p>
The trusty <a href="http://www.foolabs.com/xpdf/">Xpdf</a>
viewer, with which I have viewed PDF files for years,
turns out to have a remarkable ability
to decipher and display even somewhat damaged PDF files.
That's a great feature — <i>if</i> someone else has produced the PDF,
and you just need to read it, whether it's damaged or not.
But this “feature” becomes a problem
if you have just <i>produced</i>
a PDF, and want to know about any errors in the file
before your customer does!
</p>
<p>
In this situation, Adobe's
<a href="http://get.adobe.com/reader/">Acrobat Reader</a>
should be your viewer of choice.
Not only is it probably the software
that your customers will be using anyway,
but it is — and this seems intentional on Adobe's part —
a very stringent interpreter.
The error it displays for a corrupt PDF, I must admit,
is among the least-informative I have seen this month:
</p>
<pre>
There was a problem reading this document (14)
</pre>
<p>
But the information that this <i>does</i> yield is invaluable:
your customer will not be able to see or print this PDF
until you find the bug in your toolchain and fix the result.
It is, of course, objectionable and problematic
to have to install a closed-source product
on what might otherwise be a completely clean development system;
but I have found it irreplaceable
for its ability to show me problems
before my customers see them.
</p>
<p>
This mistake cost me more time than you might imagine.
The tool chain I built for my customer generates
several intermediate PDF files,
and it turns out that the error was happening
fairly early in the process —
so that one of the first files produced,
and therefore each subsequent PDF,
was invalid and could not be opened with Acrobat.
But because I was viewing them all with Xpdf,
I spent many minutes looking at the final step in the chain
and wondering why that PDF tool was often dying,
when the PDFs it was consuming looked so good in my viewer!
</p>
</dd>
<dt><b>2. Avoid <a href="http://www.imagemagick.org/">ImageMagick</a>
6.3.7 when producing PDFs;
try <a href="http://www.graphicsmagick.org/">GraphicsMagick</a> instead!</b>
</dt>
<dd>
<p>
More recent versions of ImageMagick might not have any problem
producing PDF files from PNG images,
but the ImageMagick that currently ships with Debian unstable,
version 6.3.7,
seems to have routine problems trying to turn some of my customer's
PNG files into valid PDFs.
To avoid having to compile, install, and maintain
my own version of ImageMagick,
I cast around for an alternative,
and was startled when Google brought me to
the <a href="http://www.graphicsmagick.org/">GraphicsMagick</a> project!
Here was ImageMagick done right:
instead of creating dozens of commands on your system,
as though this were the 1970s,
GraphicsMagick defines a single <tt>gm</tt> binary
with multiple sub-commands:
</p>
<pre>
$ gm convert watermark.png watermark.pdf
</pre>
<p>
Check out their web site for more great features;
but I'm simply happy that the PDFs it has produced so far
have been clean, correct, and consistent.
</p>
</dd>
</dl>
<p>
A question for my readers:
can a good, open-source PDF checker be found somewhere,
that is at least as stringent as Adobe Acrobat?
Leave a comment below if you have a suggestion;
such a tool would have made this project considerably easier!
</p>]]></content:encoded>
    </item>
    <item>
      <title>Installing Python packages for Emacs with virtualenv</title>
      <link>http://rhodesmill.org/brandon/2009/emacs-python-virtualenv/</link>
      <pubDate>Wed, 25 Feb 2009 18:25:15 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[emacs]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/emacs-python-virtualenv/</guid>
      <description>Installing Python packages for Emacs with virtualenv</description>

      <content:encoded><![CDATA[
The only rough edge I have found amidst the otherwise exceptional advice on Ryan McGuire's <a href="http://www.enigmacurry.com/">Enigma Curry blog</a> is that Ryan recommends installing Python packages with:
<pre>
$ sudo easy_install <i>package_url</i>
</pre>
This means that his Emacs configuration — which, very generously, <a href="http://www.enigmacurry.com/2009/01/19/my-emacs-config-on-github/">he has started maintaining as a project on github</a> so that other people can use it themselves, or branch their own versions — requires root access merely to install.

Like Ryan, I also keep my Emacs configuration under version control, so that improvements I check in from one account are easy to check out into all of my other accounts. Although my setup is probably too simple to be interesting as a public project, there is one aspect of it that I should share: unlike Ryan, I use the advanced technology of a <a href="http://pypi.python.org/pypi/virtualenv"><tt>virtualenv</tt></a> to hold the Python packages that Emacs needs. The virtual environment lives under my own account, and is easy to create, access, and rebuild, even in the absence of root privileges on a particular machine. Even better, packages that I install or upgrade inside of the virtual environment cannot interfere with Python programs running elsewhere on the system.

<p><a href="http://rhodesmill.org/brandon/2009/emacs-python-virtualenv/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>New Year's meme: What are the oldest files in your home directory?</title>
      <link>http://rhodesmill.org/brandon/2009/new-years-meme/</link>
      <pubDate>Thu, 01 Jan 2009 14:27:57 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[web notes]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2009/new-years-meme/</guid>
      <description>New Year's meme: What are the oldest files in your home directory?</description>

      <content:encoded><![CDATA[
<p>
Celebrate the new year with a blog post
discussing the oldest files
that are still sitting somewhere beneath your home directory!
The procedure is simple:
</p>
<ol>
<li>Run the following script in your home directory.
(You might want to use <i>less</i> to read the output.)</li>
<li>Ignore files whose date does not reflect your own activity.</li>
<li>List the oldest files in a blog post and discuss!</li>
</ol>


<div class="pygments_murphy"><pre><span class="c">#!/usr/bin/env python</span>
<span class="sd">&quot;&quot;&quot;Print last-modified times of files beneath &#39;.&#39;, oldest first.&quot;&quot;&quot;</span>
<span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">os.path</span><span class="o">,</span> <span class="nn">time</span>
<span class="n">paths</span> <span class="o">=</span> <span class="p">(</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">b</span><span class="p">,</span><span class="n">f</span><span class="p">)</span> <span class="k">for</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span><span class="n">ds</span><span class="p">,</span><span class="n">fs</span><span class="p">)</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">walk</span><span class="p">(</span><span class="s">&#39;.&#39;</span><span class="p">)</span> <span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="n">fs</span> <span class="p">)</span>
<span class="k">for</span> <span class="n">mtime</span><span class="p">,</span> <span class="n">path</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span> <span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">lstat</span><span class="p">(</span><span class="n">p</span><span class="p">)</span><span class="o">.</span><span class="n">st_mtime</span><span class="p">,</span> <span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">paths</span> <span class="p">):</span>
    <span class="k">print</span> <span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&quot;%Y-%m-</span><span class="si">%d</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">time</span><span class="o">.</span><span class="n">localtime</span><span class="p">(</span><span class="n">mtime</span><span class="p">)),</span> <span class="n">path</span>
</pre></div>



<p>
Only include files whose last-modified time
is a date on which you really touched the file.
The file's time should neither result from an error
(a few files beneath my own home directory
have an incorrect date of 1970-01-01),
nor from unpacking someone else's archive
that has old files inside of it.
For example,
I myself have excluded
the following pair of nearly 17-year-old files
because their dates reflect their age
inside of the Python 3.0 source archive,
instead of the actual moment last month
when they became part of my home directory:
</p>
<pre>
1992-03-02 ./src/Python-3.0/Demo/scripts/wh.py
1992-03-02 ./src/Python-3.0/Tools/scripts/dutree.doc
</pre>
<p>
But there is no requirement that the actual <i>content</i>
of each file you list be your own.
Whether you wrote the file yourself long ago,
or downloaded it from some ancient and forgotten FTP site,
you have a story to share!
</p>
<p>
Within the rules given above,
here are the oldest files beneath my own home directory:
</p>
<p><a href="http://rhodesmill.org/brandon/2009/new-years-meme/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Why triple-quotes make PyFlakes hang Emacs</title>
      <link>http://rhodesmill.org/brandon/2008/why-triple-quotes-make-pyflakes-hang-emacs/</link>
      <pubDate>Sun, 14 Dec 2008 17:41:58 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/why-triple-quotes-make-pyflakes-hang-emacs/</guid>
      <description>Why triple-quotes make PyFlakes hang Emacs</description>

      <content:encoded><![CDATA[
<p>
I need to refine the aspersions
which I cast against PyFlakes last night
in my
<a href="http://plope.com/bounty_solved">response to Chris McDonough</a>,
answering his
<a href="http://plope.com/pyflakes_flymake_bounty">bounty against the
bug that Emacs would hang</a>
in Flyspell mode when he typed triple-quotes.
My email, I admit, was not entirely fair to PyFlakes;
but you must remember
that I was writing late at night, and in great haste,
wanting to be the first to respond
among however many dozens of Emacs LISP programmers
were racing to converge on the solution to Chris's problem.
</p>
<p>
My mistake was to exaggerate somewhat
the verbosity with which PyFlakes reports a syntax error.
My email to Chris, in fact, made the following rather extravagant claim:
</p>
<blockquote><p>
The problem is that … on a syntax error,
PyFlakes prints out an error message,
then the <i>entire</i> contents of the module that it cannot import,
and <i>finally</i> a line that contains a number of spaces
equal to the offset into the file of the syntax error …
</p></blockquote>
<p>
Just glancing at the PyFlakes source code
is enough to see that this accusation cannot be true:
</p>
<pre>
    try:
        ...
    except (SyntaxError, IndentationError):
        value = sys.exc_info()[1]
        (lineno, offset, line) = value[1][1:]
        ...
        print >> sys.stderr, 'could not compile %r:%d:' \
            % (filename, lineno)
        <b>print >> sys.stderr, line
        print >> sys.stderr, " " * (offset-2), "^"</b>
</pre>
<p>
Clearly, this simply prints the line
that the Python exception cites as having caused the problem,
followed by a primitive attempt to position a <tt>^</tt> character
at the location of the error.
For simple syntax errors, this actually produces output
which is identical to that of normal Python:
</p>
<pre>
$ <b>python error1.py</b>
  File "error1.py", line 3
    return x y
             ^
SyntaxError: invalid syntax
$ <b>pyflakes error1.py</b>
could not compile 'error1.py':3:
    return x y
             ^</pre>
<p>
But the PyFlakes behavior is quite different
from that of the standard interpreter
if the syntax error happens in a Python statement
that has been continued across several lines of source code.
Imagine that there are two functions in a file,
and that we have started typing a docstring for the first one
but have not yet closed the triple-quote:
</p>
<pre>
def square(x):
    <b>"""Returns the square of x.</b>
    return x * x

def cube(x):
    """Returns the cube of x."""
    return x * x * x
</pre>
<p>
Here, Python and PyFlakes give quite different reports:
</p>
<pre>
$ <b>python error2.py</b>
  File "error2.py", line 6
    """Returns the cube of x."""
             ^
SyntaxError: invalid syntax
$ <b>~/.emacs.d/usr/bin/pyflakes error2.py</b>
could not compile 'error2.py':6:
    """Returns the square of x.
    return x * x

def cube(x):
    """Returns the cube of x."""
 ...<i>76 spaces</i>... ^</pre>
<p>
Do you see what has happened?
The unterminated triple-quoted string
looks as though it ends several lines later,
at what we ultimately intend to be the beginning
of the <i>next</i> triple-quoted string.
(If the file instead contained <i>no</i> further triple-quoted strings,
then the new string
would appear to extend all the way to the end of the file.)
</p>
<p>
This is no problem for the Python interpreter itself,
which modestly displays only the final line
of the multi-line syntax error.
But PyFlakes, not checking for this possibility,
prints out the <i>entire</i> triple-quoted string,
followed by a <tt>^</tt> character that is indented
the <i>entire</i> length of the triple-quoted string.
In the example that I was testing last night,
this produced a line of nearly four thousand spaces
that then ended in the lone little caret character.
</p>
<p>
So while PyFlakes is certainly more verbose than standard Python,
it is not being nearly as profligate as I claimed.
It does <i>not</i> insist on printing out your whole module,
but limits its output to lines
that actually appear involved in the error.
Either way, it is the following line —
the one that starts with all of the spaces —
that is really the problem,
since too many spaces
send one of the Emacs Flymake regular expressions
spiralling into exponential oblivion.
</p>
<p>
Perhaps Flymake should support a command-line option
that omits code snippets entirely,
so that Emacs will have only error messages to process.
Either way,
Chris and I can be more productive
now that we can safely integrate
a patched version of this excellent tool
into our coding sessions.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>PyEphem now available for Python 3.0!</title>
      <link>http://rhodesmill.org/brandon/2008/pyephem-now-available-for-python-30/</link>
      <pubDate>Sat, 13 Dec 2008 02:05:07 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[pyephem]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/pyephem-now-available-for-python-30/</guid>
      <description>PyEphem now available for Python 3.0!</description>

      <content:encoded><![CDATA[
<p>
Eager not to be left behind by the advance of history,
I have released <a href="http://rhodesmill.org/pyephem/">PyEphem</a>
tonight for Python 3.0!
After updating its C-language routines earlier this week,
as <a
href="http://rhodesmill.org/brandon/2008/porting-a-c-extension-module-to-python-30/">described
in my previous post</a>,
and adjusting its Python syntax,
I thought that my work was done —
until I received a bug report from Reto Schüttel,
an enterprising Swiss programmer.
He had read my previous post,
asked me for the location of PyEphem's <a
href="https://code.launchpad.net/~brandon-rhodes/pyephem/python-3">Python 3.0
branch</a>,
downloaded it with <a href="http://bazaar-vcs.org/">bzr</a>,
and already tried it out, not only on his Linux machine,
but <i>also</i> on his OS X machine!
</p>
<p>
While the <a
href="http://bazaar.launchpad.net/~brandon-rhodes/pyephem/python-3/changes/419?start_revid=419">first
twenty revisions</a> of my branch deal with simple Python 3.0 mechanics,
I must congratulate Mr. Schüttel
for most of the improvements in the <a
href="http://bazaar.launchpad.net/~brandon-rhodes/pyephem/python-3/changes/431?start_revid=431">subsequent
dozen revisions</a>.
We not only exchanged emails all day
as I produced one revision after another
that I needed him to test,
but he then joined me on IRC tonight until 3:30am in his time zone
as we worked out the last problems.
</p>
<p>
The issues were all related to localization under OS X.
The astronomy library underlying PyEphem used the C-language functions
<tt>sscanf()</tt> and <tt>atof()</tt>
to turn strings into numbers,
and it turns out that these functions are very sensitive to locale
under the specific combination of OS X and Python 3.0!
Because of his locale,
the functions wanted a comma instead of a period
to separate whole numbers from their decimal fraction
(so that <i>π</i> would have to be input like <tt>3,141</tt>
rather than like <tt>3.141</tt>).
They also wanted month name abbreviations
to be in German rather than English,
ruining my test cases
that check planet positions against
<a href="http://www.usno.navy.mil/">Naval Observatory</a> tables
which use English month abbreviations
like <i>Jan</i>, <i>Feb</i>, and <i>Mar</i>
with very little regard for how the months would be spelled in German.
We are still mystified by the combination of Python version
and operation system that were necessary to cause this problem:
</p>
<pre>
Python 2.6 under Linux: tests passed
Python 3.0 under Linux: tests passed
Python 2.6 under OS X: tests passed
Python 3.0 under OS X: <b>broken: sscanf()/atof() change with locale</b>
</pre>
<p>
But the tests worked fine if he put <tt>LANG=C</tt> on the command line.
</p>
<p>
To work around this problem,
I discovered a wonderful <tt>PyOS_ascii_strtod()</tt> function
in Python's C library that avoided all of the problems
that I was having with localization,
and so I gradually rewrote the astronomy routines
to use that function instead.
Fixing the problems with month names was easier;
instead of trying to make Python convert month abbreviations
by passing the <tt>'%b'</tt> conversion character
to <tt>time.strptime()</tt>,
I simply converted months to integers myself
and then passed the integers in
with the simpler <tt>'%m'</tt> format character.
It was only late at night
that we finally tracked down every routine that was misbehaving.
</p>
<p>
The final puzzle was how to release my new software.
The <a href="http://pypi.python.org/pypi">Python Package Index</a>
does not yet allow a project to offer separate source code archives
for both the Python 2.x and the 3.0 version of a project.
There might be some clever way
of storing both versions of the source code
in the same <tt>.tar.gz</tt> file,
but the packages I see on PyPI that already support both 2.x and 3.0
contain enough <tt>#ifdef</tt> statements
to convince me that I want to keep my branches separate!
</p>
<p>
I was saved by a peculiarity of my project.
Though it provides the Python <i>package</i> named <tt>ephem</tt>,
the actual <i>project</i> on PyPI
has always been named “PyEphem” instead.
The product has to have the “Py” in front, you see,
to distinguish it
both from the original text-screen <tt>ephem</tt> command
and the modern
<a href="http://www.clearskyinstitute.com/xephem/">XEphem</a>
graphical application,
and my first instinct had been to name the project after the product.
But as I gained experience with PyPI,
it seemed more and more awkward
that programmers who wanted their programs to be able to:
</p>
<pre>import ephem</pre>
<p>
had to remember to type something different when installing:
</p>
<pre>easy_install pyephem</pre>
<p>
Since I had been wanting to switch PyPI names anyway,
I suddenly saw my chance!
I have now released the new Python 3.0 version of PyEphem
<a href="http://pypi.python.org/pypi/ephem/">under
the actual package name <i>ephem</i></a>
and will continue to maintain the 2.x version of the package
separately under
<a href="http://pypi.python.org/pypi/pyephem/">the old <i>pyephem</i>
name</a>.
Obviously,
this solution only works because of my project's unique circumstances;
I have no idea what other projects should do
who also want to come out with their new Python 3.0 versions
this weekend.
</p>
<p>
Fans of PyEphem should rest assured
that when I develop new features,
I will be adding them to <i>both</i> versions
of PyEphem for probably at least the next decade.
I have absolutely no intention of abandoning or slowing development
of the Python 2.x version of the library;
I simply wanted the library available to users of the new platform.
As always,
feel free to email me with bugs, suggestions, and new features —
and, enjoy using PyEphem and Python!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Porting a C extension module to Python 3.0</title>
      <link>http://rhodesmill.org/brandon/2008/porting-a-c-extension-module-to-python-30/</link>
      <pubDate>Tue, 09 Dec 2008 04:18:16 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[pyephem]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/porting-a-c-extension-module-to-python-30/</guid>
      <description>Porting a C extension module to Python 3.0</description>

      <content:encoded><![CDATA[
<p>
With several packages already advertising
<a href="http://pypi.python.org/pypi?:action=browse&c=214&c=534"
 >Python 3.0 compatibility</a>,
it seemed high time to look into releasing my
<a href="http://rhodesmill.org/pyephem/">PyEphem astronomy package</a>
in an edition compatible with the new language.
But I hesitated:
how difficult is it <i>really</i>,
and how many hours of work will it consume,
to port a C-language extension module to Python 3.0?
</p>
<p>
The answer is that,
while the necessary changes were surprisingly easy,
they took lots of time to figure out
because I did not find them documented in any one place.
I offer the following notes to assist
any other adventurers who want to experiment
with porting their extension modules to 3.0.
These notes might also suggest
useful additions to the official documentation.
</p>
<p>
But, first, I need to issue three cautions.
To develop under 3.0, you may have to forego several Python tools
that you probably thought you could no longer do without.
The world of 3.0 is a windswept and icy landscape
from which the glaciers have just receded,
and you will find the stone tools rather primitive
when compared to the comforts of civilization
that you enjoy under Python 2.
To wit:
</p>
<ul>
<li>I cannot find
 <a href="http://pypi.python.org/pypi/virtualenv/1.3.1">virtualenv</a>
 for 3.0,
 which is a disaster.
 This means that you have to create a separate Python 3.0 install,
 built with a different <tt>--prefix</tt> option to <tt>./configure</tt>,
 for each development environment you want to create on your box.
</li>
<li>I cannot find a version of the
 <a href="http://peak.telecommunity.com/DevCenter/setuptools">setuptools</a>
 available for 3.0.
 This means limiting your <tt>setup.py</tt> instructions
 to the primitive vocabulary of the <tt>distutils</tt> package.
 For example,
 I find myself unable to run the PyEphem test suite at this late hour
 because I have been running it for so long with:
 <pre>$ python setup.py test</pre>
 that I am not sure how to get it running otherwise.
</li>
<li>Should you succeed in porting your extension module,
 it is not at <i>all</i> clear how to distribute it.
 I had expected either a new PyPI to spring into being —
 since every package will need an entirely different version under 3.0 —
 or for a sophisticated scheme to appear
 for registering one <tt>pyephem.tar.gz</tt> as the Python 2 version
 and another <tt>pyephem.tar.gz</tt> for 3.0.
 But while the most recent version of your package can
 mark itself as
 <a href="http://pypi.python.org/pypi?:action=browse&c=214&c=527"
  >2-compatible</a> or
 <a href="http://pypi.python.org/pypi?:action=browse&c=214&c=533"
  >3-compatible</a> (or both)
 using classifiers,
 there is no way to have <i>two</i> “most recent” versions
 of a package.
 Are we supposed to start distributing a single <tt>tar.gz</tt>
 that includes the source code for both Python series,
 and that selects the right code by detecting the interpreter version
 at the top of the <tt>setup.py</tt> file?
</li>
</ul>
<p>
So if you make the effort to port your code right now,
you might find that the shiny new version of your module
is all dressed up, but has no place to go.
If you experiment with the following steps, though,
you will at least be ready
when an official distribution channel does appear
for releasing your package into the wilds of 3.0.
</p>
<p><a href="http://rhodesmill.org/brandon/2008/porting-a-c-extension-module-to-python-30/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Comprehension consistency at last in Python 3.0!</title>
      <link>http://rhodesmill.org/brandon/2008/comprehension-consistency-at-last-in-python-30/</link>
      <pubDate>Thu, 04 Dec 2008 12:13:39 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/comprehension-consistency-at-last-in-python-30/</guid>
      <description>Comprehension consistency at last in Python 3.0!</description>

      <content:encoded><![CDATA[
<p>
A new era is begun: <a href="http://www.python.org/download/releases/3.0/">Python 3.0 has been released</a>, bringing the bright and burning lights of reason, consistency, and symmetry to bear on my favorite language.  Guido van Rossum, the creator of Python, has carefully guided this final attempt to remove the warts that have accumulated over the language's 17-year lifetime, and the result is magical.
</p>


<div class="pygments_murphy"><pre><span class="n">Python</span> <span class="mf">3.0</span> <span class="p">(</span><span class="n">r30</span><span class="p">:</span><span class="mi">67503</span><span class="p">,</span> <span class="n">Dec</span>  <span class="mi">4</span> <span class="mi">2008</span><span class="p">,</span> <span class="mi">10</span><span class="p">:</span><span class="mi">23</span><span class="p">:</span><span class="mi">44</span><span class="p">)</span>
<span class="p">[</span><span class="n">GCC</span> <span class="mf">4.3</span><span class="o">.</span><span class="mi">2</span><span class="p">]</span> <span class="n">on</span> <span class="n">linux2</span>
<span class="n">Type</span> <span class="s">&quot;help&quot;</span><span class="p">,</span> <span class="s">&quot;copyright&quot;</span><span class="p">,</span> <span class="s">&quot;credits&quot;</span> <span class="ow">or</span> <span class="s">&quot;license&quot;</span> <span class="k">for</span> <span class="n">more</span> <span class="n">information</span><span class="o">.</span>
<span class="o">&gt;&gt;&gt;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="p">[</span> <span class="n">n</span><span class="o">*</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="p">]</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">16</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="p">{</span> <span class="n">n</span><span class="o">*</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="p">}</span>
<span class="p">{</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">9</span><span class="p">}</span>
<span class="o">&gt;&gt;&gt;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="p">{</span> <span class="n">n</span><span class="p">:</span> <span class="n">n</span><span class="o">*</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="p">}</span>
<span class="p">{</span><span class="mi">0</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">4</span><span class="p">:</span> <span class="mi">16</span><span class="p">}</span>
</pre></div>



<p>
Magnificence!  Do you feel the waves of beauty crashing over you?  No, no, not over the sequence of squares&nbsp;— over the fact that <b>all three basic collection types now support comprehensions!</b>
</p>
<p>
Comprehensions were first introduced in Python&nbsp;2.0, but with the terribly awkward stipulation that they were only possible for lists, not for dictionaries. This meant teaching newcomers to the language that list construction was a special case, and that the collections that had deserved their own constructor syntax (lists and dictionaries, at that time; sets came later) were not equally powerful. It also made necessary the awkward and expensive technique of building, and then immediately discarding, a list of tuples to quickly construct dictionaries:
</p>


<div class="pygments_murphy"><pre><span class="n">Python</span> <span class="mf">2.5</span><span class="o">.</span><span class="mi">2</span> <span class="p">(</span><span class="n">r252</span><span class="p">:</span><span class="mi">60911</span><span class="p">,</span> <span class="n">Nov</span> <span class="mi">14</span> <span class="mi">2008</span><span class="p">,</span> <span class="mi">19</span><span class="p">:</span><span class="mi">46</span><span class="p">:</span><span class="mi">32</span><span class="p">)</span>
<span class="p">[</span><span class="n">GCC</span> <span class="mf">4.3</span><span class="o">.</span><span class="mi">2</span><span class="p">]</span> <span class="n">on</span> <span class="n">linux2</span>
<span class="n">Type</span> <span class="s">&quot;help&quot;</span><span class="p">,</span> <span class="s">&quot;copyright&quot;</span><span class="p">,</span> <span class="s">&quot;credits&quot;</span> <span class="ow">or</span> <span class="s">&quot;license&quot;</span> <span class="k">for</span> <span class="n">more</span> <span class="n">information</span><span class="o">.</span>
<span class="o">&gt;&gt;&gt;</span>
<span class="o">&gt;&gt;&gt;</span> <span class="nb">dict</span><span class="p">([</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">n</span><span class="o">*</span><span class="n">n</span><span class="p">)</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="p">])</span>
<span class="p">{</span><span class="mi">0</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">:</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">3</span><span class="p">:</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">4</span><span class="p">:</span> <span class="mi">16</span><span class="p">}</span>
</pre></div>



<p>
The arrival of generator expressions in&nbsp;2.4 did, at least, allow us to remove the ugly square brackets and avoid creating the list (though all of the tuples still got created then immediately discarded).  But the problem remained that dictionaries made from inline generators did not <i>look</i> like dictionaries syntactically.
</p>
<p>
But, no more!   They have even updated the scandalously withdrawn <a href="http://www.python.org/dev/peps/pep-0274/">PEP&nbsp;274</a> to announce that the feature has finally arrived.  After the aching and painful years of the Python&nbsp;2 series, the language once again shines bright and clear as a model of clever symmetries and low mental impedance.  Python's famously tight "feature set" can, now more easily than ever, fit comfortably into the programmer's brain.
</p>
<p>
What shall I write first in Python&nbsp;3.0?  I wonder.
</p>
<p>
But you can be sure that my code will find lots of excuses for constructing dictionaries.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Rise and Fall of the Two Waldos</title>
      <link>http://rhodesmill.org/brandon/2008/rise-and-fall-of-the-two-waldos/</link>
      <pubDate>Wed, 05 Nov 2008 09:41:01 EST</pubDate>
      <category><![CDATA[web notes]]></category>
      <guid>http://rhodesmill.org/brandon/2008/rise-and-fall-of-the-two-waldos/</guid>
      <description>Rise and Fall of the Two Waldos</description>

      <content:encoded><![CDATA[
<p>
I am experiencing my Flickr photostream in an entirely new way
thanks to the tools they introduced this year
for monitoring the traffic received by individual photographs.
The old, static parts of my photostream suddenly look dynamic:
I can see the <i>rate</i>
at which each old photo is continuing to attract viewers.
On October 17th, for example, I
was stunned to discover that the perennial favorite
<a href="http://www.flickr.com/photos/brandonrhodes/40609212/">Harry
Potter Lunchbox</a> had, over the previous day,
received <i>fewer</i> views than the perpetually distant second,
<a href="http://www.flickr.com/photos/brandonrhodes/41593686/">“My
Shirt”</a>
(both taken at Dragon*Con 2005).
Here is Flickr's graph of how “My Shirt” fared over the month of
October, with my mouse over October 17th
to highlight the day on which I first noticed its growing popularity:
</p>

<div class="caption">
<a href="http://rhodesmill.org/brandon/static/2008/my-shirt-stats.png">
<img src="http://rhodesmill.org/brandon/static/2008/my-shirt-stats-thumb.png"
     alt="graph of the photograph popularity" /></a>
The rise and fall of the popularity of
<a href="http://www.flickr.com/photos/brandonrhodes/41593686/">“My
Shirt”</a>
over the four weeks from 5 October through 1 November.
</div>

<p>
And by drilling down into the list of “Referrers” beneath the graph,
I was even able to discover the source of its brief popularity!
As Halloween approached,
people were doing hundreds of
<a href="http://images.google.com/imghp?tab=wi">Google Image</a>
searches
for “waldo costume,” “where's waldo costume,”
and “where's waldo shirt,”
which brought them straight to my image.
As you can see in the above graph,
the swelling interest did not peak until Halloween itself,
after which the photo plummeted back to its more typical popularity
of one or two dozen views per day.
</p>

<p>
All sorts of gems are hidden in the statistics,
waiting to be discovered.
For example,
it was very satisfying to learn
that <a href="http://images.search.yahoo.com/">Yahoo! Image Search</a>
considers my wedding photograph
<a href="http://www.flickr.com/photos/brandonrhodes/79478143/">A
Grandfather in Attendance</a>
to be the most important “grandfather” image on the entire web.
Behind every statistic is a story about how people find,
and why they wind up visiting, each of my photos.
Hopefully the fun of watching my old photographs
will not distract me from taking some new ones!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>The idea of a term paper</title>
      <link>http://rhodesmill.org/brandon/2008/the-idea-of-a-term-paper/</link>
      <pubDate>Sat, 25 Oct 2008 12:14:01 EDT</pubDate>
      <category><![CDATA[web notes]]></category>
      <guid>http://rhodesmill.org/brandon/2008/the-idea-of-a-term-paper/</guid>
      <description>The idea of a term paper</description>

      <content:encoded><![CDATA[
<p>
Displaying their usual talent for excerpt,
the folks at <a href="http://aldaily.com">Arts &amp; Letters Daily</a>
directed my attention to a recent article
in <a href="http://www.thesmartset.com/">The Smart Set</a>
with this intriguing summary of its contents:
</p>

<blockquote><p><b>Term paper mill.</b> Need $100 by Friday to keep the lights on? No sweat, if you’re a writer. Plenty of kids need ten pages on Hamlet by Thursday... <a href="http://www.thesmartset.com/article/article10100801.aspx">more»</a></p></blockquote>

<p>
The article,
entitled “<a href="http://www.thesmartset.com/article/article10100801.aspx"
 >Term Paper Artist</a>”,
alternates between hilarity and poignancy
as its author shares his adventures
writing hundreds of term papers for hire.
But near the end,
his tone suddenly becomes serious
as he turns to the question of <i>why</i> so many students
are unable to write term papers of their own.
He thinks that the reason is important enough
to stand alone in his article as a one-sentence paragraph.
Here is his preceding paragraph, and then the zinger:
</p>

<blockquote>
<p>It's not that I never felt a little skeevy writing
papers. Mostly it was a game, and a way to subsidize my more interesting
writing. Also, I've developed a few ideas of my own over the years. I
don't have the academic credentials of composition experts, but I doubt
many experts spent most of a decade writing between one and five term
papers a day on virtually every subject. I know something they don't
know; I know why students don't understand thesis statements,
argumentative writing, or proper citations.
</p>
<p>
It's because students have never read term papers.
</p>
</blockquote>

<p>
That is his diagnosis:
students never see what term papers are <i>supposed</i> to look like,
and so they have no idea how to produce them.
</p>

<p>
As he continued on,
ridiculing the idea that students
can produce something of which they are never once shown a good example,
I realized that his argument was exactly the same
as the one I made in my recent post
<a href="http://rhodesmill.org/brandon/2008/reading-code-curriculum/"
 >Reading Code: A Computer Science Curriculum</a>:
that the production of any kind of literature,
whether an essay in college or an elaborate routine in a computer program,
is an essentially imitative act.
Without being shown excellent examples
from the genre they are expected to produce,
students are left in the dark about what,
exactly, they are trying to generate —
and, more often than not, will fail.
They are never even given the opportunity
to demonstrate whether they do, in fact, lack the capacity to create,
because they are never shown the goal
towards which they are supposed to be striving.
</p>]]></content:encoded>
    </item>
    <item>
      <title>Reading Code: A Computer Science Curriculum</title>
      <link>http://rhodesmill.org/brandon/2008/reading-code-curriculum/</link>
      <pubDate>Tue, 19 Aug 2008 17:56:50 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/reading-code-curriculum/</guid>
      <description>Reading Code: A Computer Science Curriculum</description>

      <content:encoded><![CDATA[
<blockquote><p>
I developed the following ideas
about how to teach computer programming
during a recent conversation with
<a href="http://www.chrio.org/dan/">Daniel Rocco</a>,
a professor at the University of West Georgia,
and Georgia Tech grad student Derek Richardson,
and I wanted to expand on the ideas here on my blog.
I have been heavily influenced by reading
<a href="http://www.cs.toronto.edu/~gvwilson/">Greg Wilson</a>,
and, for all I know, he or someone else
may have already put these ideas together
into something like the outline below.
</p></blockquote>

<h2>The first day of class</h2>

<p>
To teach computer programming,
a professor ought to stride into the room on the semester's first day,
explain that a <i>computer program</i> is a text file
full of instructions for the computer to follow,
and then proceed to check out an example from version control.
His desktop should be displayed on a big screen in front of the class.
He should read through the example program with them, discuss it —
it should be a Python program that does something requiring two or three
dozen lines,
like opening a window and displaying the message, “Hello, world!” —
and then run it.
He should demonstrate how to edit the program
so that it prints something else instead (perhaps “Hello, professor!”),
run the altered version for them,
and, finally, check the modified program into version control.
</p>

<p>
The class now has the tools they need
to complete their first assignment.
The students are told that a version-control repository
has been created for each of them;
that they have each been subscribed to their repository's email
notification list;
and that, upon returning home from class,
their email inbox will already hold a message
informing them that their first assignment —
the “Hello, world!” program itself —
has been checked into their repository by the course software.
By the next class period
they are to have checked the assignment out,
altered it so that it prints “Hello” followed by their own name,
and submitted the assignment by checking the program back in.
</p>

<p><a href="http://rhodesmill.org/brandon/2008/reading-code-curriculum/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Aphorism</title>
      <link>http://rhodesmill.org/brandon/2008/aphorism/</link>
      <pubDate>Mon, 11 Aug 2008 08:10:14 EDT</pubDate>
      <category><![CDATA[books]]></category>
      <guid>http://rhodesmill.org/brandon/2008/aphorism/</guid>
      <description>Aphorism</description>

      <content:encoded><![CDATA[
<p>
Entertainment wants only to satisfy its audience;<br>
but Art will teach us <i>new</i> desires.
</p>
<p>
<i>(Penned after pondering the talk that <a href="http://www.danagioia.net/">Dana Gioia</a> gave at <a href="http://www.cslewis.org/programs/oxbridge/2008/">Oxbridge 2008</a>)</i>
</p>
]]></content:encoded>
    </item>
    <item>
      <title>PyEphem 3.7.2.4, now on Launchpad!</title>
      <link>http://rhodesmill.org/brandon/2008/pyephem-3724-now-on-launchpad/</link>
      <pubDate>Sat, 14 Jun 2008 13:39:57 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[pyephem]]></category>
      <category><![CDATA[web notes]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/pyephem-3724-now-on-launchpad/</guid>
      <description>PyEphem 3.7.2.4, now on Launchpad!</description>

      <content:encoded><![CDATA[
<p><img style="float: right;"
 src="http://rhodesmill.org/pyephem/_static/pyephem-logo-short.png"
 alt="PyEphem logo" />
I have decided to give my
<a href="http://rhodesmill.org/pyephem">PyEphem
astronomy library for Python</a>
a public source code repository,
an open forum for user questions,
and a bug tracker where my users
can see the progress of their bug reports out in the open
rather than having them scattered across our email inboxes.
To accomplish all of this,
I simply registered PyEphem with
<a href="http://launchpad.net/">Launchpad</a>,
a site built to host software projects
that is already used by several projects for which I have great respect.
</p>

<p>
Because users might become confused
now that PyEphem is spread across <i>three</i> web sites —
the home page is here at rhodesmill.org,
releases are posted over at the
<a href="http://www.python.org/pypi">Python Package Index</a>,
and, again, the development project is now hosted at Launchpad —
I have completely
<a href="http://rhodesmill.org/pyephem">redesigned the PyEphem home
page</a> with the goal of making the three-site distinction
clear, coherent, and easy to navigate.
The new home page and documentation
are generated by the wonderful
<a href="http://sphinx.pocoo.org/">Sphinx documentation engine</a>,
and I am still thrilled about how pretty my code samples look
(check out the one on the PyEphem home page!)
now that Sphinx is coloring them in with the renowned
<a href="http://pygments.org/">Pygments</a> system.
</p>

<p>
I have simultaneously released a new version of PyEphem
that includes the new Sphinx-based documentation,
along with several important fixes to the software itself.
From now on,
rather than cluttering my own blog
with every minor version of PyEphem that I might release,
fans of the software should visit its
<a href="https://launchpad.net/pyephem/+announcements">News and
announcements</a> page on Launchpad
and subscribe themselves to its
<a href="http://feeds.launchpad.net/pyephem/announcements.atom">Atom/RSS
feed</a>.
You will still see the project mentioned here
whenever a technical or scientific issue
becomes interesting enough for me to write about;
but the audience of astronomers and hobbyists
who just need to know when the next version is released
should not have to wade through my blog to do so!
</p>

<p>
My users have already begun transferring
their questions and problems to Lauchpad,
and I look forward to offering much greater accountability
through a fully public development process.
</p>]]></content:encoded>
    </item>
    <item>
      <title>Wordle</title>
      <link>http://rhodesmill.org/brandon/2008/wordle/</link>
      <pubDate>Fri, 13 Jun 2008 00:35:29 EDT</pubDate>
      <category><![CDATA[web notes]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/wordle/</guid>
      <description>Wordle</description>

      <content:encoded><![CDATA[
<p>
What fun! An application has been placed on the Web named <a href="http://www.wordle.net/">Wordle</a> which, given some paragraphs of text as input, produces very striking images by drawing the most important words from your document so that they are largest. The basic idea is a long-standing one on the Web, as exemplified in dozens of sites with <a href="http://www.flickr.com/photos/brandonrhodes/tags/">busy and ugly tag clouds</a> whose halfhearted attempt to create interest by varying their font size barely makes the idea worthwhile. But viewing Wordle, I am simply startled that word frequency analysis can produce something so beautiful! Here, as an example, someone has submitted the Constitution:
</p>
<a class="caption" href="http://www.wordle.net/gallery/Constitution_of_the_United_States_of_America" title="Wordle: Constitution of the United States of America"><img src="http://www.wordle.net/thumb/Constitution_of_the_United_States_of_America" style="padding:4px;border:1px solid #ddd" alt="Constitution Wordle" />United States Constitution</a>
<p>
One can spend several minutes just staring at the words so basic to our national life, and pondering the significance of their relative sizes! To make my own contribution to the burgeoning world of Wordle documents, I created a program to extract the memorial messages from the <a href="http://www.legacy.com/PostGazette/GB/GuestbookView.aspx?PersonId=98788905">Marshall Booth Guest Book</a> on <tt>legacy.com</tt>, and then submitted the result to Wordle. After several tries, and after experimenting with the color options, I came up with something I find quite satisfactory:
</p>
<a class="caption" href="http://www.wordle.net/gallery/Marshall_Booth_memorial" title="Wordle: Marshall Booth memorial"><img src="http://www.wordle.net/thumb/Marshall_Booth_memorial" style="padding:4px;border:1px solid #ddd" alt="Marhsall Booth Wordle" />Marshall Booth memorial</a>
<p>
I am sure that Wordle documents will look rather formulaic once everyone has used them to generate Christmas cards one or two years in a row. But they are without question of much greater visual interest than any other tag cloud I have ever seen, and are therefore a big step forward simply by making word frequency something worth staring at.
</p>
<p>
It would be fun to submit novels, or theological treatises, or each of the books of Paul, to Wordle and then see whether students of English literature or Biblical exegesis could identify the original document simply by which words appeared the most often. I think there would be interesting surprises! Could people tell apart the five acts of Hamlet?
</p>
]]></content:encoded>
    </item>
    <item>
      <title>My NOLA Plone Symposium talk, “the Zope 3 Component Architecture”</title>
      <link>http://rhodesmill.org/brandon/2008/nola-plone-symposium-talk/</link>
      <pubDate>Thu, 05 Jun 2008 23:44:02 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/nola-plone-symposium-talk/</guid>
      <description>My NOLA Plone Symposium talk, “the Zope 3 Component Architecture”</description>

      <content:encoded><![CDATA[
<p>
I have delivered my “Zope 3 Component Architecture” talk
to the <a href="http://plone.org/events/regional/nola08">2008 North American
Plone Symposium</a> meeting here in New Orleans.
I want to thank the folks at
<a href="http://enfoldsystems.com/">Enfold Systems</a>
both for hosting the Symposium, inviting me to speak,
and for generously making it possible for me to attend!
Here are my slides:
</p>

<div class="caption">
<a href="http://rhodesmill.org/brandon/static/2008/nola-zope3-talk.pdf">
<img src="http://rhodesmill.org/brandon/static/2008/nola-zope3-talk.jpg" alt="opening slide" /></a>
<a href="http://rhodesmill.org/brandon/static/2008/nola-zope3-talk.pdf"
 >Download slides as PDF</a>
</div>

<p>
They had asked me to attend so that I could present
the <a href="http://rhodesmill.org/brandon/adapters/">Using Grok
to Walk Like a Duck</a> talk that I gave at PyCon 2008
back in March.
They changed the title, I suppose, to better highlight
why it would be of interest to the Plone community;
but the change actually helped me to rethink the presentation.
I wound up using only the first half of my PyCon slides.
For the second half of the talk,
which at PyCon had consisted of a crazy sequence
of hints and tips about using adapters in your own applications,
I instead did a much more successful series of slides
about how adapters are actually used in Zope 3
to suit up objects for presentation on the web.
I think this made the idea more concrete,
and thus much easier to understand
for people seeing adapters for the first time.
</p>
<p>
The talk was well enough received
that I should perhaps think seriously about finding further opportunities
to share Zope 3 technologies with the Plone community.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>Name your home machines using Tomato</title>
      <link>http://rhodesmill.org/brandon/2008/tomato-reverse-dns/</link>
      <pubDate>Wed, 16 Apr 2008 22:38:25 EDT</pubDate>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/tomato-reverse-dns/</guid>
      <description>Name your home machines using Tomato</description>

      <content:encoded><![CDATA[
<blockquote><b>Update (February 2009):</b> thanks to an email I have just received asking how the mechanism described below is better than just assigning host names in Tomato "normally", I have discovered that this whole post was rather pointless. There is <i>already</i> a way to assign host names in Tomato: click on "Basic" then on "Static DHCP", and enter your IP addresses and corresponding host names there.  I had thought, from its name, that the "Static DHCP" entries were only relevant when machines were booting (when they use DHCP to ask for their host name), but I was wrong: the host names are also returned by the Tomato DNS server for both forward and reverse DNS requests. So while this post is still useful reading if you want to understand better why you might want to use host names for your home machines, the actual mechanism described below is much more trouble than is actually necessary.
</blockquote>

<iframe src="http://rcm.amazon.com/e/cm?t=letsdisthemat-20&o=1&p=8&l=as1&asins=B000BTL0OA&fc1=000000&IS2=1&lt1=_blank&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;float:right;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

<p>
I am enjoying my first weeks of using the <a href="http://www.polarcloud.com/tomato">Tomato Firmware</a>. I purchased a <a href="http://www.amazon.com/gp/product/B000BTL0OA?ie=UTF8&tag=letsdisthemat-20&linkCode=as2&camp=1789&creative=9325&creativeASIN=B000BTL0OA">Linksys WRT54GL wireless router</a> because of its admirable support for third-party firmware like Tomato, which replaces the traditional Linksys setup screens with an alterative system with many more configuration options. I can also connect directly to Tomato over SSH and use it as a very small Linux system! This opens endless possibilities for writing fancy firewall rules and running small embedded applications right at the border of my home network.
</p>

<p>
The Tomato firmware uses a small DNS server named <b><a href="http://www.thekelleys.org.uk/dnsmasq/doc.html">dnsmasq</a></b> to answer the steady stream of domain name requests from my home computers. It converts domain names that I type, like <tt>rhodesmill.org</tt> or <tt>google.com</tt>, into the low-level IP addresses with which computers identify each other.
</p>

<p>
But I also like using hostnames for the machines sitting right in my home, even though they do not have “real names” out on the Internet. I recommend placing local hostnames inside of a top-level domain that is local to your own network. Choose a suffix that differs from all of the top-level domains that exist out on the Internet — avoid <tt>.com</tt>, <tt>.net</tt>, or <tt>.uk</tt>, for example, in favor of something like <tt>.home</tt> or <tt>.myhouse</tt> instead. How, I wondered, could I add extra host names to <b>dnsmasq</b>?
</p>

<p><a href="http://rhodesmill.org/brandon/2008/tomato-reverse-dns/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>How To Produce A Linux Screencast</title>
      <link>http://rhodesmill.org/brandon/2008/how-to-produce-a-linux-screencast/</link>
      <pubDate>Wed, 27 Feb 2008 00:50:33 EST</pubDate>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/how-to-produce-a-linux-screencast/</guid>
      <description>How To Produce A Linux Screencast</description>

      <content:encoded><![CDATA[
<p>
Learning how to create Linux screencasts has been the most frustrating technical challenge that I have tackled for a very long time. I should have been worried when a search for “Linux video editing” returned, as its top hit, a <a href="http://www.robfisher.net/video/">bare and completely unstyled web page from 2002</a> which concludes that “video editing on Linux hasn't really arrived yet.”
</p>

<p>
My efforts were, in the end, successful, and you can see the result — my first two screencasts — <a href="http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/">in my previous blog entry</a>, which I posted earlier this week.
</p>

<p>
In the hope that my toil can benefit others, let me outline the details of the process that I have worked out for creating, editing, and posting Linux screencasts. For the impatient, here are the three most important things I learned:
</p>

<ul>

<li>Linux tools have great difficulty keeping audio and video from gradually going out of sync over several minutes. To avoid problems, always run <a href="http://recordmydesktop.iovar.org/">recordmydesktop</a> with its “on-the-fly encoding” option, and never let “ffmpeg” anywhere near your audio! This not only means that you have to use “mencoder” instead when converting between video formats, but even within mencoder you must avoid the “lavc” audio module, since its code seems to have the same problems.

<li>Do not attempt to directly edit the resulting Ogg/Theora video! Instead, convert first to the Digial Video (DV) format, and perform your editing there. Be prepared for the fact that DV files are enormous, and that DV pixels are not square.

<li>Finally, convert to something like AVI for submission to <a href="http://video.google.com/">Google Video</a>. Avoid submitting a raw Ogg/Theora file, since even though Google can decode it, their decoders will waste valuable screen space by placing an empty border around the result.

</ul>

<p>
For those interested in more details, I have more to share. Keep reading!
</p>

<p><a href="http://rhodesmill.org/brandon/2008/how-to-produce-a-linux-screencast/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Presentations on Buildout and KSS</title>
      <link>http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/</link>
      <pubDate>Sat, 23 Feb 2008 23:29:13 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2008/presentations-on-buildout-and-kss/</guid>
      <description>Presentations on Buildout and KSS</description>

      <content:encoded><![CDATA[
<p>
After several frustrating weeks learning how to create, edit, and publish a screencast under Linux (about which I will write a separate post), I have now published screencasts of both presentations that I gave at the PyAtl meetup in January. I opened with a talk about the <tt>import</tt> statement, and where Python packages lived before egg files were invented:
</p>

<div class="caption"><a href="http://video.google.com/videoplay?docid=5996823626349389448"><b>Python Before Eggs</b></a>

<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=5996823626349389448&hl=en" flashvars=""> </embed>

</div>

<p>
The audience seemed most interested in the last section of the talk, where I discuss three techiques for debugging problems with Python's <tt>import</tt> statement; fast-forward to around 3:00 if you want to catch that part by itself.
</p>

<p>
Next, Jeremy Jones spoke about eggs, Noah Gift introduced virtualenv, and, finally, I got back up to talk about buildout. This was probably <b>my own favorite</b> among the recent presentations I have given, and it's the one I've worked hardest to adapt to a competent screencast:
</p>

<div class="caption"><a href="http://video.google.com/videoplay?docid=3428163188647461098&hl=en"><b>Introduction to Buildout</b></a>

<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=3428163188647461098&hl=en" flashvars=""> </embed>

</div>

<p>
I have prepared a supplement to the above screencast that <a href="/brandon/buildout/">gives additional hints and tips about using buildout</a>, as well as a link to the source code of the module that I use as my example.
</p>

<p>
Finally, if you're ready to see something a little less polished — something that instead of being a screencast is actually a film of me talking in front of a live audience, and gesturing and jumping around — I filled a vacant lightning-talk slot at our February PyAtl meeting with an impromptu introduction to <a href="http://kssproject.org/">Kinetic Style Sheets</a> (KSS), using an example application that was still sitting on my laptop after at a Georgia Tech developer's luncheon earlier that week:
</p>

<div class="caption"><a href="http://video.google.com/videoplay?docid=3829442611478268688"><b>Introduction to KSS</b></a>

<embed style="width:400px; height:326px;" id="VideoPlayback" type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docId=3829442611478268688&hl=en" flashvars=""> </embed>

</div>

<p>
Now I can finally turn my attention to preparing for my upcoming talk at PyCon 2008 in Chicago! I will be talking about the basic “adapter” design pattern, and how a framework like Zope 3 can facilitate its use. Stay tuned for more information!
</p>
]]></content:encoded>
    </item>
    <item>
      <title>New PyEphem release: 3.7.2.2</title>
      <link>http://rhodesmill.org/brandon/2007/new-pyephem-release-3722/</link>
      <pubDate>Tue, 11 Dec 2007 09:42:07 EST</pubDate>
      <category><![CDATA[pyephem]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2007/new-pyephem-release-3722/</guid>
      <description>New PyEphem release: 3.7.2.2</description>

      <content:encoded><![CDATA[
<p>
On Sunday afternoon I released a new version of <a href="http://rhodesmill.org/pyephem/">PyEphem</a>, which is available from the Python Package Index as <a href="http://pypi.python.org/pypi/pyephem/3.7.2.2">version 3.7.2.2</a>!  I want to thank the users who spurred its development&nbsp;— in particular, <a href="http://asemonline.org/archives/category/members-pages/john-ducheks-pages/">John Duchek</a> of the Astronomical Society of Eastern Missouri encouraged me both to create the new moon-phase functions, and, as I <a href="http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/">announced</a> several weeks ago, to finally make PyEphem available in binary form for Windows.  Thanks, John!
</p>
<p>
PyEphem now also includes a small database of world cities, so that people living near one can simply call <tt>ephem.city('Boston')</tt> to get their longitude, latitude, and elevation, rather than having to look up the numbers themselves.
</p>
]]></content:encoded>
    </item>
    <item>
      <title>A database symbol for GraphViz</title>
      <link>http://rhodesmill.org/brandon/2007/a-database-symbol-for-graphviz/</link>
      <pubDate>Fri, 23 Nov 2007 10:12:37 EST</pubDate>
      <category><![CDATA[web notes]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2007/a-database-symbol-for-graphviz/</guid>
      <description>A database symbol for GraphViz</description>

      <content:encoded><![CDATA[
<blockquote>
<b>Download the source for my GraphViz database symbol featured in this article:</b> <a href="http://rhodesmill.org/brandon/static/2007-11/DatabaseShape.ps">DatabaseShape.ps</a>
</blockquote>

<p>
I have started using the <a href="http://www.graphviz.org/">GraphViz</a> application, which accepts a list of nodes and arrows, and figures out how to attractively arrange them in a diagram. For example, you can very nearly produce this output:
</p>

<img src="http://rhodesmill.org/brandon/static/2007-11/graphviz-with-database"
     />

<p>
by supplying this rather modest input file to GraphViz (most of whose length comes from my wanting particular colors)::
</p>



<div class="pygments_murphy"><pre> <span class="nt">digraph</span> <span class="nt">Application</span> <span class="p">{</span>
    <span class="nt">rankdir</span><span class="o">=</span><span class="nt">LR</span><span class="o">;</span>
    <span class="nt">node</span> <span class="o">[</span><span class="nt">shape</span><span class="o">=</span><span class="nt">box</span><span class="o">,</span><span class="nt">style</span><span class="o">=</span><span class="nt">filled</span><span class="o">,</span><span class="nt">fillcolor</span><span class="o">=</span><span class="s2">&quot;#C0D0C0&quot;</span><span class="o">];</span>
    <span class="nt">subgraph</span> <span class="nt">clusterClient</span> <span class="p">{</span>
       <span class="nt">label</span><span class="o">=</span><span class="s2">&quot;Client&quot;</span><span class="o">;</span> <span class="nt">style</span><span class="o">=</span><span class="nt">filled</span><span class="o">;</span> <span class="nt">bgcolor</span><span class="o">=</span><span class="s2">&quot;#D0C0A0&quot;</span><span class="o">;</span>
       <span class="s2">&quot;Browser&quot;</span><span class="o">;</span>
    <span class="p">}</span><span class="o">;</span>
    <span class="nt">subgraph</span> <span class="nt">clusterServer</span> <span class="p">{</span>
       <span class="nt">label</span><span class="o">=</span><span class="s2">&quot;Server&quot;</span><span class="o">;</span> <span class="nt">style</span><span class="o">=</span><span class="nt">filled</span><span class="o">;</span> <span class="nt">bgcolor</span><span class="o">=</span><span class="s2">&quot;#D0C0A0&quot;</span><span class="o">;</span>
       <span class="s2">&quot;App&quot;</span><span class="o">;</span>
       <span class="s2">&quot;Database&quot;</span> <span class="o">[</span><span class="nt">shape</span><span class="o">=</span><span class="nt">DatabaseShape</span><span class="o">,</span><span class="nt">peripheries</span><span class="o">=</span><span class="nt">0</span><span class="o">];</span>
    <span class="p">}</span><span class="o">;</span>
    <span class="s2">&quot;Browser&quot;</span> <span class="nt">-</span><span class="o">&gt;</span> <span class="s2">&quot;App&quot;</span> <span class="o">[</span><span class="nt">label</span><span class="o">=</span><span class="s2">&quot;HTTP&quot;</span><span class="o">];</span>
    <span class="s2">&quot;App&quot;</span> <span class="nt">-</span><span class="o">&gt;</span> <span class="s2">&quot;Database&quot;</span> <span class="o">[</span><span class="nt">label</span><span class="o">=</span><span class="s2">&quot;SQL&quot;</span><span class="o">];</span>
 <span class="p">}</span>
</pre></div>




<p>
I used the words “very nearly” because, in fact, GraphViz only knows how to draw simple shapes like rectangles, and is ignorant of the standard cylinder-shaped database symbol that I have used here by asking for a <tt>DatabaseShape</tt>. Submitting the above code to GraphViz will, normally, produce three nodes that are all rectangles. To teach it about the database shape, I had to write some PostScript.
</p>

<p><a href="http://rhodesmill.org/brandon/2007/a-database-symbol-for-graphviz/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>My November Grok Presentation</title>
      <link>http://rhodesmill.org/brandon/2007/my-november-grok-presentation/</link>
      <pubDate>Fri, 09 Nov 2007 19:06:24 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[grok]]></category>
      <category><![CDATA[zope]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2007/my-november-grok-presentation/</guid>
      <description>My November Grok Presentation</description>

      <content:encoded><![CDATA[
<p>
In this post, I provide the slides and examples from a recent talk that I gave to some fellow software developers at Georgia Tech. Many of them were not familiar with web frameworks, and I wanted to introduce them to two common concepts: the idea of “convention over configuration,” and the practice of passing inert data structures to a page template rather than letting it access live objects directly.
</p>
<p>
But because I am also really enjoying my work with the new Python web framework <a href="http://grok.zope.org/">Grok</a>, I decided to make it the centerpiece of my presentation<p><a href="http://rhodesmill.org/brandon/2007/my-november-grok-presentation/">Read more</a></p>]]></content:encoded>
    </item>
    <item>
      <title>PyEphem available for Windows!</title>
      <link>http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/</link>
      <pubDate>Fri, 09 Nov 2007 11:10:25 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[pyephem]]></category>
      <category><![CDATA[computing]]></category>
      <guid>http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/</guid>
      <description>PyEphem available for Windows!</description>

      <content:encoded><![CDATA[
<p>
Over the years I have received many requests from frustrated Windows users, asking for a Windows-native version of my <a href="http://rhodesmill.org/pyephem/">PyEphem</a> astronomy library for Python. For most Windows users, an attempt to build the extension ends abruptly with the terrible and famous message:
</p>

<blockquote><tt>error: Python was built with version 7.1 of Visual Studio, and extensions need to be built with the same version of the compiler, but it isn't installed.</tt></blockquote>

<p>
And, as I myself do not have Visual Studio on the small Windows machine that I deign to own for the sake of my photo printer, I have never been able to offer my users much help. But earlier this year, a helpful PyEphem user named Jeff Kowalczyk emailed me a link to Philip von Weitershausen's post <a href="http://www.z3lab.org/sections/blogs/philipp-weitershausen/2007_07_26_cheap-binary-windows">“Cheap binary Windows eggs”</a>, which describes a method for building Python extensions using a freely available compiler.
</p>

<p><a href="http://rhodesmill.org/brandon/2007/pyephem-available-for-windows/">Read more</a></p>]]></content:encoded>
    </item>
  </channel>
</rss>

