

<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <atom:link href="/rss.xml" rel="self"
            type="application/rss+xml" />
        <title></title>
        <link>/rss.xml</link>
        <language>en-us</language>
        <pubDate>Sat, 22 Dec 2012 18:30:49 GMT</pubDate>
        <docs>http://blogs.law.harvard.edu/tech/rss</docs>
        
            
                <item>
                    <title>Lessons</title>
                    <link>/entries/lessons.html</link>
                    <pubDate>Fri, 21 Sep 2012 15:09:00 GMT</pubDate>
                    <description>
                        &lt;p&gt;I have a problem. It&#39;s not an unusual problem, and I wish to tackle it
precisely because of its ubiquity. The problem is, roughly, this: I have a
large chunk of code which does some blocking work. I wish to augment this code
so that it can be used with &lt;a class=&#34;reference external&#34; href=&#34;http://twistedmatrix.com/&#34;&gt;Twisted&lt;/a&gt;, and I wish to do so in a way that
satisfies the following conditions:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class=&#34;arabic simple&#34;&gt;
&lt;li&gt;A minimum of source code is changed.&lt;/li&gt;
&lt;li&gt;There are no deep hacks which are not trivial to explain when taken one by
one.&lt;/li&gt;
&lt;li&gt;The caller may use either the Twisted or non-Twisted interfaces at their
leisure.&lt;/li&gt;
&lt;li&gt;The difference between the Twisted and non-Twisted results at all of the
borders of the module should be undone by &lt;a class=&#34;reference external&#34; href=&#34;http://twistedmatrix.com/documents/current/api/twisted.internet.defer.maybeDeferred.html&#34;&gt;maybeDeferred&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;These conditions should not be difficult to achieve and yet they seem to
constantly stymie many would-be IRC bot authors. I&#39;m going to see if I can
improve on this with a couple lessons from Haskell.&lt;/p&gt;
&lt;p&gt;So, first, let&#39;s consider why we cannot simply remove data from Twisted
interfaces. It&#39;s elementary: &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; computations cannot have their
results accessed directly. Instead, actions have to be lifted up into a
&lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt;, which will run the action when it is ready.&lt;/p&gt;
&lt;p&gt;To a Haskell programmer, this sounds quite a bit like how &lt;tt class=&#34;docutils literal&#34;&gt;IO&lt;/tt&gt; behaves, and
indeed, &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; is a &lt;tt class=&#34;docutils literal&#34;&gt;Functor&lt;/tt&gt; (and &lt;tt class=&#34;docutils literal&#34;&gt;Monad&lt;/tt&gt;) that cannot be
unwrapped. So, with this in mind, let&#39;s look a bit at what kind of interface
this would be in Haskell. First, let&#39;s consider the type of our computation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;nf&#34;&gt;computation&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That is, we are taking some data of type &lt;tt class=&#34;docutils literal&#34;&gt;a&lt;/tt&gt; and returning some data of type
&lt;tt class=&#34;docutils literal&#34;&gt;b&lt;/tt&gt;. The trick here, for those of you not well-versed in Haskell, is that
&lt;tt class=&#34;docutils literal&#34;&gt;computation&lt;/tt&gt; may not do &lt;strong&gt;anything&lt;/strong&gt; outside of these types; it cannot
perform I/O or have any impure effects. (Okay, fine, I mean, you can perform
horrid hacks to do those things, but remember our rules: No deep hackery
here.)&lt;/p&gt;
&lt;p&gt;Now, let&#39;s consider the type of the Twisted-style computation.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;nf&#34;&gt;deferredComputation&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Deferred&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Deferred&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;That is, we&#39;re taking a &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; containing data of type &lt;tt class=&#34;docutils literal&#34;&gt;a&lt;/tt&gt;, and
returning a &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; with data of type &lt;tt class=&#34;docutils literal&#34;&gt;b&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Now, here&#39;s the fun part. We want to generate &lt;tt class=&#34;docutils literal&#34;&gt;deferredComputation&lt;/tt&gt; from
&lt;tt class=&#34;docutils literal&#34;&gt;computation&lt;/tt&gt;, to achieve code reuse. How? Well, let&#39;s use &lt;tt class=&#34;docutils literal&#34;&gt;fmap&lt;/tt&gt;, since
&lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; is a &lt;tt class=&#34;docutils literal&#34;&gt;Functor&lt;/tt&gt;!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;nf&#34;&gt;computation&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;fmap&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Functor&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;

