<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[William John Bert]]></title>
  <link href="http://williamjohnbert.com/atom.xml" rel="self"/>
  <link href="http://williamjohnbert.com/"/>
  <updated>2013-05-16T19:15:57-04:00</updated>
  <id>http://williamjohnbert.com/</id>
  <author>
    <name><![CDATA[William John Bert]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Juxtaposition]]></title>
    <link href="http://williamjohnbert.com/2013/05/juxtaposition/"/>
    <updated>2013-05-16T19:02:00-04:00</updated>
    <id>http://williamjohnbert.com/2013/05/juxtaposition</id>
    <content type="html"><![CDATA[<p>A few days ago, I happened by chance to read these two articles one after the other:</p>

<ul>
<li><p><a href="http://tomayko.com/writings/unicorn-is-unix">I like Unicorn because it&#8217;s Unix</a></p></li>
<li><p><a href="http://highscalability.com/blog/2013/5/13/the-secret-to-10-million-concurrent-connections-the-kernel-i.html">The Secret To 10 Million Concurrent Connections -The Kernel Is The Problem, Not The Solution</a></p></li>
</ul>


<p>The first is about how good Unix is at scaling the scheduling and distribution
of work among processes. The second is about how Unix is the problem when it
comes to the scheduling and distribution of work at scale.</p>

<p>The question, of course, is &#8220;What scale?&#8221;. Like the difference between a cure and a
poison is sometimes the dosage.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Zero to Node, Again]]></title>
    <link href="http://williamjohnbert.com/2013/01/reprise-of-zero-to-node/"/>
    <updated>2013-01-17T08:09:00-05:00</updated>
    <id>http://williamjohnbert.com/2013/01/reprise-of-zero-to-node</id>
    <content type="html"><![CDATA[<p>At <a href="http://www.meetup.com/node-dc/events/98796672/">NodeDC&#8217;s January meetup</a>,
I&#8217;ll be giving a reprise of my
<a href="http://sandinmyjoints.github.com/zero-to-node/">Zero to Node</a> talk, about
designing, coding, and launching my first web service using Node.js. The meetup
is Wednesday, Jan 23, at Stetson&#8217;s (1610 U St NW). Hope to see you there!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Review of Requests 1.0]]></title>
    <link href="http://williamjohnbert.com/2013/01/review-of-requests-1-dot-0/"/>
    <updated>2013-01-14T17:22:00-05:00</updated>
    <id>http://williamjohnbert.com/2013/01/review-of-requests-1-dot-0</id>
    <content type="html"><![CDATA[<p><em>Author&#8217;s note: This piece was <a href="http://thediagram.com/12_6/rev_reitz.html">originally published</a> in the excellent literary journal
 <a href="http://thediagram.com/">DIAGRAM</a>, Issue 12.6. I&#8217;m
 re-publishing here for formatting reasons.</em></p>

<p>Identification with another is addictive: some of my life&#8217;s most profound, memorable experiences have come when something bridged the gap between me and another human. Because I&#8217;m a reader, this can occur across the distance of space and time. It&#8217;s happened with minor Chekov characters, and at the end of Kate Mansfield stories. It happens again and again with Norman Rush and George Saunders. The author has pushed a character through the page and connected with me on a deep level: identification.</p>


<p>Identification happens with computer programming, too.</p>


<p>I say this as a reader, writer, and programmer: I experience identification when reading and programming, and I strive to create it when writing and programming.</p>


<p>Though they deal with the messiness of reality differently, several techniques common to both disciplines enable them to achieve this mental intimacy: navigating complexity; avoiding pitfalls that inhibit communication; choosing structure wisely; harnessing expressive power; and inhabiting other minds. The Requests library, a work of computer programming by Kenneth Reitz, illustrates this.</p>




<!-- more -->




<h2 id="navigating-complexity">Navigating Complexity</h2>


<p>As humans, we&#8217;ve evolved to unconsciously filter the staggering possibilities available to us at each moment. To manage that complexity, we have rules. Humans come with some built in rules (eat when hungry), and easily learn more (don&#8217;t touch hot stoves; don&#8217;t lie, especially to those you love). When I&#8217;m writing, my stories might examine how these rules come into conflict with each other: a government doctor is ordered to a remote, neglected village, and comes to value its people more than his duty to the government.</p>


<p>Computers don&#8217;t come with built-in rules. When I&#8217;m programming, if I make a mistake, the computer marches into it head-on. Computers do precisely and only what you tell them (frustrations with Microsoft Word notwithstanding), and because there are a staggering number of things they can do, programmers constantly battle complexity, sometimes spelling out in excruciating detail exactly what it is we want them to do. Programming is an effort to build up sets of rules that direct the computer to do something helpful.</p>


<p>Staggering possibilities managed by rules: that&#8217;s also a description of natural language. The difference is that natural language has been with our species for a long time. Our brains have evolved pockets that just do languagey stuff. When I write, I benefit from this history.</p>


<p>When it comes to programming, we&#8217;re just getting started. Our brains need help.</p>


<h2 id="avoiding-pitfalls">Avoiding Pitfalls</h2>


<p>Misunderstandings and garbled messages kill identification before it can begin. Grammar, punctuation, and even typing mistakes fatally divert attention from what the writer is trying to say. Layout and space matter, too: linebreaks are essential to poetry, and visual flow to longer narrative. Communication can happen without them, but immersion comes more easily when nothing gets in the way.</p>


<p>The stuff that programmers write, called code, can likewise be correct or incorrect, beautiful or ugly. Requests is written in a programming language called Python <sup><a href="#fn1" class="footnoteRef" id="fnref1">1</a></sup> that&#8217;s known for being easy to read. Unusually for programming languages, Python requires a certain amount of space between bits of code, and its style guide encourages the use of even more space than required. Built-in elements of the language that programmers cannot change have clear and consistent names that further aid comprehension&#8211;not the case in every language. In Requests, Reitz embraces Python&#8217;s style.</p>


<h2 id="structure">Structure</h2>


<p>Options for structure and sequence abound: writers order narrative chronologically, <em>in media res</em>, or in more complex ways. Chapters can be short, long, or omitted. From Volumes and Parts to paragraphs and sentences, structure matters.</p>


<p>Requests&#8217;s dual structure is typical of programming libraries: the code itself, and a document that explains how to use the code. Within the code, there are structures that are roughly analogous in scale to sentences, paragraphs, and chapters, while the documentation proceeds narratively, starting with easy matters and advancing to difficult material.</p>


<p>This bundle of code plus documentation is known as an <em>application programming interface</em>, or <em>API</em>.</p>


<p>APIs are what make it possible to post your Instagram photos to your Facebook timeline, check-in on Foursquare from your iPhone, book a flight on United from Kayak, etc. Without APIs, without a way to share units of functionality with each other, each programmer or programming team would be on its own. Everything would take much, much longer; each programmer would have to reinvent the wheel.</p>


<p>Here&#8217;s an interesting bit of jargon: programmers say that somebody is &quot;exposing an API.&quot; It&#8217;s an act of confidence, but also vulnerability.</p>


<h2 id="expressive-power">Expressive Power</h2>


<p>The number of books to read is huge. Why would you choose one over another? Why might you read a literary novel over, say, a detective novel, or an author you love over one you don&#8217;t? One reason might be that while a thoughtful reader can eke meaning from even the flimsiest of genre novels (sometimes with great satisfaction and enjoyment), we tend to find more significance in novels and poetry that pack their sentences and stanzas with meaning, allusion, emotion, and impact. We might call this <em>expressive power</em>.</p>


<p>The collection of programming libraries is also huge. To show how they vary in expressive power, I need to introduce a bit of programming code:</p>


<pre><code>&gt;&gt;&gt; import urllib2
&gt;&gt;&gt; req = urllib2.Request(&#39;http://www.goodreads.com&#39;)
&gt;&gt;&gt; response = urllib2.urlopen(req)
&gt;&gt;&gt; response.read()</code></pre>


<p>This snippet <sup><a href="#fn2" class="footnoteRef" id="fnref2">2</a></sup> is the standard way to retrieve a webpage (specifically, Goodreads&#8217; homepage) using a Python library called urllib2. Requests does the same thing this way:</p>


<pre><code>&gt;&gt;&gt; import requests
&gt;&gt;&gt; response = requests.get(&quot;http://www.goodreads.com&quot;)</code></pre>


<p>Requests&#8217; code is two lines instead of four. That might not seem like a big difference from urllib2, but note it, and bear with me just a bit longer. Both these snippets store the webpage they&#8217;ve retrieved in a variable called <code>response</code>. When I&#8217;m programming, I&#8217;ll want to do something useful with <code>response</code>: save it to a file, show it to a user, parse it to see what books are popular. If I ask Python to describe the <code>response</code> returned by urllib2, I get something like <sup><a href="#fn3" class="footnoteRef" id="fnref3">3</a></sup> this:</p>


<pre><code>&gt;&gt;&gt; response
&lt;addinfourl at 4338521656 whose fp = &lt;socket._fileobject object at 0x10297ce50&gt;&gt;</code></pre>


<p>The <code>response</code> that Requests gives me, on the other hand, looks like:</p>


<pre><code>&gt;&gt;&gt; response
&lt;Response [200]&gt;</code></pre>


<p>Again, Requests is smaller, and it turns out its two lines of code give me something much more useable than urllib2. <code>Response [200]</code> is meaningful; one of the first things every web programmer learns is that, in HTTP, the language of the internet, 200 means, simply, &quot;OK&quot;. Requests lets me know my code succeeded.</p>


<p>The thing that urllib2 gave me, <code>&lt;addinfourl at 4338521656 whose fp = &lt;socket._fileobject object at 0x10297ce50&gt;&gt;</code>, is clear as mud. I can make some guesses about it, but to really understand it, I&#8217;d have to spend time rooting around in documentation. I just wanted to get a web page.</p>


<p>This difference between the two libraries&#8211;their expressive power&#8211;plays out over and over with the rest of their functionality. Fetching a webpage is just scratching the surface, and the efficiency penalty imposed by the gap in expressive power compounds as you do more complicated, hence interesting, things.</p>


<p><code>requests.get</code> is Hemingway, or Strunk and White. Declarative. Terse. Say what you mean as plainly as possible. Behind the scenes, its two lines are doing more work than they seem, the way a good writer&#8217;s sentences accomplish multiple things at once: moving plot forward, imparting character, setting tone, painting a scene.</p>


<p>urllib2&#8217;s jumble is verbose jargon, like legalese: heretofore, whereas, the party of the first part. Its API is a menagerie of abstractions with names such as <code>OpenerDirector</code> and <code>HTTPPasswordMgrWithDefaultRealm</code> <sup><a href="#fn4" class="footnoteRef" id="fnref4">4</a></sup> that must be looked up to be understood, and are often underwhelming in their capabilities.</p>


<p>Greater expressive power matches more closely the workings of my mind, where thought flows in a continuous stream. It eases the transit of thought across the boundary between internal and external. With a good novel or a good API, the pace of comprehension accelerates, syncing with my inner monologue, setting the stage for identification.</p>


<h2 id="dealing-with-reality">Dealing with Reality</h2>


<p>Programmers strive to be subtext-free. The code is tricky enough. Miss a comma or closing brace, and spend hours trying to find your mistake. The computer forgives nothing. Good programmers deal with this by making reality as clean as possible.</p>


<p>For example, within an app that tracks the books you&#8217;ve read, you&#8217;ve either read a book or not, or perhaps you&#8217;re currently reading it. There&#8217;s no &quot;I read a third of it, then put it down for a while,&quot; or &quot;I stole it from a friend and almost finished it but now Vanessa&#8217;s borrowing it, I think.&quot; A system that tried to encode every possible state of any person&#8217;s relationship to their books would never be finished. This is how programmers deal with reality: by cleaning it up.</p>


<p>What I said above about Requests being like Hemingway isn&#8217;t entirely accurate: his clean prose belies a messy reality that is always present; meaning is often unstated. Likewise, when Austen begins, &quot;It is a truth universally acknowledged, that a single man in possession of a good fortune must be in want of a wife,&quot; she is not simply stating a universal truth that she has identified. The sentence comes with subtext: the truth is universal in the minds of some people, but not others, an oxymoron, emphasized by the sentence&#8217;s lack of an active subject. There is also commentary on the relative power of men and women in her time. Here is a richness that demands and rewards repeated reading, offering interpretations as varied as the number of people who read it.</p>


<p>When I write a story, I thrive on subtext, on creating shades of meaning and multiple readings. Ambiguity and elision and irony are my techniques for dealing with the messiness of reality. But when I type:</p>


<p>I aim to banish ambiguity. I name my variables clearly, according to what data they hold. I structure the code to indicate the flow of execution. Requests helps me here: the last two lines that create a new session correspond to how I intuitively think of creating a session. The equivalent in urllib2 would be messier and more verbose.</p>


<p>I want future readers&#8211;myself and others&#8211;to understand exactly what that code is doing. Future readers are as sure a thing with code as with literature. <sup><a href="#fn5" class="footnoteRef" id="fnref5">5</a></sup> I&#8217;ll be re-reading my code in six months when I add a new feature in another part of the program and it suddenly breaks something here and I have to figure out how they are connected.</p>


<h2 id="what-its-like-to-work-with-a-bad-api">What it&#8217;s like to work with a bad API</h2>


<p>You get annoyed. You say of whoever created it, What were they thinking? You feel bogged down. Nothing comes easy. You have to keep taking breaks. You feel forgetful. You wonder if it&#8217;s your fault, if you&#8217;re missing something everyone else sees. You get a headache. You curse. You may bite or click your nails, or maniacally tap your foot. You want to be doing something else.</p>


<h2 id="grok">Grok</h2>


<p>Programmers put so much value on understanding something with intimate and exhaustive knowledge that traditional programmer slang has its own word for it: <em>grok</em> <sup><a href="#fn6" class="footnoteRef" id="fnref6">6</a></sup>. It&#8217;s from the language of the Martians in Robert Heinlein&#8217;s <em>Stranger in a Strange Land</em>, in which it means literally &quot;to drink&quot; and metaphorically &quot;to be one with.&quot;</p>


<p>In a novel or poem, you&#8217;ve been led to understanding and impression by a succession of images and literary devices and experiences and revelations. In programming, you are led to understanding by encountering problems, ways of thinking about those problems, organizing them, and finally grokking them well enough to devise a solution.</p>


<p>Reitz groks Python and the internet well, better than I ever will, as Austen grokked relationships and power dynamics better than I ever will. Through exposure to their works, I benefit from their experience of the world. In my own work of programming and writing, I strive to match the understanding that they achieved.</p>


<h2 id="theory-of-mind">Theory of Mind</h2>


<p>Writers and programmers inhabit other minds.</p>


<p>Writers inhabit the minds of their characters and of readers of their work.</p>


<p>Programmers inhabit the minds of users. In Reitz&#8217;s case, these are other programmers (as opposed to, say, the programmers of Google Chrome, which is used by non-programmers). Programmers might also be said to inhabit mind of the computer itself.</p>


<p>This habitation of minds outside my own is part of what draws me to both these pursuits. It is a challenge. It broadens my world. Thinking of others, as others think, anticipating their needs and wants and questions, helps me transcend myself and gain perspective. It&#8217;s invigorating!</p>


<h2 id="what-its-like-to-work-with-a-great-api">What it&#8217;s like to work with a great API</h2>


<p>It&#8217;s more than if Lori Moore or John Ashbery published a notebook of exercises and prompts; it&#8217;s as if they published part of their brain, so that you too can run your thoughts through it, and have them upgraded. As you figure out how to do what you set out to do, you realize other things that would also be cool to do, and you find that the API has ways to do them, too! You think the way someone else thought, and understand their thinking on a deep level. You have a sense that we are all in this together. We&#8217;re not so different.</p>


<h2 id="identification">Identification</h2>


<p>Identification is addictive. I seek it out, and I have an urge to spark it in others. The difficulties of navigating complexity while avoid communication pitfalls, of harnessing expressive power, and of inhabiting other minds make it difficult to find and create. If I can ever achieve it in my own work&#8211;whether writing or programming&#8211;it will be through studying&#8211;grokking&#8211;works like <em>Pride and Prejudice</em>, and <em>Requests</em>.</p>


<h2 id="footnotes">Footnotes</h2>


<div class="footnotes">
<hr />
<ol>
<li id="fn1"><p>As in Monty Python, not the snake.<a href="#fnref1">^</a></p></li>
<li id="fn2"><p>What does this all mean?</p>
<p>Three greater-than signs (`&gt;&gt;&gt;`) is called a prompt, as in Python is prompting me to give it something to do. The rest of the line after it is what I type. So this:</p>
<pre><code>&gt;&gt;&gt; requests.get(&quot;www.goodreads.com&quot;)
&lt;Result [200]&gt;</code></pre>
<p>is really this little dialog:</p>
<p>Python: I&#8217;m ready! Give me something to do.</p>
<p>Me: Retrieve this webpage, www.goodreads.com, for me.</p>
<p>Python: OK, did that, here&#8217;s what I got.</p>
<p>Writing out prompt/command/result is a common way for programmers to give each other examples: this is what I did; this is what I got; if you do the same, you should get the same result.<a href="#fnref2">^</a></p></li>
<li id="fn3"><p>I say &quot;something like&quot; because the exact details will vary on different computers and at different times of execution.<a href="#fnref3">^</a></p></li>
<li id="fn4"><p>These names are strikingly similar to the kinds of names that are common in another programming language you may have heard of, Java. Why that is is a whole other discussion that gets into very different philosophies about programming languages.<a href="#fnref4">^</a></p></li>
<li id="fn5"><p>An experience I&#8217;ve noticed that&#8217;s common to writers and programmers is looking back at their own work and not recognizing it, with reactions ranging from admiration (How did I do that?) to disgust (What was I thinking?).<a href="#fnref5">^</a></p></li>
<li id="fn6"><p>This definition is taken from The Jargon File, a reference of programming jargon and lore: <a href="http://www.catb.org/jargon/html/G/grok.html">http://www.catb.org/jargon/html/G/grok.html</a><a href="#fnref6">^</a></p></li>
</ol>
</div>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Update and Rescheduling]]></title>
    <link href="http://williamjohnbert.com/2012/11/update-and-rescheduling/"/>
    <updated>2012-11-04T22:23:00-05:00</updated>
    <id>http://williamjohnbert.com/2012/11/update-and-rescheduling</id>
    <content type="html"><![CDATA[<p>Hurricane Sandy rescheduled
  <a href="http://www.meetup.com/Nova-Node/events/84918342/"><strong>Zero to Node</strong></a>, my talk
  about writing and deploying a node.js app in production, to Wednesday, November
  7. Hope to see you there!</p>

<p>  (Update: <a href="http://sandinmyjoints.github.com/zero-to-node">here are the slides from my talk</a>.)</p>

<p>  In other news, I&#8217;ve redone this site using <a href="http://octopress.org/">Octopress</a>
  with the <a href="https://github.com/roberto/oct2-orange">oct2-orange theme</a>. Sweet!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[A Case Study of Node.js in Production]]></title>
    <link href="http://williamjohnbert.com/2012/10/a-case-study-of-node-js-in-production/"/>
    <updated>2012-10-01T17:27:53-04:00</updated>
    <id>http://williamjohnbert.com/2012/10/a-case-study-of-node-js-in-production</id>
    <content type="html"><![CDATA[<p>I&#8217;m giving a talk about my experience <a href="http://www.meetup.com/Nova-Node/events/84918342/">developing and deploying a Node.js web
service in production</a> at the
next Nova-Node meetup, October 30 at 6:30 p.m. Below is the writeup. If it
sounds interesting to you, come by!</p>

<blockquote><p>SpanishDict recently deployed a new text-to-speech service powered by
  Node. This service can generate audio files on the fly for arbitrary Spanish
  and English texts with rapid response times. The presentation will walk
  through the design, development, testing, monitoring, and deployment process
  for the new application. We will cover topics like how to structure an Express
  app, testing and debugging, learning to think in streams and pipes, writing a
  Chef cookbook to deploy to AWS, and monitoring the application for high
  performance. The lead engineer on the project, William Bert, will also talk
  about his experiences transitioning from a Python background to Node and some
  of the key insights he had about writing in Node while developing the
  application.</p></blockquote>

<p>Update: <a href="http://sandinmyjoints.github.com/zero-to-node">here are the slides from the talk</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[(Relatively) quick and easy Gensim example code]]></title>
    <link href="http://williamjohnbert.com/2012/05/relatively-quick-and-easy-gensim-example-code/"/>
    <updated>2012-05-04T04:12:23-04:00</updated>
    <id>http://williamjohnbert.com/2012/05/relatively-quick-and-easy-gensim-example-code</id>
    <content type="html"><![CDATA[<p>Here&#8217;s some sample code that shows the basic steps necessary to use gensim to create a corpus, train models (log entropy and latent semantic analysis), and perform semantic similarity comparisons and queries.</p>

<p><a href="http://radimrehurek.com/gensim/">gensim</a> has an excellent tutorial, and this does not replace reading and understanding it. Nonetheless, this may be helpful for those interested in doing some quick experimentation and getting their hands dirty fast. It takes you from training corpus to index and queries in about 100 lines of code, much of which is documentation.</p>

<p>Note that this code <strong>will not work out of the box</strong>. To train the models, you need to provide your own background corpus (a collection of documents, where a document can range from one sentence up to multiple pages of text). Choosing a good corpus is an art; generally, you want tens of thousands of documents that are representative of your problem domain. Like the gensim tutorial, this code also shows how to build a corpus from Wikipedia for experimentation, though note that doing so require a lot of computing time. You could potentially <a href="http://williamjohnbert.com/2012/03/how-to-install-accelerated-blas-into-a-python-virtualenv/">save hours by installing accelerated BLAS on your system</a>.</p>

<!-- more -->




<figure class='code'><figcaption><span>Gensim sample code  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
<span class='line-number'>103</span>
<span class='line-number'>104</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">import</span> <span class="nn">logging</span><span class="o">,</span> <span class="nn">sys</span><span class="o">,</span> <span class="nn">pprint</span>
</span><span class='line'>
</span><span class='line'><span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">stream</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c">### Generating a training/background corpus from your own source of documents</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">gensim.corpora</span> <span class="kn">import</span> <span class="n">TextCorpus</span><span class="p">,</span> <span class="n">MmCorpus</span><span class="p">,</span> <span class="n">Dictionary</span>
</span><span class='line'>
</span><span class='line'><span class="c"># gensim docs: &quot;Provide a filename or a file-like object as input and TextCorpus will be initialized with a</span>
</span><span class='line'><span class="c"># dictionary in `self.dictionary`and will support the `iter` corpus method. For other kinds of corpora, you only</span>
</span><span class='line'><span class="c"># need to override `get_texts` and provide your own implementation.&quot;</span>
</span><span class='line'><span class="n">background_corpus</span> <span class="o">=</span> <span class="n">TextCorpus</span><span class="p">(</span><span class="nb">input</span><span class="o">=</span><span class="n">YOUR_CORPUS</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Important -- save the dictionary generated by the corpus, or future operations will not be able to map results</span>
</span><span class='line'><span class="c"># back to original words.</span>
</span><span class='line'><span class="n">background_corpus</span><span class="o">.</span><span class="n">dictionary</span><span class="o">.</span><span class="n">save</span><span class="p">(</span>
</span><span class='line'>    <span class="s">&quot;my_dict.dict&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">MmCorpus</span><span class="o">.</span><span class="n">serialize</span><span class="p">(</span><span class="s">&quot;background_corpus.mm&quot;</span><span class="p">,</span>
</span><span class='line'>    <span class="n">background_corpus</span><span class="p">)</span>  <span class="c">#  Uses numpy to persist wiki corpus in Matrix Market format. File will be several GBs.</span>
</span><span class='line'>
</span><span class='line'><span class="c">### Generating a large training/background corpus using Wikipedia</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">gensim.corpora</span> <span class="kn">import</span> <span class="n">WikiCorpus</span><span class="p">,</span> <span class="n">wikicorpus</span>
</span><span class='line'>
</span><span class='line'><span class="n">articles</span> <span class="o">=</span> <span class="s">&quot;enwiki-latest-pages-articles.xml.bz2&quot;</span>  <span class="c"># available from http://en.wikipedia.org/wiki/Wikipedia:Database_download</span>
</span><span class='line'>
</span><span class='line'><span class="c"># This will take many hours! Output is Wikipedia in bucket-of-words (BOW) sparse matrix.</span>
</span><span class='line'><span class="n">wiki_corpus</span> <span class="o">=</span> <span class="n">WikiCorpus</span><span class="p">(</span><span class="n">articles</span><span class="p">)</span>
</span><span class='line'><span class="n">wiki_corpus</span><span class="o">.</span><span class="n">dictionary</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s">&quot;wiki_dict.dict&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">MmCorpus</span><span class="o">.</span><span class="n">serialize</span><span class="p">(</span><span class="s">&quot;wiki_corpus.mm&quot;</span><span class="p">,</span> <span class="n">wiki_corpus</span><span class="p">)</span>  <span class="c">#  File will be several GBs.</span>
</span><span class='line'>
</span><span class='line'><span class="c">### Working with persisted corpus and dictionary</span>
</span><span class='line'><span class="n">bow_corpus</span> <span class="o">=</span> <span class="n">MmCorpus</span><span class="p">(</span><span class="s">&quot;wiki_corpus.mm&quot;</span><span class="p">)</span>  <span class="c"># Revive a corpus</span>
</span><span class='line'>
</span><span class='line'><span class="n">dictionary</span> <span class="o">=</span> <span class="n">Dictionary</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s">&quot;wiki_dict.dict&quot;</span><span class="p">)</span>  <span class="c"># Load a dictionary</span>
</span><span class='line'>
</span><span class='line'><span class="c">### Transformations among vector spaces</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">gensim.models</span> <span class="kn">import</span> <span class="n">LsiModel</span><span class="p">,</span> <span class="n">LogEntropyModel</span>
</span><span class='line'>
</span><span class='line'><span class="n">logent_transformation</span> <span class="o">=</span> <span class="n">LogEntropyModel</span><span class="p">(</span><span class="n">wiki_corpus</span><span class="p">,</span>
</span><span class='line'>    <span class="n">id2word</span><span class="o">=</span><span class="n">dictionary</span><span class="p">)</span>  <span class="c"># Log Entropy weights frequencies of all document features in the corpus</span>
</span><span class='line'>
</span><span class='line'><span class="n">tokenize_func</span> <span class="o">=</span> <span class="n">wikicorpus</span><span class="o">.</span><span class="n">tokenize</span>  <span class="c"># The tokenizer used to create the Wikipedia corpus</span>
</span><span class='line'><span class="n">document</span> <span class="o">=</span> <span class="s">&quot;Some text to be transformed.&quot;</span>
</span><span class='line'><span class="c"># First, tokenize document using the same tokenization as was used on the background corpus, and then convert it to</span>
</span><span class='line'><span class="c"># BOW representation using the dictionary created when generating the background corpus.</span>
</span><span class='line'><span class="n">bow_document</span> <span class="o">=</span> <span class="n">dictionary</span><span class="o">.</span><span class="n">doc2bow</span><span class="p">(</span><span class="n">tokenize_func</span><span class="p">(</span>
</span><span class='line'>    <span class="n">document</span><span class="p">))</span>
</span><span class='line'><span class="c"># converts a single document to log entropy representation. document must be in the same vector space as corpus.</span>
</span><span class='line'><span class="n">logent_document</span> <span class="o">=</span> <span class="n">logent_transformation</span><span class="p">[[</span>
</span><span class='line'>    <span class="n">bow_document</span><span class="p">]]</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Transform arbitrary documents by getting them into the same BOW vector space created by your training corpus</span>
</span><span class='line'><span class="n">documents</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;Some iterable&quot;</span><span class="p">,</span> <span class="s">&quot;containing multiple&quot;</span><span class="p">,</span> <span class="s">&quot;documents&quot;</span><span class="p">,</span> <span class="s">&quot;...&quot;</span><span class="p">]</span>
</span><span class='line'><span class="n">bow_documents</span> <span class="o">=</span> <span class="p">(</span><span class="n">dictionary</span><span class="o">.</span><span class="n">doc2bow</span><span class="p">(</span>
</span><span class='line'>    <span class="n">tokenize_func</span><span class="p">(</span><span class="n">document</span><span class="p">))</span> <span class="k">for</span> <span class="n">document</span> <span class="ow">in</span> <span class="n">documents</span><span class="p">)</span>  <span class="c"># use a generator expression because...</span>
</span><span class='line'><span class="n">logent_documents</span> <span class="o">=</span> <span class="n">logent_transformation</span><span class="p">[</span>
</span><span class='line'>                   <span class="n">bow_documents</span><span class="p">]</span>  <span class="c"># ...transformation is done during iteration of documents using generators, so this uses constant memory</span>
</span><span class='line'>
</span><span class='line'><span class="c">### Chained transformations</span>
</span><span class='line'><span class="c"># This builds a new corpus from iterating over documents of bow_corpus as transformed to log entropy representation.</span>
</span><span class='line'><span class="c"># Will also take many hours if bow_corpus is the Wikipedia corpus created above.</span>
</span><span class='line'><span class="n">logent_corpus</span> <span class="o">=</span> <span class="n">MmCorpus</span><span class="p">(</span><span class="n">corpus</span><span class="o">=</span><span class="n">logent_transformation</span><span class="p">[</span><span class="n">bow_corpus</span><span class="p">])</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Creates LSI transformation model from log entropy corpus representation. Takes several hours with Wikipedia corpus.</span>
</span><span class='line'><span class="n">lsi_transformation</span> <span class="o">=</span> <span class="n">LsiModel</span><span class="p">(</span><span class="n">corpus</span><span class="o">=</span><span class="n">logent_corpus</span><span class="p">,</span> <span class="n">id2word</span><span class="o">=</span><span class="n">dictionary</span><span class="p">,</span>
</span><span class='line'>    <span class="n">num_features</span><span class="o">=</span><span class="mi">400</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Alternative way of performing same operation as above, but with implicit chaining</span>
</span><span class='line'><span class="c"># lsi_transformation = LsiModel(corpus=logent_transformation[bow_corpus], id2word=dictionary,</span>
</span><span class='line'><span class="c">#    num_features=400)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Can persist transformation models, too.</span>
</span><span class='line'><span class="n">logent_transformation</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s">&quot;logent.model&quot;</span><span class="p">)</span>
</span><span class='line'><span class="n">lsi_transformation</span><span class="o">.</span><span class="n">save</span><span class="p">(</span><span class="s">&quot;lsi.model&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c">### Similarities (the best part)</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">gensim.similarities</span> <span class="kn">import</span> <span class="n">Similarity</span>
</span><span class='line'>
</span><span class='line'><span class="c"># This index corpus consists of what you want to compare future queries against</span>
</span><span class='line'><span class="n">index_documents</span> <span class="o">=</span> <span class="p">[</span><span class="s">&quot;A bear walked in the dark forest.&quot;</span><span class="p">,</span>
</span><span class='line'>             <span class="s">&quot;Tall trees have many more leaves than short bushes.&quot;</span><span class="p">,</span>
</span><span class='line'>             <span class="s">&quot;A starship may someday travel across vast reaches of space to other stars.&quot;</span><span class="p">,</span>
</span><span class='line'>             <span class="s">&quot;Difference is the concept of how two or more entities are not the same.&quot;</span><span class="p">]</span>
</span><span class='line'><span class="c"># A corpus can be anything, as long as iterating over it produces a representation of the corpus documents as vectors.</span>
</span><span class='line'><span class="n">corpus</span> <span class="o">=</span> <span class="p">(</span><span class="n">dictionary</span><span class="o">.</span><span class="n">doc2bow</span><span class="p">(</span><span class="n">tokenize_func</span><span class="p">(</span><span class="n">document</span><span class="p">))</span> <span class="k">for</span> <span class="n">document</span> <span class="ow">in</span> <span class="n">index_documents</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">index</span> <span class="o">=</span> <span class="n">Similarity</span><span class="p">(</span><span class="n">corpus</span><span class="o">=</span><span class="n">lsi_transformation</span><span class="p">[</span><span class="n">logent_transformation</span><span class="p">[</span><span class="n">corpus</span><span class="p">]],</span> <span class="n">num_features</span><span class="o">=</span><span class="mi">400</span><span class="p">,</span> <span class="n">output_prefix</span><span class="o">=</span><span class="s">&quot;shard&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span> <span class="s">&quot;Index corpus:&quot;</span>
</span><span class='line'><span class="n">pprint</span><span class="o">.</span><span class="n">pprint</span><span class="p">(</span><span class="n">documents</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">print</span> <span class="s">&quot;Similarities of index corpus documents to one another:&quot;</span>
</span><span class='line'><span class="n">pprint</span><span class="o">.</span><span class="n">pprint</span><span class="p">([</span><span class="n">s</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">index</span><span class="p">])</span>
</span><span class='line'>
</span><span class='line'><span class="n">query</span> <span class="o">=</span> <span class="s">&quot;In the face of ambiguity, refuse the temptation to guess.&quot;</span>
</span><span class='line'><span class="n">sims_to_query</span> <span class="o">=</span> <span class="n">index</span><span class="p">[</span><span class="n">lsi_transformation</span><span class="p">[</span><span class="n">logent_transformation</span><span class="p">[</span><span class="n">dictionary</span><span class="o">.</span><span class="n">doc2bow</span><span class="p">(</span><span class="n">tokenize_func</span><span class="p">(</span><span class="n">query</span><span class="p">))]]]</span>
</span><span class='line'><span class="k">print</span> <span class="s">&quot;Similarities of index corpus documents to &#39;</span><span class="si">%s</span><span class="s">&#39;&quot;</span> <span class="o">%</span> <span class="n">query</span>
</span><span class='line'><span class="n">pprint</span><span class="o">.</span><span class="n">pprint</span><span class="p">(</span><span class="n">sims_to_query</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="n">best_score</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">sims_to_query</span><span class="p">)</span>
</span><span class='line'><span class="n">index</span> <span class="o">=</span> <span class="n">sims_to_query</span><span class="o">.</span><span class="n">tolist</span><span class="p">()</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">best_score</span><span class="p">)</span>
</span><span class='line'><span class="n">most_similar_doc</span> <span class="o">=</span> <span class="n">documents</span><span class="p">[</span><span class="n">index</span><span class="p">]</span>
</span><span class='line'><span class="k">print</span> <span class="s">&quot;The document most similar to the query is &#39;</span><span class="si">%s</span><span class="s">&#39; with a score of </span><span class="si">%.2f</span><span class="s">.&quot;</span> <span class="o">%</span> <span class="p">(</span><span class="n">most_similar_doc</span><span class="p">,</span> <span class="n">best_score</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[An Introduction to gensim: "Topic Modelling for Humans"]]></title>
    <link href="http://williamjohnbert.com/2012/05/an-introduction-to-gensim-topic-modelling-for-humans/"/>
    <updated>2012-05-03T10:06:02-04:00</updated>
    <id>http://williamjohnbert.com/2012/05/an-introduction-to-gensim-topic-modelling-for-humans</id>
    <content type="html"><![CDATA[<p>On Tuesday, I presented at the monthly DC Python meetup. My talk was an introduction to gensim, a free Python framework for topic modelling and semantic similarity using LSA/LSI and other statistical techniques. I&#8217;ve been using gensim on and off for several months at work, and I really appreciate its performance, clean API design, documentation, and community. (All of this is due to its creator, Radim Rehurek, who I interviewed recently.)</p>

<p>The presentation slides are <a href="http://www.slideshare.net/sandinmyjoints/an-introduction-to-gensim-topic-modelling-for-humans">available here</a>. I also wrote some <a href="http://williamjohnbert.com/2012/05/relatively-quick-and-easy-gensim-example-code/">quick gensim example code</a> that walks through creating a corpus, generating and transforming models, and using models to do semantic similarity. The code and slides are both also available on my <a href="https://github.com/sandinmyjoints/gensimtalk">github account</a>.</p>

<p>Finally, I also developed a <a href="http://github.com/sandinmyjoints/visularity">demo app to visualize semantic similarity queries</a>. It&#8217;s a Flask web app, with gensim generating data on the backend that is clustered by scipy and scikit-learn and visualized by d3.js as agglomerative and hierarchical clusters as well as a simple table and dendrogram. To make it all work in realtime, I used threading and hookbox. I call it Visularity, and it&#8217;s <a href="http://github.com/sandinmyjoints/visularity">available on github</a>. You need to provide your own model and dictionary data to use&#8211;check out my presentation and visit <a href="http://radimrehurek.com/gensim">radimrehurek.com/gensim/</a> to learn how. Comments and feedback welcome!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Interview with Radim Rehurek, creator of gensim]]></title>
    <link href="http://williamjohnbert.com/2012/04/interview-with-radim-rehurek-creator-of-gensim/"/>
    <updated>2012-04-30T08:58:42-04:00</updated>
    <id>http://williamjohnbert.com/2012/04/interview-with-radim-rehurek-creator-of-gensim</id>
    <content type="html"><![CDATA[<p>Tomorrow at the <a href="http://meetup.dcpython.org/events/23832731/">May 2012 DC Python meetup</a>, I&#8217;m giving a talk on <a href="http://radimrehurek.com/gensim/">gensim</a>, a Python framework for topic modeling that I use at work and on my own for semantic similarity comparisons. (I&#8217;ll post the slides and example code for the talk soon.) I&#8217;ve found gensim to be a useful and well-designed tool, and pretty much all credit for it goes to its creator, Radim Rehurek. Radim was kind enough to answer a few questions I sent him about gensim&#8217;s history and goals, and about his background and interests.</p>

<p><strong>WB: Why did you create gensim?</strong></p>

<p>RR: Consulting gig for a digital library project (Czech Digital
Mathematics Library, dml.cz), some 3 years ago. It started off as a
few loosely connected Python scripts to support the &#8220;show similar
articles&#8221; functionality. We wanted to use some of the statistical
methods, like latent semantic analysis. Originally, gensim only
contained wrappers around existing Fortran libraries for SVD, like
Propack and Svdpack.</p>

<p>But there were issues with that, and it scaled badly (all documents in
RAM), so I started looking for more scalable, online algorithms.
Running these popular methods shouldn&#8217;t be so hard, I thought!</p>

<p>In the end, I developed new algorithms for these methods for gensim.
The theoretical part of this research later turned into a part of my
PhD thesis.</p>

<!-- more -->


<p><strong>Who is using gensim (as far as you know)&#8211;academics, hobbyists, commercial entities, a mixture? Any particularly interesting uses?</strong></p>

<p>Yes, I&#8217;ve heard from many academic as well as commercial
organizations, both on the mailing list and off. Off the top of my
head: ravn.co.uk, roistr.com, sportsauthority.com, larkc.eu; TU of
Denmark, U of Stuttgart, Masaryk U, U of Ghent, some people used it in
the Yahoo! KD cup competition&#8230; But what they all did with gensim, or
whether they still use it, I don&#8217;t know. The gensim license (LGPL) is
pretty liberal in that respect.</p>

<p>Unfortunately, all this use rarely translates into any feedback or
contributions. I guess I&#8217;m just not very good at the
bring-new-developers-and-grow-open-source stuff :(</p>

<p><strong>Roughly how much of the current codebase was written by you, and how much by contributors?</strong></p>

<p>Almost everything by me, but I am very grateful for bug fixes and
patches. I try to put every contribution from other people into the
changelog: https://github.com/piskvorky/gensim/blob/develop/CHANGELOG.txt
. I made some wiki pages to make contributing easier:
https://github.com/piskvorky/gensim/wiki . I also try to answer
general questions on the mailing list.</p>

<p><strong>What are your favorite features, or parts of the code that you&#8217;re most proud of?</strong></p>

<p>I don&#8217;t have emotional attachments to parts of the code &#8211; if it&#8217;s
bad, it needs to go. I guess the most proven parts are the ones that
had been around for the longest &#8211; LSA etc. Things that were
contributed recently by other people, like the new HDP (hierarchical
dirichlet process) code, or the <code>gensim.parsing</code> subpackage, are the
most rough around the edges.</p>

<p>The best feature is the memory independence for sure. Most
implementations of the statistical semantics methods assume the
training data resides in RAM, which limits their use to small/medium
corpora. Also they work in batch mode, needing a full re-train when
new training data arrives. The LSA/LDA algos are online though (can be
updated with new data, incrementally).</p>

<p><strong>What&#8217;s your background? Academic, software engineering, both?</strong></p>

<p>I finished my PhD, but I feel more like a software engineer than a
pure researcher. Even during my academic years, I was working in IT
commerce. I wouldn&#8217;t like to stay in academia professionally.</p>

<p><strong>What are you working on next for gensim? What about outside of gensim?</strong></p>

<p>Small things like adding the &#8220;hashing trick&#8221; etc:
https://github.com/piskvorky/gensim/issues . Basically things that
gensim users have been asking for. Some issues keep coming back on the
mailing list, and while not technically bugs, they hint at minor
redesigns and improvements.</p>

<p>One big thing that is missing is a basic visual style for gensim. I
have no clue how to do that and it&#8217;s really pathetic gensim doesn&#8217;t
even have a logo yet!</p>

<p>Outside of gensim, I am busy doing consulting (scaling up text
processing: fulltext search, semantic search, ad targeting etc &#8211;
backend stuff). I&#8217;m planning to do a startup that offers semantic
search and similarity as a service. A kind of easy-to-use black box
tool, something like searchify or myrrix. But it&#8217;s hard to find good
people to work with&#8230; and hard to give up/interrupt a well-paying
career :) I applied for YC last month, alone, but they turned me down.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[ExtJS TreeStore trouble with nested nodes]]></title>
    <link href="http://williamjohnbert.com/2012/04/extjs-treestore-trouble-with-nested-nodes/"/>
    <updated>2012-04-19T06:23:07-04:00</updated>
    <id>http://williamjohnbert.com/2012/04/extjs-treestore-trouble-with-nested-nodes</id>
    <content type="html"><![CDATA[<p>At work, we&#8217;re building an app to edit objects in a database&#8211;a classic CRUD
application. For now, we&#8217;re trying out ExtJS as the client-side UI
framework. One of the use cases is selecting and editing nested objects,
represented in our relational database with foreign keys. Let&#8217;s call the root
object a Task, which consists of nested Goals, which have Steps. Each of those
is defined by a model on the backend that is more or less mimicked by an
Ext.data.Model on the client-side, and each model has a proxy to a RESTful
endpoint on the backend for create/retrieve/update/delete operations. We want to
use an Ext.tree.TreePanel for the UI, so we hold the data in an
Ext.data.TreeStore. So far so good.</p>

<p>We coded up our prototype, but when a user selects a Task, Ext JS throws this
error: <code>Uncaught TypeError: Cannot read property 'internalId' of
undefined</code>. Hmm. Everything seems to be working. Our models are loading the
correct data. No obvious bugs. A lot of inspecting and googling and reading
documentation later, I discover <a href="http://www.sencha.com/forum/archive/index.php/t-160068.html?s=03fb3a67ebf1e1ef856bc5f277ad12e8">this
thread</a>. The
key quote:</p>

<!-- more -->


<blockquote><p>It doesn&#8217;t matter if the [model] ids are unique within the JSON [or any
  data]. It must be unique within the tree.</p></blockquote>

<p>If you add the first json to the tree with for example the id 4_1 and you add
the second json with again a node 4_1 then you have two nodes with the same id.</p>

<p>In other words, TreeStore doesn&#8217;t distinguish the types of roots and their
children (or children&#8217;s children, etc). To TreeStore, they are <strong>all</strong> nodes,
and ids must be unique across all nodes. If you have an instance of a Task model
with id=1 and it has a foreign key to a Goal that also has id=1, TreeStore has a
problem with that. Apparently it doesn&#8217;t introspect the objects enough to see
that, say, one is a Task and its children are Goals, despite the Task model
having a <code>hasMany</code> field that defines its relation to the Goal model. That seems
counterintuitive to me, maybe even misleading. Perhaps that&#8217;s why we&#8217;re not the
only ones who&#8217;ve
<a href="http://www.sencha.com/forum/showthread.php?129524-CLOSED-Selection-of-Association-in-DataView">had</a>
<a href="http://www.sencha.com/forum/showthread.php?135285-TreeStore-Model-and-quot-id-quot-field">this</a>
<a href="http://www.sencha.com/forum/showthread.php?196396-How-to-add-children-tree-nodes-dynamically">problem</a>.</p>

<p>My quick fix was to write a <code>stringify_id()</code> function to wrap ids passed to the TreeStore with a prefix unique to each type, so the id of Task id=1 becomes &#8220;task-1&#8221;. <code>destringify_id()</code> unwraps the ids that come back through the proxy.</p>

<p>TreeStore&#8217;s <a href="http://docs.sencha.com/ext-js/4-0/#!/api/Ext.data.TreeStore">docs</a> do not mention this restriction, as far as I can tell. Maybe if you purchase Ext JS, you get better docs, I&#8217;m not sure. We may be doing just that, so I could have a chance to find out. One of the complaints you sometimes hear about open source is that the docs aren&#8217;t that great, so I&#8217;m curious to see how a for-profit company&#8217;s docs stack up against the documentation culture of the communities I&#8217;m most familiar with (Python and Django), which tend to be pretty solid.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Fake bio for Steve]]></title>
    <link href="http://williamjohnbert.com/2012/04/fake-bio-for-steve/"/>
    <updated>2012-04-06T09:53:07-04:00</updated>
    <id>http://williamjohnbert.com/2012/04/fake-bio-for-steve</id>
    <content type="html"><![CDATA[<p>My good friend Steve has hosted <a href="http://826dc.org/?p=3336">the lowercase</a>, the monthly reading series associated with <a href="http://826dc.org/">826DC</a>, for three years. Steve has a charming habit of introducing his readers with made-up bios, so in his honor, I asked some lowercase regulars to write fake bios of him and share them at the third anniversary reading on April 4. The results were highly entertaining; thanks to everyone who wrote one!</p>

<p>Here&#8217;s mine:</p>

<blockquote><p>Steve Souryal is a group of 15 small islets and rocks in the central equatorial Atlantic Ocean. He lies in the Intertropical Convergence Zone, a region of severe storms. Steve exposes serpentinized abyssal mantle peridotite and kaersutite-bearing ultramafic mylonite on the top of the second-largest megamullion in the world (after the Parece Vela megamullion under Okinotoshima in the Pacific). He is the only location in the Atlantic Ocean where the abyssal mantle is exposed above sea level! In 1986, Steve was designated an environmentally protected area, and since 1998, the Danish Navy has maintained a permanently manned research facility in him. His main economic activity is tuna fishing, and we are incredibly lucky to have him with us tonight.</p></blockquote>

<p>Apologies to Wikipedia. But somehow, it just feels right.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to install accelerated BLAS into a Python virtualenv]]></title>
    <link href="http://williamjohnbert.com/2012/03/how-to-install-accelerated-blas-into-a-python-virtualenv/"/>
    <updated>2012-03-23T16:43:33-04:00</updated>
    <id>http://williamjohnbert.com/2012/03/how-to-install-accelerated-blas-into-a-python-virtualenv</id>
    <content type="html"><![CDATA[<h2>Background</h2>

<p>Some mathematically intense operations that use Numpy/Scipy can run faster with accelerated basic linear algebra subroutine (BLAS) libraries installed on your system (e.g., <a href="http://radimrehurek.com/gensim/">gensim&#8217;s</a> corpus processing).</p>

<p>To see what BLAS libraries you are using, do:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="n">python</span> <span class="o">-</span><span class="n">c</span> <span class="s">&#39;import numpy; numpy.show_config()&#39;</span>
</span></code></pre></td></tr></table></div></figure>


<p>If none of them are installed, you probably want to install one or
more. <a href="http://math-atlas.sourceforge.net/">ATLAS</a> is always a good bet, since
it&#8217;s portable and self-optimizing. There are others out there targeted at
particular CPU architectures.</p>

<!-- more -->


<p>Unfortunately, the <a href="http://docs.scipy.org/doc/numpy/user/install.html">Scipy
docs</a> are out of date
regarding installing accelerated BLAS libraries on Ubuntu. The instructions I
have written below work for Ubuntu 10.04, the current LTS (long-term support)
version, and though I haven&#8217;t tried to run them on a more recent version, it&#8217;s
possible they work with those as well.</p>

<h2>Prereqs</h2>

<p>On Ubuntu 10.04, and possibly other versions, you need liblapack-dev and gfortran (yes, fortran):</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>sudo apt-get install liblapack-dev
</span><span class='line'><span class="nv">$ </span>sudo apt-get install gfortran
</span></code></pre></td></tr></table></div></figure>


<h2>Instructions</h2>

<p>Install the accelerated linear algebra libraries (ATLAS/LAPACK) in your virtualenv on Ubutu:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="c">#!/bin/bash</span>
</span><span class='line'>workon <span class="o">[</span>envname<span class="o">]</span>
</span><span class='line'>pip uninstall numpy <span class="c">## only if numpy is already installed</span>
</span><span class='line'>pip uninstall scipy <span class="c">## only if scipy is already installed</span>
</span><span class='line'><span class="nb">export </span><span class="nv">LAPACK</span><span class="o">=</span>/usr/lib/liblapack.so
</span><span class='line'><span class="nb">export </span><span class="nv">ATLAS</span><span class="o">=</span>/usr/lib/libatlas.so
</span><span class='line'><span class="nb">export </span><span class="nv">BLAS</span><span class="o">=</span>/usr/lib/libblas.so
</span></code></pre></td></tr></table></div></figure>


<p>Now you can install numpy and scipy into the same virtualenv and be confident they will perform operations using the accelerated BLAS routines:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='bash'><span class='line'><span class="nv">$ </span>pip install numpy
</span><span class='line'><span class="nv">$ </span>pip install scipy
</span></code></pre></td></tr></table></div></figure>



]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Novelties & Traditions]]></title>
    <link href="http://williamjohnbert.com/2011/11/novelties-traditions/"/>
    <updated>2011-11-19T05:28:21-05:00</updated>
    <id>http://williamjohnbert.com/2011/11/novelties-traditions</id>
    <content type="html"><![CDATA[<p>Today&#8217;s the third annual Friendsgiving, a Thanksgiving-like pre-Thanksgiving event for a bunch of people who like each other; hence, Friendsgiving. Thanksgiving&#8217;s always been my favorite holiday so I&#8217;m more than happy to celebrate it twice a year. The first two Friendsgivings took place at my house, but because in the spring I traded my room in a cavernous and amply chandeliered group rowhouse for cozier and warmer digs, the honor of hosting this year falls to two friends who&#8217;re renting an entire lovely house for themselves up in Pleasant Plains. Sweet.</p>

<p>So much for traditions; recent novelties include starting a new job, about which more another time, but basically, I love it; and getting a lesson plan published in <a href="http://www.amzn.com/111802432X">Don&#8217;t Forget to Write</a>, the second volume of lesson plans from <a href="http://www.826national.org/">826</a>. The lesson plan, &#8220;Busted,&#8221; aims to make storytellers out of middle schoolers by having them write about a time they got caught doing something they shouldn&#8217;t have been doing&#8211;a theme first cooked up by the folks who led the <a href="http://826dc.org/?p=510">Get Used to the Seats</a> book project. I <a href="http://williamjohnbert.com/2010/11/caught-in-the-act-part-3/">wrote about leading the workshops that ultimately became the &#8220;Busted&#8221; lesson plan</a> more than a year ago&#8211;right around the previous Friendsgiving. Hard to believe it&#8217;s been that long!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Gender, programming, and the power of language ]]></title>
    <link href="http://williamjohnbert.com/2011/08/gender-programming-and-the-power-of-language/"/>
    <updated>2011-08-28T12:15:02-04:00</updated>
    <id>http://williamjohnbert.com/2011/08/gender-programming-and-the-power-of-language</id>
    <content type="html"><![CDATA[<p>An interlude from the recent trend of hardcore Django action:</p>

<blockquote><p>When I spoke with a female intern this summer, she recounted how, in 2006, the
GNOME Project, a free and open source software project, received almost 200 Google
Summer of Code applicants. All of them were male. When GNOME advertised an
identical program for women, emphasizing opportunities for learning and mentorship
instead of tough competition, they received more than 100 highly qualified female
applicants for the three spots they were able to fund. What amazed me even more was
when she suggested that our own company slogan — “We Help the World’s Best
Developers Make Better Software” — might alienate prospective female candidates.
That had never occurred to me. But according to our intern, in the world of
computer science, “when you hear the phrase ‘the world’s best developers,’ you see
a guy.”</p></blockquote>

<p>From <a href="http://www.washingtonpost.com/opinions/when-computer-programming-was-womens-work/2011/08/24/gIQAdixGgJ_print.html">When computer programming was ‘women’s work’</a>.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[django-social-auth: Installing and troubleshooting]]></title>
    <link href="http://williamjohnbert.com/2011/08/django-social-auth-installing-and-troubleshooting/"/>
    <updated>2011-08-26T07:16:14-04:00</updated>
    <id>http://williamjohnbert.com/2011/08/django-social-auth-installing-and-troubleshooting</id>
    <content type="html"><![CDATA[<p>Thanks to <code>django-registration</code>, I was able to build a working account
registration/login system pretty easily. But I wanted to give users the ability
to use their existing accounts through popular services such as Facebook,
Twitter, etc., rather than have to create yet another account. Here&#8217;s how I did
it.</p>

<h1>Sorting Through the Choices</h1>

<p>There are a number of reusable Django apps out there to help with
registration/login from social media sites. I found this <a href="http://hackerluddite.wordpress.com/2011/05/17/review-of-4-django-social-auth-apps/">Review of 4 Django Social Auth apps</a>
very helpful in sorting out the options. After reading it, I was left to choose
between <a href="https://github.com/omab/django-social-auth"><code>django-social-auth</code></a> (I
originally linked to the wrong app here, but this link is correct) and
<a href="https://github.com/pennersr/django-allauth"><code>django-allauth</code></a>. In the end, I
went with <code>django-social-auth</code> (not to be confused with <code>django-socialauth</code>)
because a friend had recommended it and because I&#8217;d already installed it before
I read this article. However, the article&#8217;s conclusion that <code>django-allauth</code> is
best out of the box also seems valid.</p>

<h1>Installation</h1>

<p>The instructions in <a href="http://django-social-auth.readthedocs.org/en/latest/"><code>django-social-auth</code>&#8217;s docs</a> are helpful in
walking you through available settings and options.</p>

<p>I also found the included example app useful. To use this app, I cloned
<code>django-social-auth</code>&#8217;s git repo, created a virtualenv called
<code>django-social-auth</code>, ran <code>pip install -r requirements.txt</code> inside this
virtualenv to install all the required apps, ran <code>manage.py syncdb</code>, and finally
ran <code>manage.py runserver</code>. Voila, example app is up and running at 127.0.0.1,
showing a simple screen with options to login through about a dozen different
different services.</p>

<h1>API Keys</h1>

<p>The first service I tested was Twitter. I use it more than any others, and I
already had the API keys for it. I threw my API key and secret key into the
example <code>local_settings.py</code> file provided with <code>django-social-auth</code> and tried to
log in via the example app. Boom: <code>401 Unauthorized</code>. I double-checked all my
settings and installation and whatnot. Seemed fine.</p>

<p>I turned my attention to the API keys. The ones I had were generated for
<a href="http://www.readsrs.com">Readsr</a>, i.e., I entered readsrs.com as the domain when
I generated them at dev.twitter.com. But now I was running on localhost,
127.0.0.1, so I suspected the readsrs.com keys wouldn&#8217;t be valid. I wasn&#8217;t sure
whether Twitter would hand over a new consumer key for 127.0.0.1, or baulk at
the request. (It seemed like it should do so, but I hadn&#8217;t seen any instructions
anywhere that said to get a key for your development machine.) Turns out Twitter
will happily give you a key for 127.0.0.1. Once I plugged the new keys in, I was
able to log in with my Twitter credentials, and just as it should,
<code>django-social-auth</code> automatically created an <code>auth.user</code> for this account.</p>

<h1>Integrating with Readsr</h1>

<p>I followed the instructions again to config my own app, Readsr. To add a login
option using Twitter credentials, I put a link to the reversed view that begins
the <code>django-social-auth</code> login process for twitter, i.e., <code>{% url
socialauth_begin "twitter" %}</code>, to my login template. And it worked.</p>

<p>I still need to fix a few oddities. For example, Twitter returns my first and
last names together in <code>first_name</code> (or else <code>django-social-auth</code> is
concatenating them into that column), and doesn&#8217;t supply any email address. But
the basic functionality is there, and was relatively easy to achieve.</p>

<h1>Postscript</h1>

<p>The author of the article I linked above had an error using OpenID when using <code>django-social-auth</code>, which is why he preferred <code>django-authall</code>. He filed a bug
for the error he got, and I notice that <a href="https://github.com/omab/django-social-auth/issues/67">it was closed</a> 15 hours ago
(though if you read the comments, it seems it was actually fixed back in
mid-July). Good timing.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[How to: Unit testing in Django with mocking and patching]]></title>
    <link href="http://williamjohnbert.com/2011/07/how-to-unit-testing-in-django-with-mocking-and-patching/"/>
    <updated>2011-07-08T06:56:29-04:00</updated>
    <id>http://williamjohnbert.com/2011/07/how-to-unit-testing-in-django-with-mocking-and-patching</id>
    <content type="html"><![CDATA[<h3>Background</h3>

<p>For <a href="www.readsrs.com">Readsr</a>, I need to track events that recur on a particular
day of the week (e.g., first Sunday of the month, third Friday of the month). I
created a DayOfWeek model to store any particular event&#8217;s day of the week. It
contains a method next_day_of_week() to return a datetime.date object set to
the next occurrence of whatever weekday a given event instance is set to (this
helps with figuring out when the next occurrence of an event is).</p>

<p>It&#8217;s easier to show through an example. On Sunday 7/3/2011:</p>

<ul>
<li>For an object with DayOfWeek set to Sunday, next_day_of_week() would return 7/3/2011 (current day).</li>
<li>For DayOfWeek set to Monday, it would return 7/4/2011 (first subsequent Monday).</li>
<li>For DayOfWeek set to Saturday, it would return 7/9/2011 (first subsequent Saturday).</li>
</ul>


<p>Sounds simple enough. It seemed like this would be a good place to do my first
unit tests.</p>

<h3>Unit Testing</h3>

<p>To do unit testing, the typical method is to first write test cases and then
write code. In this case, I&#8217;d already written my code, so I went back and wrote
test cases, trying to forget how my code worked.</p>

<p>To write test cases, you have to detail requirements for each method you want to
test: input and expected (correct) output. The list of examples for
next_day_of_week() I wrote above works for this purpose. But there&#8217;s a catch:
next_day_of_week() calculates the next day of the week relative to the
current date, by calling datetime.date.today(). So if I write expected output
for 7/3/2011, it will no longer be the correct output on 7/4/2011 or any
following day. I needed a way to make datetime.date.today() always spit out my
input date when I run tests, yet still continue to function normally outside of
testing. Enter mocking.</p>

<h3>Mocking</h3>

<p>The solution was to mock out the method&#8211;to replace the real
datetime.date.today() with a fake one that produces the same output no matter
what day it is. To accomplish this, I used the powerful <a href="http://www.voidspace.org.uk/python/mock/">Mock
library</a>. Specifically, I needed to
use the patch decorator. This decorator makes it really easy to replace on
particular object within the scope of a particular method.</p>

<p>Before I could patch the today() method, I needed to create my own fake
method. It would look like this:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">faketoday</span><span class="p">()</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">date</span><span class="p">(</span><span class="mi">2011</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>There&#8217;s a problem, though, when I try to patch (or mock out) the method:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="kn">import</span> <span class="nn">mock</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="k">def</span> <span class="nf">faketoday</span><span class="p">():</span>
</span><span class='line'><span class="o">...</span>     <span class="k">return</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="p">(</span><span class="mi">2011</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">4</span><span class="p">)</span>
</span><span class='line'><span class="o">...</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="nd">@mock.patch</span><span class="p">(</span><span class="s">&quot;datetime.date.today&quot;</span><span class="p">,</span> <span class="n">faketoday</span><span class="p">)</span>
</span><span class='line'><span class="o">...</span> <span class="k">def</span> <span class="nf">testfunc</span><span class="p">():</span>
</span><span class='line'><span class="o">...</span>     <span class="k">return</span> <span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span>
</span><span class='line'><span class="o">...</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span> <span class="n">testfunc</span><span class="p">()</span>
</span><span class='line'><span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;&lt;console&gt;&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o">&lt;</span><span class="n">module</span><span class="o">&gt;</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;/Users/wbert/.virtualenvs/readsr_env/lib/python2.6/site-packages/mock.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">561</span><span class="p">,</span> <span class="ow">in</span> <span class="n">patched</span>
</span><span class='line'>    <span class="n">arg</span> <span class="o">=</span> <span class="n">patching</span><span class="o">.</span><span class="n">__enter__</span><span class="p">()</span>
</span><span class='line'>  <span class="n">File</span> <span class="s">&quot;/Users/wbert/.virtualenvs/readsr_env/lib/python2.6/site-packages/mock.py&quot;</span><span class="p">,</span> <span class="n">line</span> <span class="mi">623</span><span class="p">,</span> <span class="ow">in</span> <span class="n">__enter__</span>
</span><span class='line'>    <span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">attribute</span><span class="p">,</span> <span class="n">new_attr</span><span class="p">)</span>
</span><span class='line'><span class="ne">TypeError</span><span class="p">:</span> <span class="n">can</span><span class="s">&#39;t set attributes of built-in/extension type &#39;</span><span class="n">datetime</span><span class="o">.</span><span class="n">date</span><span class="s">&#39;</span>
</span><span class='line'><span class="o">&gt;&gt;&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p><code>datetime.date</code> is considered a Python built-in and can&#8217;t be modified.</p>

<h3>Modifying a Class That Can&#8217;t Be Modified</h3>

<p>The trick is to write a child class that can be modified, and thus faked:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">FakeDate</span><span class="p">(</span><span class="n">date</span><span class="p">):</span>
</span><span class='line'>  <span class="s">&quot;A fake replacement for date that can be mocked for testing.&quot;</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">__new__</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span class='line'>      <span class="k">return</span> <span class="n">date</span><span class="o">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">date</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>All this does is create a class whose constructor returns an instance of its
parent&#8217;s class, date. Usually, this would be pointless, but it&#8217;s useful here
because the new class isn&#8217;t a built-in and thus can be mocked.</p>

<p>To use it, we simply decorate any test method that calls datetime.date.today()
with a patch to replace datetime.date with FakeDate, and we also provide
FakeDate a fake today() method that returns only and always the particular we
are going to use for testing:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">class</span> <span class="nc">TestDayOfWeek</span><span class="p">(</span><span class="n">TestCase</span><span class="p">):</span>
</span><span class='line'>  <span class="sd">&quot;&quot;&quot;Test the day of the week functions.&quot;&quot;&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="nd">@mock.patch</span><span class="p">(</span><span class="s">&#39;series.models.date&#39;</span><span class="p">,</span> <span class="n">FakeDate</span><span class="p">)</span>
</span><span class='line'><span class="k">def</span> <span class="nf">test_valid_my_next_day_of_week_sameday</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span class='line'>  <span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">date</span>
</span><span class='line'>  <span class="n">FakeDate</span><span class="o">.</span><span class="n">today</span> <span class="o">=</span> <span class="nb">classmethod</span><span class="p">(</span><span class="k">lambda</span> <span class="n">cls</span><span class="p">:</span> <span class="n">date</span><span class="p">(</span><span class="mi">2011</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span> <span class="c"># July 3, 2011 is a Sunday</span>
</span><span class='line'>  <span class="n">new_day_of_week</span> <span class="o">=</span> <span class="n">DayOfWeek</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">create</span><span class="p">()</span>
</span><span class='line'>  <span class="n">new_day_of_week</span><span class="o">.</span><span class="n">day</span> <span class="o">=</span> <span class="s">&quot;SU&quot;</span>
</span><span class='line'>  <span class="bp">self</span><span class="o">.</span><span class="n">assertEquals</span><span class="p">(</span><span class="n">new_day_of_week</span><span class="o">.</span><span class="n">my_next_day_of_week</span><span class="p">(),</span> <span class="n">date</span><span class="p">(</span><span class="mi">2011</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>


<p>A couple things to note: the patch only applies within this particular method,
so each method to use a patch must be decorated. Also, the real datetime.date is
imported in the method so we can use it inside the fake today() method. We could
put this fake today() method inside FakeClass, but making it a lambda
(anonymous) method assigned inside the test case gives us the flexibility to set
a particular date for each test case.</p>

<h3>Namespacing</h3>

<p>You may be wondering why the patch decorator takes &#8220;series.models.date&#8221; as the
method to replace instead of &#8220;datetime.date&#8221;. That was how I tried it at first,
and I was confused when it didn&#8217;t work. It seemed as if the patch hadn&#8217;t taken
effect.</p>

<p>Well, it hadn&#8217;t. That&#8217;s because within the module being tested (models.py in the
series app, or series.models in Python dotted notation), date has been imported
like so:</p>

<figure class='code'> <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">date</span>
</span></code></pre></td></tr></table></div></figure>


<p>This means that within series.models, date is now available as
series.models.date, so that&#8217;s the name that needs to be mocked out. For more on
namespacing when mocking, checked out <a href="http://www.voidspace.org.uk/python/mock/patch.html#id2">Mock&#8217;s Where to patch documentation</a>.</p>

<p>Now we can supply out unit tests with any date we want, ensuring that we know
what the results should be and can test against them.</p>

<h3>References</h3>

<p>Learning how to do this stuff, I posted <a href="http://stackoverflow.com/questions/6575687/how-do-i-use-mocking-to-test-a-next-day-of-week-function">my first question at Stackoverflow</a>
(I ended up answering it myself). I also learned about using a fake class <a href="http://stackoverflow.com/questions/4481954/python-trying-to-mock-datetime-date-today-but-not-working">from this question</a>. Finally,
the <a href="http://www.voidspace.org.uk/python/mock/index.html">Mock documentation</a> was
very helpful as well.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Simple Django Event Calendar]]></title>
    <link href="http://williamjohnbert.com/2011/06/django-event-calendar-for-a-django-beginner/"/>
    <updated>2011-06-13T16:34:52-04:00</updated>
    <id>http://williamjohnbert.com/2011/06/django-event-calendar-for-a-django-beginner</id>
    <content type="html"><![CDATA[<h3>Background</h3>

<p>I&#8217;ve been teaching myself Django by writing a web app that tracks reading series in cities: <a href="http://www.readsrs.com">Readsr</a>. A reading series is a kind of recurring event. It defines a time, location, and recurrence rule such as first Monday of the month. Writing a list view to display upcoming readings was easy, but I also wanted to create a calendar view, similar to what Google Calendar provides. That took a little more work.</p>

<h3>Existing Solutions</h3>

<p>First I searched for existing Django calendar solutions. I found several. <a href="https://code.google.com/p/django-swingtime/">Swingtime</a> and <a href="https://github.com/dokterbob/django-agenda">django-agenda</a> seemed very well thought out and comprehensive, but were also perhaps overkill for what I needed. <a href="https://code.google.com/p/django-gencal/">django-gencal</a> doesn&#8217;t appear to be maintained and I had trouble understanding the documentation (though you may have better results, as I am slow).</p>

<h3>A Way Forward</h3>

<p>I found that Python&#8217;s calendar module has a built template called <a href="http://docs.python.org/library/calendar.html#calendar.HTMLCalendar">HTMLCalendar</a>, which sounded promising. Then I found a <a href="http://journal.uggedal.com/creating-a-flexible-monthly-calendar-in-django/">couple</a> <a href="http://drumcoder.co.uk/blog/2010/jun/13/monthly-calendar-django/">examples</a> of people inheriting from HTMLCalendar to add data to the calendar display. This sounded right on, so I adapted this code for my reading events.</p>

<h3>Problem: Presentation and Content Mixed</h3>

<p>I noticed a problem in the code I was adapting. The view was producing HTML. That seemed to violate separation of content and presentation. Shouldn&#8217;t the HTML be generated in the template? And since the templating language itself isn&#8217;t powerful enough to generate an HTML table from a list of objects, that meant I needed to write my own template tag. Yikes.</p>

<h3>Writing My First Template Tag</h3>

<p>Django&#8217;s documentation made it easy, though. A template tag consists of a few parts. Below is the code; it goes into a subdirectory of the django app called &#8220;templatetags.&#8221;</p>

<p>The first part follows directly from the Django docs: get a register object.</p>

<p>Then I define a function to parse the template tag arguments and return the node (the HTML code from which the page is eventually build). The template syntax is defined here.</p>

<p>Then I define the node itself, which is made thread-safe by storing and retrieving the variables passed through the template tag from a context (again, this is straight from the Django docs).</p>

<p>Then I inherit from HTMLCalendar and redefine the format methods to add the particular reading event data. You could adapt this class to any kind of event that has an associated date/time by changing the groupby lambda function to use whatever field your event object uses to store its date and time (my reading object simply calls it &#8220;date_and_time&#8221;).</p>

<p>Finally, I register this template tag so it is available to templates.</p>

<p>Here&#8217;s the code.</p>

<figure class='code'><figcaption><span>Reading calendar  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'>
</span><span class='line'><span class="kn">from</span> <span class="nn">calendar</span> <span class="kn">import</span> <span class="n">HTMLCalendar</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">django</span> <span class="kn">import</span> <span class="n">template</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">date</span>
</span><span class='line'><span class="kn">from</span> <span class="nn">itertools</span> <span class="kn">import</span> <span class="n">groupby</span>
</span><span class='line'>
</span><span class='line'><span class="kn">from</span> <span class="nn">django.utils.html</span> <span class="kn">import</span> <span class="n">conditional_escape</span> <span class="k">as</span> <span class="n">esc</span>
</span><span class='line'>
</span><span class='line'><span class="n">register</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Library</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">do_reading_calendar</span><span class="p">(</span><span class="n">parser</span><span class="p">,</span> <span class="n">token</span><span class="p">):</span>
</span><span class='line'>  <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd"> The template tag&#39;s syntax is { % reading_calendar year month reading_list %}</span>
</span><span class='line'><span class="sd"> &quot;&quot;&quot;</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">try</span><span class="p">:</span>
</span><span class='line'>      <span class="n">tag_name</span><span class="p">,</span> <span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">,</span> <span class="n">reading_list</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">split_contents</span><span class="p">()</span>
</span><span class='line'>  <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span class='line'>      <span class="k">raise</span> <span class="n">template</span><span class="o">.</span><span class="n">TemplateSyntaxError</span><span class="p">,</span> <span class="s">&quot;</span><span class="si">%r</span><span class="s"> tag requires three arguments&quot;</span> <span class="o">%</span> <span class="n">token</span><span class="o">.</span><span class="n">contents</span><span class="o">.</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">ReadingCalendarNode</span><span class="p">(</span><span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">,</span> <span class="n">reading_list</span><span class="p">)</span>
</span><span class='line'>  
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ReadingCalendarNode</span><span class="p">(</span><span class="n">template</span><span class="o">.</span><span class="n">Node</span><span class="p">):</span>
</span><span class='line'>  <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd"> Process a particular node in the template. Fail silently.</span>
</span><span class='line'><span class="sd"> &quot;&quot;&quot;</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">,</span> <span class="n">reading_list</span><span class="p">):</span>
</span><span class='line'>      <span class="k">try</span><span class="p">:</span>
</span><span class='line'>          <span class="bp">self</span><span class="o">.</span><span class="n">year</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Variable</span><span class="p">(</span><span class="n">year</span><span class="p">)</span>
</span><span class='line'>          <span class="bp">self</span><span class="o">.</span><span class="n">month</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Variable</span><span class="p">(</span><span class="n">month</span><span class="p">)</span>
</span><span class='line'>          <span class="bp">self</span><span class="o">.</span><span class="n">reading_list</span> <span class="o">=</span> <span class="n">template</span><span class="o">.</span><span class="n">Variable</span><span class="p">(</span><span class="n">reading_list</span><span class="p">)</span>
</span><span class='line'>      <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span class='line'>          <span class="k">raise</span> <span class="n">template</span><span class="o">.</span><span class="n">TemplateSyntaxError</span>
</span><span class='line'>      
</span><span class='line'>  <span class="k">def</span> <span class="nf">render</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
</span><span class='line'>      <span class="k">try</span><span class="p">:</span>
</span><span class='line'>          <span class="c"># Get the variables from the context so the method is thread-safe.</span>
</span><span class='line'>          <span class="n">my_reading_list</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">reading_list</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
</span><span class='line'>          <span class="n">my_year</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
</span><span class='line'>          <span class="n">my_month</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">month</span><span class="o">.</span><span class="n">resolve</span><span class="p">(</span><span class="n">context</span><span class="p">)</span>
</span><span class='line'>          <span class="n">cal</span> <span class="o">=</span> <span class="n">ReadingCalendar</span><span class="p">(</span><span class="n">my_reading_list</span><span class="p">)</span>
</span><span class='line'>          <span class="k">return</span> <span class="n">cal</span><span class="o">.</span><span class="n">formatmonth</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">my_year</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">my_month</span><span class="p">))</span>
</span><span class='line'>      <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span class='line'>          <span class="k">return</span>           
</span><span class='line'>      <span class="k">except</span> <span class="n">template</span><span class="o">.</span><span class="n">VariableDoesNotExist</span><span class="p">:</span>
</span><span class='line'>          <span class="k">return</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">ReadingCalendar</span><span class="p">(</span><span class="n">HTMLCalendar</span><span class="p">):</span>
</span><span class='line'>  <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd"> Overload Python&#39;s calendar.HTMLCalendar to add the appropriate reading events to</span>
</span><span class='line'><span class="sd"> each day&#39;s table cell.</span>
</span><span class='line'><span class="sd"> &quot;&quot;&quot;</span>
</span><span class='line'>  
</span><span class='line'>  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">readings</span><span class="p">):</span>
</span><span class='line'>      <span class="nb">super</span><span class="p">(</span><span class="n">ReadingCalendar</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">()</span>
</span><span class='line'>      <span class="bp">self</span><span class="o">.</span><span class="n">readings</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">group_by_day</span><span class="p">(</span><span class="n">readings</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">formatday</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">day</span><span class="p">,</span> <span class="n">weekday</span><span class="p">):</span>
</span><span class='line'>      <span class="k">if</span> <span class="n">day</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
</span><span class='line'>          <span class="n">cssclass</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cssclasses</span><span class="p">[</span><span class="n">weekday</span><span class="p">]</span>
</span><span class='line'>          <span class="k">if</span> <span class="n">date</span><span class="o">.</span><span class="n">today</span><span class="p">()</span> <span class="o">==</span> <span class="n">date</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">month</span><span class="p">,</span> <span class="n">day</span><span class="p">):</span>
</span><span class='line'>              <span class="n">cssclass</span> <span class="o">+=</span> <span class="s">&#39; today&#39;</span>
</span><span class='line'>          <span class="k">if</span> <span class="n">day</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">readings</span><span class="p">:</span>
</span><span class='line'>              <span class="n">cssclass</span> <span class="o">+=</span> <span class="s">&#39; filled&#39;</span>
</span><span class='line'>              <span class="n">body</span> <span class="o">=</span> <span class="p">[</span><span class="s">&#39;&lt;ul&gt;&#39;</span><span class="p">]</span>
</span><span class='line'>              <span class="k">for</span> <span class="n">reading</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">readings</span><span class="p">[</span><span class="n">day</span><span class="p">]:</span>
</span><span class='line'>                  <span class="n">body</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;&lt;li&gt;&#39;</span><span class="p">)</span>
</span><span class='line'>                  <span class="n">body</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;&lt;a href=&quot;</span><span class="si">%s</span><span class="s">&quot;&gt;&#39;</span> <span class="o">%</span> <span class="n">reading</span><span class="o">.</span><span class="n">get_absolute_url</span><span class="p">())</span>
</span><span class='line'>                  <span class="n">body</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">esc</span><span class="p">(</span><span class="n">reading</span><span class="o">.</span><span class="n">series</span><span class="o">.</span><span class="n">primary_name</span><span class="p">))</span>
</span><span class='line'>                  <span class="n">body</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;&lt;/a&gt;&lt;/li&gt;&#39;</span><span class="p">)</span>
</span><span class='line'>              <span class="n">body</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#39;&lt;/ul&gt;&#39;</span><span class="p">)</span>
</span><span class='line'>              <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">day_cell</span><span class="p">(</span><span class="n">cssclass</span><span class="p">,</span> <span class="s">&#39;&lt;span class=&quot;dayNumber&quot;&gt;</span><span class="si">%d</span><span class="s">&lt;/span&gt; </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">day</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">body</span><span class="p">)))</span>
</span><span class='line'>          <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">day_cell</span><span class="p">(</span><span class="n">cssclass</span><span class="p">,</span> <span class="s">&#39;&lt;span class=&quot;dayNumberNoReadings&quot;&gt;</span><span class="si">%d</span><span class="s">&lt;/span&gt;&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">day</span><span class="p">))</span>
</span><span class='line'>      <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">day_cell</span><span class="p">(</span><span class="s">&#39;noday&#39;</span><span class="p">,</span> <span class="s">&#39;&amp;nbsp;&#39;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">formatmonth</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">):</span>
</span><span class='line'>      <span class="bp">self</span><span class="o">.</span><span class="n">year</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">month</span> <span class="o">=</span> <span class="n">year</span><span class="p">,</span> <span class="n">month</span>
</span><span class='line'>      <span class="k">return</span> <span class="nb">super</span><span class="p">(</span><span class="n">ReadingCalendar</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">formatmonth</span><span class="p">(</span><span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">group_by_day</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">readings</span><span class="p">):</span>
</span><span class='line'>      <span class="n">field</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">reading</span><span class="p">:</span> <span class="n">reading</span><span class="o">.</span><span class="n">date_and_time</span><span class="o">.</span><span class="n">day</span>
</span><span class='line'>      <span class="k">return</span> <span class="nb">dict</span><span class="p">(</span>
</span><span class='line'>          <span class="p">[(</span><span class="n">day</span><span class="p">,</span> <span class="nb">list</span><span class="p">(</span><span class="n">items</span><span class="p">))</span> <span class="k">for</span> <span class="n">day</span><span class="p">,</span> <span class="n">items</span> <span class="ow">in</span> <span class="n">groupby</span><span class="p">(</span><span class="n">readings</span><span class="p">,</span> <span class="n">field</span><span class="p">)]</span>
</span><span class='line'>      <span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">day_cell</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cssclass</span><span class="p">,</span> <span class="n">body</span><span class="p">):</span>
</span><span class='line'>      <span class="k">return</span> <span class="s">&#39;&lt;td class=&quot;</span><span class="si">%s</span><span class="s">&quot;&gt;</span><span class="si">%s</span><span class="s">&lt;/td&gt;&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="n">cssclass</span><span class="p">,</span> <span class="n">body</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Register the template tag so it is available to templates</span>
</span><span class='line'><span class="n">register</span><span class="o">.</span><span class="n">tag</span><span class="p">(</span><span class="s">&quot;reading_calendar&quot;</span><span class="p">,</span> <span class="n">do_reading_calendar</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Then, here&#8217;s the view (and a couple helper functions) that gets called with the arguments from the URL, including the year, month, and series to display events for.</p>

<figure class='code'><figcaption><span>View  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="k">def</span> <span class="nf">named_month</span><span class="p">(</span><span class="n">month_number</span><span class="p">):</span>
</span><span class='line'>
</span><span class='line'>  <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd"> Return the name of the month, given the number.</span>
</span><span class='line'><span class="sd"> &quot;&quot;&quot;</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">date</span><span class="p">(</span><span class="mi">1900</span><span class="p">,</span> <span class="n">month_number</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s">&quot;%B&quot;</span><span class="p">)</span>
</span><span class='line'>  
</span><span class='line'><span class="k">def</span> <span class="nf">this_month</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
</span><span class='line'>  <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd"> Show calendar of readings this month.</span>
</span><span class='line'><span class="sd"> &quot;&quot;&quot;</span>
</span><span class='line'>  <span class="n">today</span> <span class="o">=</span> <span class="n">datetime</span><span class="o">.</span><span class="n">now</span><span class="p">()</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">calendar</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">today</span><span class="o">.</span><span class="n">year</span><span class="p">,</span> <span class="n">today</span><span class="o">.</span><span class="n">month</span><span class="p">)</span>
</span><span class='line'>  
</span><span class='line'>  
</span><span class='line'><span class="k">def</span> <span class="nf">calendar</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">,</span> <span class="n">series_id</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
</span><span class='line'>  <span class="sd">&quot;&quot;&quot;</span>
</span><span class='line'><span class="sd"> Show calendar of readings for a given month of a given year.</span>
</span><span class='line'><span class="sd"> ``series_id``</span>
</span><span class='line'><span class="sd"> The reading series to show. None shows all reading series.</span>
</span><span class='line'><span class="sd"> &quot;&quot;&quot;</span>
</span><span class='line'>  
</span><span class='line'>  <span class="n">my_year</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">year</span><span class="p">)</span>
</span><span class='line'>  <span class="n">my_month</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">month</span><span class="p">)</span>
</span><span class='line'>  <span class="n">my_calendar_from_month</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="n">my_year</span><span class="p">,</span> <span class="n">my_month</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span><span class='line'>  <span class="n">my_calendar_to_month</span> <span class="o">=</span> <span class="n">datetime</span><span class="p">(</span><span class="n">my_year</span><span class="p">,</span> <span class="n">my_month</span><span class="p">,</span> <span class="n">monthrange</span><span class="p">(</span><span class="n">my_year</span><span class="p">,</span> <span class="n">my_month</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">my_reading_events</span> <span class="o">=</span> <span class="n">Reading</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">date_and_time__gte</span><span class="o">=</span><span class="n">my_calendar_from_month</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">date_and_time__lte</span><span class="o">=</span><span class="n">my_calendar_to_month</span><span class="p">)</span>
</span><span class='line'>  <span class="k">if</span> <span class="n">series_id</span><span class="p">:</span>
</span><span class='line'>      <span class="n">my_reading_events</span> <span class="o">=</span> <span class="n">my_reading_events</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">series</span><span class="o">=</span><span class="n">series_id</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="c"># Calculate values for the calendar controls. 1-indexed (Jan = 1)</span>
</span><span class='line'>  <span class="n">my_previous_year</span> <span class="o">=</span> <span class="n">my_year</span>
</span><span class='line'>  <span class="n">my_previous_month</span> <span class="o">=</span> <span class="n">my_month</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>  <span class="k">if</span> <span class="n">my_previous_month</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span><span class='line'>      <span class="n">my_previous_year</span> <span class="o">=</span> <span class="n">my_year</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>      <span class="n">my_previous_month</span> <span class="o">=</span> <span class="mi">12</span>
</span><span class='line'>  <span class="n">my_next_year</span> <span class="o">=</span> <span class="n">my_year</span>
</span><span class='line'>  <span class="n">my_next_month</span> <span class="o">=</span> <span class="n">my_month</span> <span class="o">+</span> <span class="mi">1</span>
</span><span class='line'>  <span class="k">if</span> <span class="n">my_next_month</span> <span class="o">==</span> <span class="mi">13</span><span class="p">:</span>
</span><span class='line'>      <span class="n">my_next_year</span> <span class="o">=</span> <span class="n">my_year</span> <span class="o">+</span> <span class="mi">1</span>
</span><span class='line'>      <span class="n">my_next_month</span> <span class="o">=</span> <span class="mi">1</span>
</span><span class='line'>  <span class="n">my_year_after_this</span> <span class="o">=</span> <span class="n">my_year</span> <span class="o">+</span> <span class="mi">1</span>
</span><span class='line'>  <span class="n">my_year_before_this</span> <span class="o">=</span> <span class="n">my_year</span> <span class="o">-</span> <span class="mi">1</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">render_to_response</span><span class="p">(</span><span class="s">&quot;cal_template.html&quot;</span><span class="p">,</span> <span class="p">{</span> <span class="s">&#39;readings_list&#39;</span><span class="p">:</span> <span class="n">my_reading_events</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;month&#39;</span><span class="p">:</span> <span class="n">my_month</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;month_name&#39;</span><span class="p">:</span> <span class="n">named_month</span><span class="p">(</span><span class="n">my_month</span><span class="p">),</span>
</span><span class='line'>                                                      <span class="s">&#39;year&#39;</span><span class="p">:</span> <span class="n">my_year</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;previous_month&#39;</span><span class="p">:</span> <span class="n">my_previous_month</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;previous_month_name&#39;</span><span class="p">:</span> <span class="n">named_month</span><span class="p">(</span><span class="n">my_previous_month</span><span class="p">),</span>
</span><span class='line'>                                                      <span class="s">&#39;previous_year&#39;</span><span class="p">:</span> <span class="n">my_previous_year</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;next_month&#39;</span><span class="p">:</span> <span class="n">my_next_month</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;next_month_name&#39;</span><span class="p">:</span> <span class="n">named_month</span><span class="p">(</span><span class="n">my_next_month</span><span class="p">),</span>
</span><span class='line'>                                                      <span class="s">&#39;next_year&#39;</span><span class="p">:</span> <span class="n">my_next_year</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;year_before_this&#39;</span><span class="p">:</span> <span class="n">my_year_before_this</span><span class="p">,</span>
</span><span class='line'>                                                      <span class="s">&#39;year_after_this&#39;</span><span class="p">:</span> <span class="n">my_year_after_this</span><span class="p">,</span>
</span><span class='line'>  <span class="p">},</span> <span class="n">context_instance</span><span class="o">=</span><span class="n">RequestContext</span><span class="p">(</span><span class="n">request</span><span class="p">))</span>
</span></code></pre></td></tr></table></div></figure>


<p>And finally, here&#8217;s the template where we load the template tag and employ it, passing the year, month, and list from the view (you would also want to write some control elements that use previous_year, previous_month, etc. to allow the user to change what the calendar displays, but because I want to wrap this up I&#8217;ll forgo writing that out):</p>

<figure class='code'><figcaption><span>Use template tag  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='python'><span class='line'><span class="p">{</span><span class="o">%</span> <span class="n">load</span> <span class="n">reading_tags</span> <span class="o">%</span><span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="o">&lt;</span><span class="n">div</span> <span class="nb">id</span><span class="o">=</span><span class="s">&quot;calendar&quot;</span><span class="o">&gt;</span>
</span><span class='line'>  <span class="p">{</span><span class="o">%</span> <span class="n">reading_calendar</span> <span class="n">year</span> <span class="n">month</span> <span class="n">reading_list</span> <span class="o">%</span><span class="p">}</span>
</span><span class='line'><span class="o">&lt;/</span><span class="n">div</span><span class="o">&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Hopefully that makes sense. Enjoy!</p>

<p><em>You can also see this code (made generic for any kind of event) <a href="http://djangosnippets.org/snippets/2464/">on django snippets</a>.</em></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Marshall, Barnard, Laurel, Marshall]]></title>
    <link href="http://williamjohnbert.com/2011/05/marshall-barnard-laurel-marshall/"/>
    <updated>2011-05-19T18:13:26-04:00</updated>
    <id>http://williamjohnbert.com/2011/05/marshall-barnard-laurel-marshall</id>
    <content type="html"><![CDATA[<p><a href="http://williamjohnbert.com/wp-content/uploads/2011/05/2.jpg"><img src="http://williamjohnbert.com/wp-content/uploads/2011/05/2.jpg" alt="" /></a><a href="http://williamjohnbert.com/wp-content/uploads/2011/05/3.jpg"><img src="http://williamjohnbert.com/wp-content/uploads/2011/05/3.jpg" alt="" /></a>
<a href="http://williamjohnbert.com/wp-content/uploads/2011/05/5.jpg"><img src="http://williamjohnbert.com/wp-content/uploads/2011/05/5.jpg" alt="" /></a>
<a href="http://williamjohnbert.com/wp-content/uploads/2011/05/4.jpg"><img src="http://williamjohnbert.com/wp-content/uploads/2011/05/4.jpg" alt="" /></a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Poetry for the President]]></title>
    <link href="http://williamjohnbert.com/2011/05/poetry-for-the-president/"/>
    <updated>2011-05-11T07:43:10-04:00</updated>
    <id>http://williamjohnbert.com/2011/05/poetry-for-the-president</id>
    <content type="html"><![CDATA[<p><a href="http://williamjohnbert.com/wp-content/uploads/2011/05/IMG_1361-1.jpg"><img src="http://williamjohnbert.com/wp-content/uploads/2011/05/IMG_1361-1.jpg" alt="" /></a>Since March, I&#8217;ve been working with DC students from several high schools, including Duke Ellington, Ballou, Wilson and Bell, in evening poetry workshops at <a href="http://www.826dc.org">826DC</a>. A bunch of us have been helping out—Mike Scalise, Adam Pelligrini, and Sally Keith (the last two being actual poets, while Mike and I, both prose writers, were faking it the whole time). And of course program director Mariam Al-Shawaf and 826DC Executive Director Joe Callahan did the thankless behind-the-scenes labor to make it all happen.</p>

<p>The students came to us talented and hard-working, and we just helped them along with workshops on poetic forms, poetic sound, and metaphor (this is the one I&#8217;m awkwardly teaching in the photo above), and by giving plenty of exercises and time to generate new material. We even had a guest visit from the amazing <a href="http://www.poetryfoundation.org/bio/carolyn-forche">Carolyn Forche</a>.</p>

<p>All this <a href="http://english.georgetown.edu/217153.html">culminates today</a> in a <a href="http://www.826national.org/article/405/826dc-and-826chi-students-write-poetry-at-the-white-house">workshop at the White House</a>, hosted by the Obamas, where the students will work with the likes of Billy Collins, Common, Rita Dove, Aimee Mann, Jill Scott and several other amazing poets to hone their craft even further. Very, very cool. Congrats to 826DC and especially to the students!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Spring, spring, spring]]></title>
    <link href="http://williamjohnbert.com/2011/05/spring-spring-spring/"/>
    <updated>2011-05-09T05:59:26-04:00</updated>
    <id>http://williamjohnbert.com/2011/05/spring-spring-spring</id>
    <content type="html"><![CDATA[<p><a href="http://williamjohnbert.com/wp-content/uploads/2011/05/jbb_cr2.jpg"><img src="http://williamjohnbert.com/wp-content/uploads/2011/05/jbb_cr2.jpg" alt="" /></a>Spring is the rarest of seasons in DC, but it looks like we get a few days of it this week. This could not be happening at a better time. The protracted move from Columbia Heights/Baltimore/Tucson to Capitol Hill is over. The <a href="http://www.callandresponsedc.org/">art show</a> has wrapped. Work is still way busy, but next week I head to North Carolina for some writing time in the mountains at <a href="http://doebranchink.org/">Doe Branch Ink</a>&#8211;the ideal vacation.</p>

<p>Craig Nova is the resident author for this session at DBI, and I&#8217;m looking forward to reading his novel <em>The Good Son</em>, starting on the commute home this afternoon. It&#8217;ll be good to dive back into reading and writing, which have taken a back seat so far this season. I did have the honor of getting tapped for <a href="http://dcarts.dc.gov/DC/DCARTS/Events/Annual+Programming/Annual+Programming#4">a Larry Neal award</a>, 2nd place for adult fiction  (the non-euphemistic kind), for a story I began back in Arizona but kept revisiting up until last fall. That just made me want to sit down and get back to writing, drafting, and revising even more! I don&#8217;t have any illusions that late spring and summer will be slow, but few things suck up time more than moving, and with a good solid week to get jump-started, I&#8217;m feeling optimistic.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[New story, and other updates]]></title>
    <link href="http://williamjohnbert.com/2011/03/new-story-in-anomalous-press/"/>
    <updated>2011-03-23T07:35:36-04:00</updated>
    <id>http://williamjohnbert.com/2011/03/new-story-in-anomalous-press</id>
    <content type="html"><![CDATA[<p><a href="http://williamjohnbert.com/wp-content/uploads/2011/03/anomalous1.png"><img src="http://williamjohnbert.com/wp-content/uploads/2011/03/anomalous1.png" alt="Anomalous Press #1" /></a>I&#8217;m really thrilled to have a story, <a href="http://www.anomalouspress.org/current/21.bert.winner.php">&#8220;Winner,&#8221;</a> in the very first issue of Anomalous Press. It was released on the Ides of March, so I&#8217;m a bit tardy announcing it here—it&#8217;s been a busy March so far.</p>

<p>The issue includes work from many better writers than me, including <a href="http://www.anomalouspress.org/current/25.ayala.winter.php">a poem</a> and <a href="http://www.anomalouspress.org/current/26.ayala.vision.php">two translations</a> from my friend Naomi Ayala. It was Naomi who suggested I submit to Anomalous. In this way and many others, she&#8217;s been a great friend and supporter of my writing, and I hope someday to be able to pay her back. You can catch another poem of hers when <a href="http://www.callandresponsedc.org/">Call + Response: Textures</a> opens on April 16. (More on that tomorrow.)</p>

<p>Anomalous Press #1 is available for download as a PDF, but only if you <a href="http://www.paywithatweet.com/">pay with a tweet</a>. Neat concept. Attention as currency. And from a technical standpoint, I&#8217;m interested in how they integrated with <a href="http://dev.twitter.com/">Twitter using OAuth</a>—I want to do a similar thing with the reading series web app (Readsr/Readthing/whatever) I&#8217;m working on: tweet whenever a reading series is updated. So I&#8217;ll be looking into this soon.</p>

<p>First, though, I plan to deploy an alpha version of the site this weekend. I&#8217;ve been reading up on <a href="http://pypi.python.org/pypi/virtualenv">virtualenv</a>, <a href="http://pypi.python.org/pypi/pip">pip</a>, <a href="http://fabfile.org/">fabric</a>, and <a href="http://git-scm.com/">git</a>, trying to figure out how to deploy the right way&#8211;with automated version control and dependency isolation. This part, the admin stuff, is as complicated as any coding problem I&#8217;ve faced. Looking forward to tackling it in a marathon session on Saturday!</p>
]]></content>
  </entry>
  
</feed>