&lt;span class=&#34;nf&#34;&gt;deferredComputation&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Deferred&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Deferred&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;deferredComputation&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fmap&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;computation&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Hey hey! Pretty cool, right? This might seem super-obvious to people with lots
of Haskell experience, but I think it&#39;s still worth repeating since not
everybody has done this sort of thing before.&lt;/p&gt;
&lt;p&gt;And now we return to the land of Python. Python-land. It&#39;s time to construct
this thing in Python, as well. So, how do we lift a function up into a
&lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; in Python?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;computation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;deferredComputation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addCallback&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;computation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Think about this for a second. Remember, &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; objects carry state
around with them, so we need this &amp;quot;impure&amp;quot; sort of approach, which is really
not actually impure but just object-at-a-time. If you&#39;re unsure of exactly
what this snippet&#39;s doing, go through it one bit at a time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol class=&#34;arabic simple&#34;&gt;
&lt;li&gt;Take a &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; which will fire with a value of type &lt;tt class=&#34;docutils literal&#34;&gt;a&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Append a callback which transforms &lt;tt class=&#34;docutils literal&#34;&gt;a&lt;/tt&gt; into &lt;tt class=&#34;docutils literal&#34;&gt;b&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Return a &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; which will fire with a value of type &lt;tt class=&#34;docutils literal&#34;&gt;b&lt;/tt&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, let&#39;s make this concrete with an example. Let&#39;s say that we&#39;ve got a
system that has two implementations of a client, one which is synchronous, and
one which is asynchronous. We&#39;ve isolated and split out these clients such
that they have exactly the same setup functions, and they return exactly the
same data, with one single difference: One client is blocking and returns the
data, and the other client is non-blocking and returns a &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt; which
will fire with the data. This is &lt;em&gt;exactly&lt;/em&gt; the difference that
&lt;tt class=&#34;docutils literal&#34;&gt;maybeDeferred&lt;/tt&gt; can paper over. We&#39;ve got all of the code set up just the
way we want it, according to those conditions I listed earlier.&lt;/p&gt;
&lt;p&gt;But! These clients only make up a couple dozen lines of code. There are still
thousands of lines of code that only work with the synchronous client. How do
we make them work with Twisted without losing our synchronous abilities?&lt;/p&gt;
&lt;p&gt;Let&#39;s create some helper which will &lt;strong&gt;apply&lt;/strong&gt; the computation to the data.
This helper will come with the client and will be tailored to the client&#39;s
output. For unlifted non-Twisted data, this is simply the classic builtin
&lt;tt class=&#34;docutils literal&#34;&gt;apply&lt;/tt&gt;, known to Haskellers as &lt;tt class=&#34;docutils literal&#34;&gt;($)&lt;/tt&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;$&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;
&lt;span class=&#34;nf&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;$&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;apply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that my &lt;tt class=&#34;docutils literal&#34;&gt;apply&lt;/tt&gt; is &lt;em&gt;not&lt;/em&gt; the Python &lt;tt class=&#34;docutils literal&#34;&gt;apply&lt;/tt&gt; builtin function, which
does a slightly different thing if its argument is iterable.&lt;/p&gt;
&lt;p&gt;And for the &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt;-handling case, let&#39;s create a slightly more
interesting applier which will continue to move data through the &lt;tt class=&#34;docutils literal&#34;&gt;Deferred&lt;/tt&gt;.
We already wrote this above, actually, and in Haskell, it would be &lt;tt class=&#34;docutils literal&#34;&gt;fmap&lt;/tt&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;nf&#34;&gt;fmap&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;::&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;Functor&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;b&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;deferredApply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addCallback&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now we&#39;re ready to put everything together! Here&#39;s a small skeleton:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;SyncClient&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;object&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;applier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;sync_library_call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;AsyncClient&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;object&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;nd&#34;&gt;@staticmethod&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;applier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;addCallback&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;deferred&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;async_library_call&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;computation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;transform&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;poke&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;request_and_compute&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;resource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;resource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;client&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;applier&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;computation&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Look at &lt;tt class=&#34;docutils literal&#34;&gt;request_and_compute&lt;/tt&gt;. It has no idea whether it&#39;s handling
synchronous or asynchronous data, and it doesn&#39;t really care; it asks the
client to actually apply the computation to the data. And the computation
itself is totally unaware of things going on around it. It doesn&#39;t even have
to be pure; it could do all kinds of side effects with that data. The only
requirement for the computation is that it must remember to return the data so
that subsequent computations can access it.&lt;/p&gt;
&lt;p&gt;This is the approach I&#39;m taking in a new library I&#39;m hacking together for
&lt;a class=&#34;reference external&#34; href=&#34;https://code.google.com/p/ganeti/&#34;&gt;Ganeti&lt;/a&gt;, called &lt;a class=&#34;reference external&#34; href=&#34;https://github.com/MostAwesomeDude/gentleman&#34;&gt;Gentleman&lt;/a&gt;. I think it&#39;ll work out well.&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/lessons.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Be Prepared</title>
                    <link>/entries/be-prepared.html</link>
                    <pubDate>Wed, 15 Feb 2012 20:34:00 GMT</pubDate>
                    <description>
                        &lt;p&gt;I like &lt;a class=&#34;reference external&#34; href=&#34;http://flask.pocoo.org/&#34;&gt;Flask&lt;/a&gt;. No, really, I do. Yesterday, during a lightning talk, I
claimed that I love it, and if I don&#39;t love it, then at least I love the form
and function of it. I wouldn&#39;t marry it, since I don&#39;t think being married to
a microframework for Web applications would provide any tax benefits. Maybe
I&#39;m getting off-topic?&lt;/p&gt;
&lt;p&gt;Flask is built on &lt;a class=&#34;reference external&#34; href=&#34;http://werkzeug.pocoo.org/&#34;&gt;Werkzeug&lt;/a&gt;, and directly uses Werkzeug routes for view
lookup and URL building. As a result, anything that can be done to Werkzeug
can be done to Flask. A little-known ability of Werkzeug is the ability to add
new &lt;strong&gt;URL converters&lt;/strong&gt;. An example and explanation is provided in the
&lt;a class=&#34;reference external&#34; href=&#34;http://werkzeug.pocoo.org/docs/routing/#custom-converters&#34;&gt;Werkzeug documentation on converters&lt;/a&gt;. I decided to build some cool
converters which would automate some of the work I have to do when working
with certain objects.&lt;/p&gt;
&lt;p&gt;Without further ado, I would like to present &lt;tt class=&#34;docutils literal&#34;&gt;ModelConverter&lt;/tt&gt;, a class which
can convert a segment of a URL representing a text field on a model into an
instance of that model, and vice versa.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;__future__&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;with_statement&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;werkzeug.routing&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;BaseConverter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ValidationError&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;sqlalchemy.orm.exc&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MultipleResultsFound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NoResultFound&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;ModelConverter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;BaseConverter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;sd&#34;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&#34;sd&#34;&gt;    Converts a URL segment to and from a SQLAlchemy model.&lt;/span&gt;

&lt;span class=&#34;sd&#34;&gt;    Rather than use an initializer, this class should be subclassed and&lt;/span&gt;
&lt;span class=&#34;sd&#34;&gt;    have the `model` and `field` class attributes filled in. `model` is&lt;/span&gt;
&lt;span class=&#34;sd&#34;&gt;    the Flask-SQLAlchemy model to use for queries, and `field` is the&lt;/span&gt;
&lt;span class=&#34;sd&#34;&gt;    field on the model to use for lookups.&lt;/span&gt;

&lt;span class=&#34;sd&#34;&gt;    The field to use should be Unicode or bytes.&lt;/span&gt;
&lt;span class=&#34;sd&#34;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_python&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;try&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;test_request_context&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
                &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;query&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter_by&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;**&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;field&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;one&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;except&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MultipleResultsFound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NoResultFound&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;raise&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ValidationError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;obj&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;to_url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;getattr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;value&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;field&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This particular flavor uses an inheritance-based approach in order to avoid
clobbering &lt;tt class=&#34;docutils literal&#34;&gt;BaseConverter&lt;/tt&gt;&#39;s initializer, but a compositional approach works
too. A &lt;tt class=&#34;docutils literal&#34;&gt;make_model_converter&lt;/tt&gt; convenience method can provide the glue needed
to specialize the converter. To apply it to the Flask application, merely
modify the URL map after application creation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;converters&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_model_converter&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;models&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Character&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Flask&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;__name__&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;url_map&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;converters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;character&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;make_model_converter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;app&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
    &lt;span class=&#34;s&#34;&gt;&amp;quot;slug&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now you can create cool things along the lines of:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;nd&#34;&gt;@app.route&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;/&amp;lt;character:c&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;character&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;render_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;character.html&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;There is one caveat with this technique: the model instances retrieved this
way will be detached from SQLAlchemy and the current session will not know
about them. If you need to look up any lazily-loaded data on the models, you
will need to add them to the current session first. For example, assuming
&lt;tt class=&#34;docutils literal&#34;&gt;Character.friends&lt;/tt&gt; is a lazily-loaded one-to-many mapping:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;nd&#34;&gt;@app.route&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;/&amp;lt;character:c&amp;gt;/friends&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;character_and_friends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
    &lt;span class=&#34;n&#34;&gt;db&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;session&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;add&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;render_template&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;friends.html&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;friends&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;friends&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Today&#39;s snippets are all real-world snippets from &lt;a class=&#34;reference external&#34; href=&#34;https://github.com/MostAwesomeDude/dcon&#34;&gt;DCoN&lt;/a&gt;, and can be seen in
the &lt;a class=&#34;reference external&#34; href=&#34;https://github.com/MostAwesomeDude/dcon/blob/master/newrem/converters.py&#34;&gt;converters.py&lt;/a&gt; and &lt;a class=&#34;reference external&#34; href=&#34;https://github.com/MostAwesomeDude/dcon/blob/master/newrem/views.py&#34;&gt;views.py&lt;/a&gt; source files.&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/be-prepared.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Japanese Standing Cat</title>
                    <link>/entries/japanese-standing-cat.html</link>
                    <pubDate>Tue, 31 Jan 2012 11:42:00 GMT</pubDate>
                    <description>
                        &lt;p&gt;I recently purchased and installed a standing desk. While I normally don&#39;t
blog about things in my personal life, I figured that this was permissible
since it directly affects my ability to write code.&lt;/p&gt;
&lt;a class=&#34;reference external image-reference&#34; href=&#34;images/desk.jpg&#34;&gt;&lt;img alt=&#34;My standing desk, fully loaded&#34; class=&#34;align-right&#34; src=&#34;images/desk-thumb.jpg&#34; /&gt;&lt;/a&gt;
&lt;p&gt;This standing desk is a &lt;a class=&#34;reference external&#34; href=&#34;http://www.ikea.com/us/en/catalog/products/60115989/&#34;&gt;Fredrik&lt;/a&gt; &amp;quot;computer work station,&amp;quot; but let&#39;s be
honest, here: it&#39;s a standing desk. It&#39;s pretty sturdy and removes the need to
hack together various Ikea desks to produce reasonably-scaled tabletops.
Pictured here is my desk, in its natural habitat. My workstation and
hacked-apart AGP box both have their own monitor, and there is plenty of
tabletop room for anything I need to have at my hands.&lt;/p&gt;
&lt;p&gt;For those in the audience who aren&#39;t yet aware of standing desks, and don&#39;t
want to read &lt;a class=&#34;reference external&#34; href=&#34;https://en.wikipedia.org/wiki/Standing_desk&#34;&gt;Wikipedia on standing desks&lt;/a&gt;, here are the abridged notes:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class=&#34;simple&#34;&gt;
&lt;li&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;Reduces back stress and pain after a few months&lt;/li&gt;
&lt;li&gt;Reduces risk of &lt;a class=&#34;reference external&#34; href=&#34;https://en.wikipedia.org/wiki/DVT&#34;&gt;DVT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;When monitors are elevated, reduces neck stress and pain&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;Slightly more expensive than sitting desks&lt;/li&gt;
&lt;li&gt;Hard to find&lt;/li&gt;
&lt;li&gt;Causes foot and ankle stress for the first few weeks&lt;/li&gt;
&lt;li&gt;Turns one into a hipster programmer&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, on the bright side, this desk has definitely improved my back pain. But,
if I start writing &lt;a class=&#34;reference external&#34; href=&#34;http://nodejs.org/&#34;&gt;Node.js&lt;/a&gt; code soon, we&#39;ll all know who to blame.&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/japanese-standing-cat.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>A Little Bit is Better Than Nada</title>
                    <link>/entries/a-little-bit-is-better-than-nada.html</link>
                    <pubDate>Sun, 22 Jan 2012 12:00:00 GMT</pubDate>
                    <description>
                        &lt;p&gt;It is a running joke in the &lt;a class=&#34;reference external&#34; href=&#34;http://www.x.org/&#34;&gt;X.Org&lt;/a&gt; community that X12 development will
commence as soon as all of the X11 bugs in the &lt;a class=&#34;reference external&#34; href=&#34;http://bugs.freedesktop.org/&#34;&gt;FreeDesktop.org bug tracker&lt;/a&gt;
have been closed. When I first heard this, my reaction was, of course,
&amp;quot;Challenge accepted!&amp;quot; But where to start?&lt;/p&gt;
&lt;p&gt;There were about 10,000 bugs open on the tracker at that point, a few years
ago. We&#39;re definitely improving; there are about 9180 bugs open (at the time
of writing) which could be considered relevant to any kind of desktop
development. Many of those don&#39;t belong to anything in X11, but assuming they
did...&lt;/p&gt;
&lt;p&gt;Pretend that all of the card-carrying members of X.Org closed 92 bugs. That
would be 1% per person. We could be done with X11! So, during XDC 2011, I
pulled out my netbook, and started closing bugs. I picked, as my targets,
things that nobody would miss, like Xprint.&lt;/p&gt;
&lt;p&gt;I closed some Xprint-related bugs, before simply shuttering everything in the
Xprint product. I also picked up a couple of stray bugs. Finally, with
maintainer permission, I closed everything still assigned to xf86-video-nv.&lt;/p&gt;
&lt;p&gt;The results:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class=&#34;simple&#34;&gt;
&lt;li&gt;24 Xprint-related bugs&lt;/li&gt;
&lt;li&gt;37 bugs in Product: xprint&lt;/li&gt;
&lt;li&gt;42 bugs in Component: driver/nv&lt;/li&gt;
&lt;li&gt;37 bugs in Component: driver/nVidia (open)&lt;/li&gt;
&lt;li&gt;#9455, #28657, #29832, #30129&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;A total of 144 bugs. We can do this, guys!&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/a-little-bit-is-better-than-nada.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Secrets</title>
                    <link>/entries/secrets.html</link>
                    <pubDate>Tue, 29 Nov 2011 17:03:00 GMT</pubDate>
                    <description>
                        &lt;p&gt;After accidentally hitting yet another window manager key combination this
morning, I finally was fed up, and went off to read &lt;tt class=&#34;docutils literal&#34;&gt;&lt;span class=&#34;pre&#34;&gt;chromeos-wm&lt;/span&gt;&lt;/tt&gt; source
code to discover all of the key bindings. Here&#39;s the complete list:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class=&#34;simple&#34;&gt;
&lt;li&gt;Ctrl-F5: Take fullscreen screenshot&lt;/li&gt;
&lt;li&gt;Ctrl-Shift-F5, Print Screen: Take region screenshot&lt;/li&gt;
&lt;li&gt;Alt-Tab: Cycle windows forward&lt;/li&gt;
&lt;li&gt;Alt-Shift-Tab: Cycle windows backwards&lt;/li&gt;
&lt;li&gt;Alt-1 through Alt-8: Go to window 1 through 8, 1-indexed&lt;/li&gt;
&lt;li&gt;Alt-9: Go to the last window&lt;/li&gt;
&lt;li&gt;Ctrl-Alt-t: Create a new shell window&lt;/li&gt;
&lt;li&gt;Ctrl-Shift-W: Kill the current window&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;These are only available in overlapping-window mode, which appears to be the
default on at least Samsung Series 5 Chromebooks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class=&#34;simple&#34;&gt;
&lt;li&gt;F5: Toggle overlapping-window mode&lt;/li&gt;
&lt;li&gt;Alt-Comma: Expand current window&lt;/li&gt;
&lt;li&gt;Alt-Period: Shrink current window&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

                    </description>
                    <guid>
                        /entries/secrets.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Poison Was the Cure</title>
                    <link>/entries/poison-was-the-cure.html</link>
                    <pubDate>Mon, 03 Oct 2011 10:16:59 GMT</pubDate>
                    <description>
                        &lt;p&gt;&lt;a class=&#34;reference external&#34; href=&#34;http://glyph.twistedmatrix.com/&#34;&gt;glyph&lt;/a&gt; and I met for the first time a few weeks ago, and ever since, he&#39;s been
asking me to do things. Write code, review patches, write blog posts, that
kind of thing. Being the lazy person I am, I&#39;m not really up-front or speedy
about doing things outside of my habitual box. Thankfully, I got inspired by a
troll.&lt;/p&gt;
&lt;p&gt;Everybody&#39;s read Ted Dziuba&#39;s &lt;a class=&#34;reference external&#34; href=&#34;http://teddziuba.com/2011/10/node-js-is-cancer.html&#34;&gt;fantastic anti-Node troll&lt;/a&gt;, right? It&#39;s good
food for thought, even if it is a little bit belligerent. I wanted to
demonstrate that &lt;a class=&#34;reference external&#34; href=&#34;http://twistedmatrix.com/&#34;&gt;Twisted&lt;/a&gt; doesn&#39;t have the same problems as Node. I also
wanted to write a small application for &lt;a class=&#34;reference external&#34; href=&#34;http://heroku.com/&#34;&gt;Heroku&lt;/a&gt;, because I participated in
their Python beta and figured out how to run Twisted applications on their
platform.&lt;/p&gt;
&lt;p&gt;So, I wrote a tiny application that does a few things. First, it runs on
Heroku. It includes the Procfile magic for running on Heroku correctly, and
only depends on Twisted. Second, it calculates Fibonacci numbers. The idiom
that I chose to implement involves not caching the numbers, and instead using
threads to do background work. I was going to do something highly idiomatic
and Twisted-like, such as setting a timer and coming back to do the work
later, but I wanted to show off a feature of Twisted which is completely
missing from Node: The ability to write threaded code without leaving your
language.&lt;/p&gt;
&lt;p&gt;That&#39;s right, &lt;strong&gt;Node.js does not have the ability to host multiple threads in
JavaScript&lt;/strong&gt;. (Correct me if I&#39;m wrong, but after a half-hour of research and
an &lt;a class=&#34;reference external&#34; href=&#34;http://news.ycombinator.com/item?id=3063157&#34;&gt;assertion I made on Hacker News&lt;/a&gt; which went unchallenged, I&#39;m pretty sure
that this is the case.) Why? I don&#39;t know. Possibly because Node&#39;s tied to
V8, which is very shiny but certainly not as cool as the dominant Python
implementations, like &lt;a class=&#34;reference external&#34; href=&#34;http://python.org/&#34;&gt;CPython&lt;/a&gt; or &lt;a class=&#34;reference external&#34; href=&#34;http://pypy.org/&#34;&gt;PyPy&lt;/a&gt;. Now, make no mistake, many Pythons
have GILs or fine-grained locks, which can slow down threaded code, but Node
can&#39;t even attempt to thread off its CPU-bound long-running computations, and
I think that&#39;s an important ability to have. And as a well-known
anti-threading advocate, when &lt;em&gt;I&lt;/em&gt; admit that threads have their uses, I hope
people notice.&lt;/p&gt;
&lt;p&gt;I also got very annoyed at everybody who felt that they were demonstrating the
benefits of Node by writing equivalent servers in Python using the standard
library. Python&#39;s built-in servers suck. They straight-up suck. Would you
deploy a web server written in pure JavaScript with only the standard library
shipped with all JavaScript implementations? Probably not! Just like one needs
Node to write those servers, Python developers use Twisted to provide that
functionality. Otherwise, you&#39;re deliberately crippling your examples in order
to skew impressions of Python. I&#39;m going to shame you here, because you should
know better. You should know about Twisted, if for no other reason than that
it is listed on the front page of &lt;a class=&#34;reference external&#34; href=&#34;http://nodejs.org/&#34;&gt;Node.js&lt;/a&gt;&#39;s homepage as one of the
inspirations for Node. No, really, go check. I&#39;ll wait here.&lt;/p&gt;
&lt;p&gt;The actual Heroku side of things is kind of boring. Heroku&#39;s Python support is
fantastic. Use the cedar stack when you create your app with &lt;tt class=&#34;docutils literal&#34;&gt;heroku
apps:create &lt;span class=&#34;pre&#34;&gt;--stack&lt;/span&gt; cedar&lt;/tt&gt; and put a line into your Procfile which passes the
&lt;tt class=&#34;docutils literal&#34;&gt;$PORT&lt;/tt&gt; shell variable into your app somehow. If you&#39;re deploying stock
Twisted Web, something like &lt;tt class=&#34;docutils literal&#34;&gt;bin/python ./twistd &lt;span class=&#34;pre&#34;&gt;-n&lt;/span&gt; web &lt;span class=&#34;pre&#34;&gt;--port=$PORT&lt;/span&gt;&lt;/tt&gt; is a
good starter. You can, of course, easily deploy WSGI apps on top of this using
&lt;tt class=&#34;docutils literal&#34;&gt;&lt;span class=&#34;pre&#34;&gt;--wsgi&lt;/span&gt;&lt;/tt&gt;. You &lt;em&gt;must not daemonize&lt;/em&gt; on Heroku. That&#39;s really about it; it&#39;s a
very straightforward platform which is easy to use and I&#39;m very impressed by
their work.&lt;/p&gt;
&lt;p&gt;I have an application running on Heroku right now. The link is currently
&lt;a class=&#34;reference external&#34; href=&#34;http://radiant-stone-8394.herokuapp.com/&#34;&gt;right here&lt;/a&gt; although it might be
taken down in a few months when I need to experiment more. I&#39;m a free
customer, you see, and I&#39;m not willing to pay a monthly fee just to prove a
point about people on the Internets. Anyway, the application does nothing
except check how many threads are running on the system, calculate a Fibonacci
number, and tell you how long the request took. It can do this for many
concurrent users; you might notice, if there are many active requests, that
the page will stop loading halfway through as your request to calculate a
Fibonacci number sits in line in a threadpool. Your actual browser connection
won&#39;t be dropped, though.&lt;/p&gt;
&lt;p&gt;The code is a demonstration of Heroku&#39;s cedar stack and a few fancier things
in Twisted Web, like the new templating system added in Twisted 11.0. You can
find it on Github; the repo is called &amp;quot;&lt;a class=&#34;reference external&#34; href=&#34;http://github.com/MostAwesomeDude/cancer&#34;&gt;cancer&lt;/a&gt;&amp;quot; for obvious reasons.&lt;/p&gt;
&lt;p&gt;Oh, and as a closer: Some people have complained heavily about the idiom that
was demonstrated at the end of Ted&#39;s rant. The reason that he posted that is
that JavaScript programmers, unlike Python programmers, never really got in
the habit of not using names which haven&#39;t been declared or defined. The idiom
in Python looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;my_var&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;is&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;None&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
    &lt;span class=&#34;o&#34;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We don&#39;t check to see if &lt;tt class=&#34;docutils literal&#34;&gt;my_var in locals()&lt;/tt&gt; or anything stupid like that,
because &lt;tt class=&#34;docutils literal&#34;&gt;my_var&lt;/tt&gt; should be easy to track and the line where it was defined
should be obvious. If it&#39;s not, you&#39;re writing bad code.&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/poison-was-the-cure.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Theme of DCoN</title>
                    <link>/entries/theme-of-dcon.html</link>
                    <pubDate>Sun, 04 Sep 2011 13:26:24 GMT</pubDate>
                    <description>
                        &lt;p&gt;Some of you may remember the &amp;quot;Release Date: 2011&amp;quot; meme which we&#39;ve been
spreading for the past two years. We are proud to announce an actual piece of
DCoN software, now available for your use.&lt;/p&gt;
&lt;p&gt;Presenting &lt;a class=&#34;reference external&#34; href=&#34;https://github.com/MostAwesomeDude/dcon&#34;&gt;DCoN&lt;/a&gt;, the Doubly-linked Comic ORM for Newrem. This is the new
webcomic management system powering &lt;a class=&#34;reference external&#34; href=&#34;http://newrem.com/&#34;&gt;Newrem&lt;/a&gt;. It&#39;s young, but already it&#39;s
powerful enough to fill the shoes it was designed to fill, and perhaps other
people will find it useful as well.&lt;/p&gt;
&lt;p&gt;We are releasing DCoN under the GPLv2, in accordance with obligations laid out
by one of the component libraries. We hope it will be instructive for others
looking to create or deploy webcomic management systems.&lt;/p&gt;
&lt;p&gt;Please note that this software is, as people often say in the business,
&amp;quot;brand-spankin&#39;-new,&amp;quot; so don&#39;t be surprised if there are still a few bugs left
to hammer out.&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/theme-of-dcon.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Nobody Gonna Take My Car</title>
                    <link>/entries/nobody-gonna-take-my-car.html</link>
                    <pubDate>Sat, 13 Aug 2011 15:22:29 GMT</pubDate>
                    <description>
                        &lt;p&gt;Hi! Just a quick status update on that crazy &lt;a class=&#34;reference external&#34; href=&#34;http://en.wikipedia.org/wiki/Chromebook&#34;&gt;Chromebook&lt;/a&gt; of mine.&lt;/p&gt;
&lt;p&gt;To get VBA-M to work, use the GTK+ frontend by emerging with
&lt;tt class=&#34;docutils literal&#34;&gt;&lt;span class=&#34;pre&#34;&gt;USE=&amp;quot;gtk&amp;quot;&lt;/span&gt;&lt;/tt&gt;. Set it however you like; I highly advise against setting
it globally, but if you have sgt-puzzles installed, you will already have
GTK+. Afterwards, you will have a shiny new &lt;tt class=&#34;docutils literal&#34;&gt;gvbam&lt;/tt&gt; executable, ready
to use.&lt;/p&gt;
&lt;p&gt;While ZSNES might be very unhappy, &lt;a class=&#34;reference external&#34; href=&#34;http://www.snes9x.com/&#34;&gt;Snes9x&lt;/a&gt; can correctly accept input. Well,
to a point, at least; sound output and screen scaling appear to be broken.
More research is needed.&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/nobody-gonna-take-my-car.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Highway Star</title>
                    <link>/entries/highway-star.html</link>
                    <pubDate>Tue, 09 Aug 2011 02:03:29 GMT</pubDate>
                    <description>
                        &lt;p&gt;I have a &lt;a class=&#34;reference external&#34; href=&#34;http://en.wikipedia.org/wiki/Chromebook&#34;&gt;Chromebook&lt;/a&gt;. Specifically, a Samsung Series 5, courtesy of &lt;a class=&#34;reference external&#34; href=&#34;http://google.com/&#34;&gt;Google&lt;/a&gt;.
It&#39;s pretty snazzy, but what&#39;s really great is that the &amp;quot;Chrome OS&amp;quot; which it
comes with is actually a modified &lt;a class=&#34;reference external&#34; href=&#34;http://www.gentoo.org/&#34;&gt;Gentoo Linux&lt;/a&gt;. Cool, right?
Unfortunately, the Chromebook is a bit too hobbled for generic Gentoo usage,
but I will outline the steps I have taken towards getting mine to a point
where I&#39;m happy with it.&lt;/p&gt;
&lt;p&gt;When modding hardware, especially hardware over which one has limited control,
it&#39;s good to set a goal, so I&#39;ll outline my goal in terms of what I usually do
on traveling laptops: Games and music. Since there&#39;s usually a pretty heavy
limit on disk space, but plenty of bandwidth, I want to be able to access some
kind of music stream, and as far as games, I&#39;ll go with a selection of small
puzzles as well as classic emulators. In particular, I want to have &lt;a class=&#34;reference external&#34; href=&#34;https://github.com/PromyLOPh/pianobar&#34;&gt;Pianobar&lt;/a&gt;
(media-sound/pianobar), &lt;a class=&#34;reference external&#34; href=&#34;http://www.chiark.greenend.org.uk/~sgtatham/puzzles/&#34;&gt;Simon Tatham&#39;s Puzzles&lt;/a&gt; (games-puzzle/sgt-puzzles),
and either &lt;a class=&#34;reference external&#34; href=&#34;http://vba-m.com/&#34;&gt;VBA-M&lt;/a&gt; (games-emulation/vbam) or &lt;a class=&#34;reference external&#34; href=&#34;http://zsnes.com/&#34;&gt;ZSNES&lt;/a&gt; (games-emulation/zsnes).&lt;/p&gt;
&lt;p&gt;First things first: Let&#39;s get access to the shell. Two keyboard commands to
know (which have no mouse equivalents!) are the classic Alt+Tab, for switching
between windows, as well as Alt+Shift+Tab for going through the window list
backwards, and also the common Ctrl+Alt+T, which spawns a shell. On a
Chromebook, the shell provided by default is &amp;quot;crosh&amp;quot;, a remarkably useless
shell mostly provided for diagnostics. Crosh has a secret command, &amp;quot;shell&amp;quot;,
which spawns a real shell, bash! However, we can&#39;t get to it until &lt;a class=&#34;reference external&#34; href=&#34;http://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices/samsung-series-5-chromebook&#34;&gt;Developer
Mode&lt;/a&gt; has been enabled. After Developer Mode is enabled, crosh will now
permit us to get a real shell, and the real fun can begin.&lt;/p&gt;
&lt;p&gt;As a user on the filesystem, we are always under the login &amp;quot;chronos&amp;quot;. We can
sudo freely and without limit; invocations like &lt;tt class=&#34;docutils literal&#34;&gt;sudo &lt;span class=&#34;pre&#34;&gt;-i&lt;/span&gt;&lt;/tt&gt; to gain root shell
access work as expected. Let&#39;s take a look at what&#39;s in the filesystem at the
moment.&lt;/p&gt;
&lt;p&gt;(Aside: If you just want to know how I got stuff working on my Chromebook,
skip the next few paragraphs; I&#39;m going to talk about my though processes and
the current state of what I know about the machine. Interesting stuff,
perhaps, but not really directly relevant to getting up and running.)&lt;/p&gt;
&lt;pre class=&#34;literal-block&#34;&gt;
chronos&amp;#64;localhost ~ $ mount
rootfs on / type rootfs (rw)
/dev/root on / type ext2 (ro,relatime)
devtmpfs on /dev type devtmpfs (rw,size=970408k,nr_inodes=242602,mode=755)
none on /proc type proc (rw,nosuid,nodev,noexec,relatime)
none on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
/tmp on /tmp type tmpfs (rw,nosuid,nodev,noexec,relatime)
udev on /dev type tmpfs (rw,nosuid,noexec,relatime,mode=755)
shmfs on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime)
devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620)
/dev/sda1 on /mnt/stateful_partition type ext3
(rw,nosuid,nodev,noexec,relatime,errors=continue,commit=600,data=ordered)
/dev/sda1 on /var type ext3
(rw,nosuid,nodev,noexec,relatime,errors=continue,commit=600,data=ordered)
/dev/sda1 on /home type ext3
(rw,nosuid,nodev,noexec,relatime,errors=continue,commit=600,data=ordered)
varrun on /var/run type tmpfs (rw,nosuid,nodev,noexec,relatime,mode=755)
varlock on /var/lock type tmpfs (rw,nosuid,nodev,noexec,relatime)
/media on /media type tmpfs (rw,nosuid,nodev,noexec,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
cgroup on /tmp/cgroup/cpu type cgroup (rw,relatime,cpu)
/home/.shadow/d72e888592600e3025a778270172192458d0a039/vault on
/home/chronos/user type ecryptfs
(rw,nosuid,nodev,relatime,ecryptfs_sig=6c1fcef0779bc58d,ecryptfs_fnek_sig=997328e527b573bc,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_unlink_sigs)
chronos&amp;#64;localhost ~ $ df -h
Filesystem            Size  Used Avail Use% Mounted on
rootfs                837M  548M  290M  66% /
/dev/root             837M  548M  290M  66% /
devtmpfs              948M  472K  948M   1% /dev
/tmp                  948M   24M  925M   3% /tmp
udev                  948M  472K  948M   1% /dev
shmfs                 948M  256K  948M   1% /dev/shm
/dev/sda1              11G  3.4G  6.7G  34% /mnt/stateful_partition
/dev/sda1              11G  3.4G  6.7G  34% /var
/dev/sda1              11G  3.4G  6.7G  34% /home
varrun                948M   68K  948M   1% /var/run
varlock               948M     0  948M   0% /var/lock
/media                948M     0  948M   0% /media
/home/.shadow/d72e888592600e3025a778270172192458d0a039/vault
                       11G  3.4G  6.7G  34% /home/chronos/user
&lt;/pre&gt;
&lt;p&gt;What a list of mounts! I&#39;ll try to explain. The rootfs and kernel each live on
partitions not mounted during normal operation, and are generally reasonably
protected. Modifying them is beyond what I will discuss today, but rest
assured that they are there and modifiable if developer-mode BIOS is enabled.
(All the gory details are on the Chromium OS wiki, linked above.) If we want
to avoid making changes which can be easily wiped out, then we will have to
consider an alternative approach to modifying the rootfs. There is apparently
a way to cook an entirely-new Chromium OS image, but I&#39;m going to avoid that
for a pair of reasons:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class=&#34;simple&#34;&gt;
&lt;li&gt;The build process takes a fair amount of space and time&lt;/li&gt;
&lt;li&gt;The image has to be respun for every update&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;These two things wouldn&#39;t be that big of a deal, if I knew exactly what I
wanted ahead of time and didn&#39;t plan to update more than every three months or
so. However, knowing the speed of Gentoo, this isn&#39;t going to be reasonable.
Moreover, there are a few things missing from the Chrome OS rootfs: Portage
and a compiler, to say nothing of Python. There aren&#39;t even the tools for
bootstrapping a stage3. Also, look at how much space is allocated to the
default rootfs: 840MiB, nowhere near enough to get anywhere when it&#39;s already
two-thirds full. An alternate approach sounds better.&lt;/p&gt;
&lt;p&gt;Can&#39;t we just wipe the entire SSD and put a standard Gentoo install on it?
Well, no. There&#39;s a couple obstacles. First, how does one get into a live
Gentoo environment? We can&#39;t boot from USB or MMC/SD into a non-Chrome OS
environment, thanks to a verified bootloader. We can&#39;t access the deepest
bootloaders easily; while an EFI loader is shipped onboard, it appears to be
unused, and documentation points to a signed kernel loader being used instead.
This is frustrating, because it means that we have to use the same kind of
partitioning as the current system, and we have to sign our kernels. While the
tools are all there in the Chromium OS repositories, I didn&#39;t feel like going
through the ardour of figuring out how to put it all together and flashing my
device multiple times to get it all going. (I&#39;m lazy like that; if some
enterprising developer wants to do it, please, go ahead!) So, we&#39;ll stick to
userspace modifications.&lt;/p&gt;
&lt;p&gt;The next thing I noticed: chroot is available in the rootfs! This could get us
into a Gentoo environment! But what would we do in there? We can&#39;t install
things directly onto the rootfs or stateful partition, and we can&#39;t change the
partition table. Either one would wreck the Chrome OS boot pretty thoroughly.
But, we could always go the brutish, lazy route, and simply have a chroot
&lt;em&gt;in our home directory&lt;/em&gt;. Getting at our Portage and compiler would be
as easy as invoking chroot, and we could still have the rest of the system
(Chrome, WiFi manager, battery monitor, terminal emulator, window manager) at
our disposal. Excellent.&lt;/p&gt;
&lt;p&gt;How much disk space would this take? It sounds wasteful. As you may have
noticed from the above filesystem readout, though, it only adds about 2.8GiB
for an entire chroot with everything I like to have in my minimal Gentoo
systems. I&#39;m a bit of a pig, but even so, it&#39;s possible to have a very
slimmed-down chroot.&lt;/p&gt;
&lt;p&gt;So, let&#39;s get started. First, create your chroot directory in your home,
calling it &amp;quot;chroot&amp;quot; or something like that. You can go ahead and be root for
this. In fact, get comfortable being root; you will always be root in your
chroot. I mean, seriously, why not? There&#39;s all the traditional reasons to not
be root, but the Chrome OS is a brand-new world, a world where people can be
root inside a chroot inside a cryptfs inside a single-user system inside
&lt;strong&gt;the cloud&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You should have the &lt;a class=&#34;reference external&#34; href=&#34;http://www.gentoo.org/proj/en/base/x86/chroot.xml&#34;&gt;Gentoo Handbook&#39;s Chroot Guide&lt;/a&gt; open while you do this,
as what we are doing is quite similar. The one catch is that you &lt;em&gt;must&lt;/em&gt; be
root in order to create all the device nodes. Once your chroot is in place,
the following script will enter the chroot: &lt;a class=&#34;reference external&#34; href=&#34;https://gist.github.com/1128864&#34;&gt;https://gist.github.com/1128864&lt;/a&gt;
Just put it in your home directory, &lt;tt class=&#34;docutils literal&#34;&gt;chmod +x&lt;/tt&gt; it, and we&#39;re almost ready to
go!&lt;/p&gt;
&lt;p&gt;Oops, wait, what&#39;s with this cryptic &amp;quot;bad interpreter&amp;quot; error? For security
reasons, most filesystems are mounted noexec. Sadly, there&#39;s no good place to
put a shell script to turn it off, so I instead encourage you to memorize
&lt;tt class=&#34;docutils literal&#34;&gt;mount &lt;span class=&#34;pre&#34;&gt;-i&lt;/span&gt; &lt;span class=&#34;pre&#34;&gt;-o&lt;/span&gt; remount,exec ~&lt;/tt&gt;. It rolls right off the tongue! You only have
to do this once, at boot, but you can&#39;t put it in the rootfs without alerting
Chrome OS to our shenanigans. If Chrome OS gets ticked enough at our meddling,
it will destroy the entire stateful partition, including the chroot. (If you
want to keep your chroot on a USB drive or SD card, I would totally
understand!)&lt;/p&gt;
&lt;p&gt;There are a few more things required to get all of the things in the chroot
working. Presumably you will eventually want to run applications which talk to
the local X11 server; for that, you will need to add a single line to your
.bashrc inside the chroot:&lt;/p&gt;
&lt;pre class=&#34;literal-block&#34;&gt;
export XAUTHORITY=&amp;quot;/root/.Xauthority&amp;quot;
&lt;/pre&gt;
&lt;p&gt;So, now that we&#39;re inside our chroot, and have everything wired up, it&#39;s time
to start experimenting. I&#39;ve gone ahead and selected the following USE flags:&lt;/p&gt;
&lt;pre class=&#34;literal-block&#34;&gt;
USE=&amp;quot;X alsa ao mmx opengl sse sse2 sse3 -cups -xscreensaver&amp;quot;
&lt;/pre&gt;
&lt;p&gt;And here&#39;s the package list in my world file (/var/lib/portage/world):&lt;/p&gt;
&lt;pre class=&#34;literal-block&#34;&gt;
app-admin/localepurge
app-editors/vim
app-misc/screen
app-portage/eix
app-portage/genlop
app-portage/gentoolkit
app-portage/ufed
games-emulation/vbam
games-emulation/zsnes
games-puzzle/sgt-puzzles
media-sound/pianobar
net-im/pidgin
x11-apps/mesa-progs
x11-apps/xauth
x11-apps/xdpyinfo
x11-apps/xhost
&lt;/pre&gt;
&lt;p&gt;You may notice that I emerged things I don&#39;t technically need. This is because
I am a creature of habit, and several things nearly always make their way into
my list, like vim, eix, genlop, gentoolkit, and ufed. I emerged all of the X
and GL programs to help debug X issues; they are not necessary at all for you
as long as you have set up .Xauthority as I have.&lt;/p&gt;
&lt;p&gt;You may also notice that I grabbed localepurge. I highly recommend trimming
the fat from your chroot with localepurge; that and trimming the categories
from your Portage tree (do you really need &lt;tt class=&#34;docutils literal&#34;&gt;&lt;span class=&#34;pre&#34;&gt;sci-*&lt;/span&gt;&lt;/tt&gt;?) are going to save
around 500MiB if done zealously.&lt;/p&gt;
&lt;p&gt;With the current setup, pianobar Just Works. sgt-puzzles installs its binaries
as games, so you will have to make sure that, when chrooted, your user has the
games group set. This is the purpose of that mystical &lt;tt class=&#34;docutils literal&#34;&gt;&lt;span class=&#34;pre&#34;&gt;--groups=35&lt;/span&gt;&lt;/tt&gt; on the
chroot invocation -- 35 is the GID of the games group! This is definitely the
cleanest solution. With that added, sgt-puzzles works. Two of four.&lt;/p&gt;

                    </description>
                    <guid>
                        /entries/highway-star.html
                    </guid>
                </item>
            
        
            
                <item>
                    <title>Summertime</title>
                    <link>/entries/summertime.html</link>
                    <pubDate>Sun, 31 Jul 2011 23:47:12 GMT</pubDate>
                    <description>
                        &lt;p&gt;Some people use summer vacation to do useful things. I have been using my
summertime to demonstrate how awesome &lt;a class=&#34;reference external&#34; href=&#34;http://twistedmatrix.com/&#34;&gt;Twisted&lt;/a&gt; is.&lt;/p&gt;
&lt;p&gt;Here&#39;s a fun example: Take this &lt;a class=&#34;reference external&#34; href=&#34;http://toastdriven.com/blog/2011/jul/31/gevent-long-polling-you/&#34;&gt;basic long-polling example&lt;/a&gt;, in gevent, and
turn it into a Twisted-based server instead.&lt;/p&gt;
&lt;p&gt;First, let&#39;s look at the chunk of code that will communicate with the web
browser:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Pusher&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Resource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;isLeaf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;True&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;render_GET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connectTCP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;localhost&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6379&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;nd&#34;&gt;@d.addCallback&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;protocol&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;protocol&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;protocol&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subscribe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;messages&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4096&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;h1&amp;gt;Messages!&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NOT_DONE_YET&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Pretty nifty, right? This is a straightforward Twisted Web resource. It will
respond to GET requests by writing a small banner, &amp;quot;Messages!&amp;quot; and will leave
the connection open via &lt;tt class=&#34;docutils literal&#34;&gt;NOT_DONE_YET&lt;/tt&gt;. It also opens a connection to some
local server via the &lt;tt class=&#34;docutils literal&#34;&gt;cc&lt;/tt&gt; object, which I will explain momentarily.&lt;/p&gt;
&lt;p&gt;Now, let&#39;s look at the Redis client. This is my first time ever using Redis,
and also using txRedis, but I think I did alright.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Puller&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RedisSubscriber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;None&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;messageReceived&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;channel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;finished&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&amp;lt;div&amp;gt;Message on &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%s&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;: &amp;#39;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%s&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;
                &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;channel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;quot;quit&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;finish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;quot;quit&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;transport&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loseConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What does this do? I&#39;m not super-sure, but it&#39;s pretty self-explanatory,
thankfully. &lt;tt class=&#34;docutils literal&#34;&gt;RedisSubscriber&lt;/tt&gt; is a protocol which can subscribe to, and
publish, messages on Redis. Only the &lt;tt class=&#34;docutils literal&#34;&gt;messageReceived&lt;/tt&gt; method needs to be
overriden, and we just use it to send messages to that request object.&lt;/p&gt;
&lt;p&gt;Here&#39;s the part where people might get lost. How are these two objects hooked
up? Well, the answer (as some of you Twisted veterans may have guessed) is the
venerable &lt;a class=&#34;reference external&#34; href=&#34;http://twistedmatrix.com/documents/current/api/twisted.internet.protocol.ClientCreator.html&#34;&gt;ClientCreator&lt;/a&gt;, which creates instances of &lt;tt class=&#34;docutils literal&#34;&gt;Puller&lt;/tt&gt; for every
GET request made in the &lt;tt class=&#34;docutils literal&#34;&gt;Pusher&lt;/tt&gt;. Now, hopefully, the first half of
&lt;tt class=&#34;docutils literal&#34;&gt;render_GET()&lt;/tt&gt; makes more sense: The &lt;tt class=&#34;docutils literal&#34;&gt;ClientCreator&lt;/tt&gt; is asked to connect
to the local Redis server on port 6379, and will return a &lt;tt class=&#34;docutils literal&#34;&gt;Puller&lt;/tt&gt; in the
callback. The &lt;tt class=&#34;docutils literal&#34;&gt;Pusher&lt;/tt&gt; then hands the request over, and the &lt;tt class=&#34;docutils literal&#34;&gt;Puller&lt;/tt&gt; will
relay any Redis messages it picks up into that request. Everything else is
plumbing or sanity stuff; of note are the 4KiB of empty space at the beginning
of the request, which convinces browsers to start rendering the page, and also
the logic in &lt;tt class=&#34;docutils literal&#34;&gt;messageReceived&lt;/tt&gt; for closing the request and transport
properly.&lt;/p&gt;
&lt;p&gt;Here&#39;s the entire thing, imports and all. Note that it&#39;s only one line longer
than the gevent version, and comes with a bunch of nifty free features like
&lt;a class=&#34;reference external&#34; href=&#34;http://pypy.org/&#34;&gt;PyPy&lt;/a&gt; compatibility.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre&gt;&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;twisted.internet&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;reactor&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;twisted.internet.protocol&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ClientCreator&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;twisted.web.resource&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Resource&lt;/span&gt;
&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;twisted.web.server&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Site&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NOT_DONE_YET&lt;/span&gt;

&lt;span class=&#34;kn&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;txredis.protocol&lt;/span&gt; &lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;RedisSubscriber&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Puller&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;RedisSubscriber&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;None&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;messageReceived&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;channel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;and&lt;/span&gt; &lt;span class=&#34;ow&#34;&gt;not&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;finished&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&amp;lt;div&amp;gt;Message on &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%s&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;: &amp;#39;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;%s&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#39;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;
                &lt;span class=&#34;o&#34;&gt;%&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;channel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
            &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;quot;quit&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
                &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;finish&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

        &lt;span class=&#34;c&#34;&gt;# Ugh, Venn logic.&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;quot;quit&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
            &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;transport&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;loseConnection&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;cc&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ClientCreator&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;reactor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Puller&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Pusher&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Resource&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;

    &lt;span class=&#34;n&#34;&gt;isLeaf&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;True&lt;/span&gt;

    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;render_GET&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;d&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;cc&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;connectTCP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;localhost&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;6379&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;nd&#34;&gt;@d.addCallback&lt;/span&gt;
        &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;cb&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;protocol&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;protocol&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;request&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;
            &lt;span class=&#34;n&#34;&gt;protocol&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;subscribe&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;messages&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

        &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot; &amp;quot;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;4096&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
        &lt;span class=&#34;n&#34;&gt;request&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;write&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&amp;lt;!DOCTYPE html&amp;gt;&amp;lt;h1&amp;gt;Messages!&amp;lt;/h1&amp;gt;&lt;/span&gt;&lt;span class=&#34;se&#34;&gt;\n&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;

        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;NOT_DONE_YET&lt;/span&gt;

&lt;span class=&#34;n&#34;&gt;reactor&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;listenTCP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1234&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Site&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Pusher&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()))&lt;/span&gt;
&lt;span class=&#34;n&#34;&gt;reactor&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

                    </description>
                    <guid>
                        /entries/summertime.html
                    </guid>
                </item>
            
        
            
        
            
        
            
        
            
        
            
        
            
        
    </channel>
</rss>