<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
<channel>
    
    <title>argv0.net</title>
    <link>http://argv0.net</link>
    <description>complicating matters since 1977</description>
    <language>en</language>
    <pubDate></pubDate>
    <generator>http://minnow.argv0.net/minnow</generator>
    
    <item>
            <title>Simple AJAX with MochiKit and JSON, Part I</title>
            <link>http://argv0.net/2005/9/2/simple-ajax-with-mochikit-and-json-part-i</link>
            <comments>http://argv0.net/2005/9/2/simple-ajax-with-mochikit-and-json-part-i/#comments</comments>
            <pubDate>Fri, 02 Sep 2005 05:57:06 GMT</pubDate>
            <category>python</category><category>javascript</category><category>ajax</category><category>mochikit</category>
            <guid>http://argv0.net/2005/9/2/simple-ajax-with-mochikit-and-json-part-i</guid>
            <description>&lt;p&gt;I've just posted &lt;a href="http://argv0.net/static/mochitut/1"&gt;part one&lt;/a&gt; of a series of tutorials on using the &lt;a href="http://mochikit.com"&gt;MochiKit&lt;/a&gt; JavaScript framework to write AJAX web applications.  Enjoy!&lt;/p&gt;
</description>
    </item><item>
            <title>MochiKit Rules</title>
            <link>http://argv0.net/2005/7/30/mochikit-rules</link>
            <comments>http://argv0.net/2005/7/30/mochikit-rules/#comments</comments>
            <pubDate>Sat, 30 Jul 2005 05:29:08 GMT</pubDate>
            <category>webdev</category><category>python</category>
            <guid>http://argv0.net/2005/7/30/mochikit-rules</guid>
            <description>&lt;p&gt;There's much buzz about &lt;a href="http://mochikit.com"&gt;MochiKit&lt;/a&gt; - the insanely  cool Javascript framework by Pythonista/uber-hacker/all-around nice guy &lt;a href="http://bob.pythonmac.org"&gt;Bob Ippolito&lt;/a&gt; - &lt;a href="http://del.icio.us/url/4d748ae62b7296edf0784ceb8e171624"&gt;hundreds&lt;/a&gt; of del.icio.us links, &lt;a href="http://technorati.com/search/mochikit"&gt;blogosphere buzz&lt;/a&gt;, and silent awe from authors of existing Javascript frameworks as they ponder something objectively superior to just about of all the crapulent, buggy stuff currently out there&lt;/p&gt;&lt;p&gt;MochiKit holds a special place in my heart, though, as I just completed a flashy web app for my job, with all the AJAX bells and whistles managers expect ever since Google (with Google Maps) went and made our jobs much harder by upping expectations on how real web apps should behave.  Most of this wouldn't be possible without MochiKit, especially &lt;a href="http://mochikit.com/doc/html/MochiKit/DOM.html"&gt;MochiKit.DOM&lt;/a&gt;, which brings Nevow "stan" syntax to Javascript.&lt;/p&gt;&lt;p&gt;MochiKit also brings the Twisted idioms we've come to know and love, with Deferreds and callLater.  Sometimes I forget if I'm editing client or server code.  MochiKit encourages the use of JSON, and since Javascript dictionaries look just like Python dictionaries, writing server handlers is usually just a matter of returning a string representation of a Python dictionary, right from the database.&lt;/p&gt;&lt;p&gt;So, if you do any web development, it's imperative you check out &lt;a href="http://mochikit.com"&gt;MochiKit&lt;/a&gt;.  Consider this a case study - MochiKit was a key enabling factor for pulling this project off on time.&lt;/p&gt;</description>
    </item><item>
            <title>Simple AJAX With OpenRICO</title>
            <link>http://argv0.net/2005/7/1/simple-ajax-with-openrico</link>
            <comments>http://argv0.net/2005/7/1/simple-ajax-with-openrico/#comments</comments>
            <pubDate>Fri, 01 Jul 2005 06:07:28 GMT</pubDate>
            <category>python</category><category>webdev</category><category>ajax</category>
            <guid>http://argv0.net/2005/7/1/simple-ajax-with-openrico</guid>
            <description>&lt;p&gt;New JavaScript frameworks seem to be coming fast and furious these days, and it can be hard to weed out the good stuff from the garbage.  Yesterday I came across &lt;a href="http://openrico.org"&gt;OpenRICO&lt;/a&gt;, an open source version of what was formerly a proprietary framework at &lt;a href="http://sabre.com"&gt;Sabre&lt;/a&gt;.  The OpenRICO page has a bunch of cool demos (I especially dig the lazy-loading AJAX table views for large datasets).&lt;/p&gt;&lt;p&gt;So far, I've only done AJAX stuff with &lt;a href="http://http://argv0.net/2005/6/27/simple-ajax-with-nevow-livepage/"&gt;Nevow and LivePage&lt;/a&gt;, which is about as easy as it gets.  Easy has its downsides though - I found myself writing lots of code in handlers on the server that could (and should) be executed on the client, like keyboard event handlers.  Since the all client code for LivePage is either auto-generated or complicated enough to discourage manual edits,  I decided it was time to bite the bullet and start writing client-side code that "manually" invokes server methods.  Here I present a simple example on how to use OpenRICO and Nevow.  While this example is specific to Nevow, it could be easily adapted to any framework or language.&lt;/p&gt;&lt;p&gt;Most of these JavaScript frameworks are just convenience wrappers around the various implementations of XmlHttpRequest, along with helper functions for manipulating the DOM when the results come back.  For simple jobs, I could just use the Nevow implementation of these wrappers, but the cooler OpenRICO stuff depends on the OpenRICO implementation, so I use that here, even though this is a trivial example.&lt;/p&gt;&lt;p&gt;On the client, we have to mark up the area on the page we're going to to replace, then register a handler to make the request.  We do this in a function that gets called when the page finishes loading, via the &lt;code&gt;onLoad&lt;/code&gt; event of the &lt;code&gt;body&lt;/code&gt; element.  &lt;/p&gt;
&lt;code&gt;
&lt;pre&gt;
&amp;lt;html&gt;
&amp;lt;head&gt;
&amp;lt;script src="/static/prototype.js"&gt;
&amp;lt;script src="/static/rico.js"&gt;
&amp;lt;title&gt;Content Replacement Demo&amp;lt;/title&gt;
&amp;lt;script type=text/javascript&gt;

function bodyOnLoad() {
    /* Register the div named 'targetDiv' as something that will be replaced
       by an AJAX call to the server */
    ajaxEngine.registerAjaxElement('targetDiv');

    /* Register our event handler and associate it with a method on the
       server */
    ajaxEngine.registerRequest( 'replaceMe', 'doReplace' );
    }

function replaceMe(thing) {
    /* Our event handler */
    ajaxEngine.sendRequest( 'replaceMe');
    }
&amp;lt;/script&gt;
&amp;lt;body onload="javascript:bodyOnLoad()"&gt;
&amp;lt;a onclick="javascript:replaceMe(this)"&gt;click me&amp;lt/a&gt;
&amp;lt;div id="targetDiv"&gt;
&amp;lt;p&gt;this text will be replaced&amp;lt;/p&gt;
&amp;lt;/div&gt;
&amp;lt;/body&gt;
&amp;lt;/html&gt;
&lt;/pre&gt;&lt;/code&gt;
&lt;p&gt;Simple enough, and fairly self-explanatory.  The &lt;code&gt;registerRequest&lt;/code&gt; method maps a local event handler, &lt;code&gt;replaceMe&lt;/code&gt;, to a method on the server, &lt;code&gt;doReplace&lt;/code&gt;, which we'll implement now with a nice, reusable AJAXResponse class.&lt;/p&gt;
&lt;pre&gt;
&lt;span class="py-src-keyword"&gt;from&lt;/span&gt; &lt;span class="py-src-variable"&gt;nevow&lt;/span&gt; &lt;span class="py-src-keyword"&gt;import&lt;/span&gt; &lt;span class="py-src-variable"&gt;rend&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;loaders&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;inevow&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;tags&lt;/span&gt; &lt;span class="py-src-variable"&gt;as&lt;/span&gt; &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;static&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;&lt;span class="py-src-keyword"&gt;class&lt;/span&gt; &lt;span class="py-src-identifier"&gt;AJAXResponse&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;rend&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-parameter"&gt;Page&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;    &lt;span class="py-src-nl"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;    &lt;/span&gt;&lt;span class="py-src-variable"&gt;docFactory&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;loaders&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;xmlfile&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-string"&gt;"ajaxresponse.xml"&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;    &lt;span class="py-src-nl"&gt;
&lt;/span&gt;    &lt;span class="py-src-keyword"&gt;def&lt;/span&gt; &lt;span class="py-src-identifier"&gt;__init__&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;targetId&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;replaceWith&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;        &lt;/span&gt;&lt;span class="py-src-variable"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;targetId&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;targetId&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;        &lt;span class="py-src-variable"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;replaceWith&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;replaceWith&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;        &lt;span class="py-src-nl"&gt;
&lt;/span&gt;    &lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-keyword"&gt;def&lt;/span&gt; &lt;span class="py-src-identifier"&gt;beforeRender&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;ctx&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;        &lt;/span&gt;&lt;span class="py-src-variable"&gt;inevow&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;IRequest&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;ctx&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;setHeader&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;            &lt;span class="py-src-string"&gt;'Content-Type'&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-nl"&gt;
&lt;/span&gt;            &lt;span class="py-src-string"&gt;'text/xml; charset=UTF-8'&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;            &lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;    &lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-keyword"&gt;def&lt;/span&gt; &lt;span class="py-src-identifier"&gt;data_innerHTML&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;ctx&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;data&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;        &lt;/span&gt;&lt;span class="py-src-keyword"&gt;return&lt;/span&gt; &lt;span class="py-src-variable"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;replaceWith&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;    &lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-keyword"&gt;def&lt;/span&gt; &lt;span class="py-src-identifier"&gt;data_targetId&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;ctx&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;data&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;        &lt;/span&gt;&lt;span class="py-src-keyword"&gt;return&lt;/span&gt; &lt;span class="py-src-variable"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;targetId&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;&lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-dedent"&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;This class takes two arguments, the id of the div to replace, and the content to replace it with.  The XML format expected by OpenRICO is in the "ajaxresponse.xml" template, viewable &lt;a href="http://argv0.net/static/ajaxresponse.xml.txt"&gt;here&lt;/a&gt;. We can use this class from within a &lt;code&gt;child_&lt;/code&gt; method of another Nevow page to handle AJAX requests (entire file &lt;a href="http://argv0.net/static/simpleajax.py"&gt;here&lt;/a&gt;):&lt;/p&gt;&lt;pre&gt;
&lt;span class="py-src-indent"&gt;    &lt;/span&gt;&lt;span class="py-src-keyword"&gt;def&lt;/span&gt; &lt;span class="py-src-identifier"&gt;child_doReplace&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;self&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;ctx&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;        &lt;/span&gt;&lt;span class="py-src-keyword"&gt;return&lt;/span&gt; &lt;span class="py-src-variable"&gt;AJAXResponse&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;targetId&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"targetDiv"&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                            &lt;span class="py-src-variable"&gt;replaceWith&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;p&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;"ok, you're replaced"&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-endmarker"&gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;And that's it.  I'm finding that once you get the hang of it, developing web apps in this style is easier than trying to give the illusion of continuity to a bunch of stateless pages, with all the long query strings, session state, and boilerplate HTML that comes along with it.&lt;/p&gt;</description>
    </item><item>
            <title>Simple AJAX With Nevow LivePage</title>
            <link>http://argv0.net/2005/6/27/simple-ajax-with-nevow-livepage</link>
            <comments>http://argv0.net/2005/6/27/simple-ajax-with-nevow-livepage/#comments</comments>
            <pubDate>Tue, 28 Jun 2005 04:44:32 GMT</pubDate>
            <category>webdev</category><category>python</category>
            <guid>http://argv0.net/2005/6/27/simple-ajax-with-nevow-livepage</guid>
            <description>&lt;p&gt;I spent the weekend without an net connection and with a few free hours without much to do, so I played around with &lt;a href="http://nevow.com/"&gt;Nevow&lt;/a&gt;'s &lt;a href="http://exe.cfdl.auckland.ac.nz/ref/private/nevow.livepage.LivePage-class.html"&gt;LivePage&lt;/a&gt;, which enables one to write so-called "AJAX" (Asyncronous Javascript And XmlHttpRequest) web applications.  Like most else with Nevow, it's ridiculously easy to do.  I wrote a simple app that lets the user enter an RSS url and get a 'slideshow' of items from that feed (using the &lt;a href="http://feedparser.org/"&gt;FeedParser module&lt;/a&gt; to parse the RSS).  It's nothing special at all, but it serves as decent boilerplate for an AJAX page, and it was short enough that I figured I'd post it here as an example.&lt;/p&gt;&lt;pre&gt;
&lt;span class="py-src-keyword"&gt;class&lt;/span&gt; &lt;span class="py-src-identifier"&gt;AjaxRSS&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;livepage&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-parameter"&gt;LivePage&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;    &lt;/span&gt;&lt;span class="py-src-variable"&gt;addSlash&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;True&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;    &lt;span class="py-src-op"&gt;@&lt;/span&gt;&lt;span class="py-src-variable"&gt;livepage&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;handler&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;byId&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-string"&gt;'input'&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;value&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;    &lt;span class="py-src-keyword"&gt;def&lt;/span&gt; &lt;span class="py-src-identifier"&gt;selectFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;client&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-parameter"&gt;feedUrl&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;        &lt;/span&gt;&lt;span class="py-src-keyword"&gt;def&lt;/span&gt; &lt;span class="py-src-identifier"&gt;updateClient&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-parameter"&gt;parsedFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;            &lt;/span&gt;&lt;span class="py-src-keyword"&gt;if&lt;/span&gt; &lt;span class="py-src-variable"&gt;parsedFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;'entries'&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-indent"&gt;                &lt;/span&gt;&lt;span class="py-src-variable"&gt;entry&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;parsedFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;'entries'&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-number"&gt;0&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;                &lt;span class="py-src-variable"&gt;parsedFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;'entries'&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;parsedFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;'entries'&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-number"&gt;1&lt;/span&gt;&lt;span class="py-src-op"&gt;:&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;                &lt;span class="py-src-variable"&gt;client&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;set&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-string"&gt;"link"&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;a&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;href&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-variable"&gt;entry&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;'link'&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-variable"&gt;entry&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;'title'&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;                &lt;span class="py-src-variable"&gt;client&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;set&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-string"&gt;"content"&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;p&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-variable"&gt;loaders&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;htmlstr&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;entry&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;'summary'&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;                &lt;span class="py-src-variable"&gt;reactor&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;callLater&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-number"&gt;5&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;updateClient&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;parsedFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;        &lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-variable"&gt;d&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;getPage&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;feedUrl&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;        &lt;span class="py-src-variable"&gt;d&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;addCallback&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;parse&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;addCallback&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;updateClient&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;        &lt;span class="py-src-nl"&gt;
&lt;/span&gt;    &lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-variable"&gt;docFactory&lt;/span&gt; &lt;span class="py-src-op"&gt;=&lt;/span&gt; &lt;span class="py-src-variable"&gt;loaders&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;stan&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;        &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;html&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;            &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;head&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-variable"&gt;livepage&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;glue&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;            &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;body&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;p&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-string"&gt;"Enter an RSS url"&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;div&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;id&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"main"&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                    &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;form&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;id&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"form"&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;onsubmit&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-variable"&gt;selectFeed&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                        &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;input&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;id&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"input"&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;width&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"20"&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                        &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;input&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;type&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"submit"&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;value&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"submit"&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                    &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;div&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;id&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"post"&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;[&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                        &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;a&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;id&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"link"&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt; &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;br&lt;/span&gt;&lt;span class="py-src-op"&gt;,&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;                        &lt;span class="py-src-variable"&gt;T&lt;/span&gt;&lt;span class="py-src-op"&gt;.&lt;/span&gt;&lt;span class="py-src-variable"&gt;p&lt;/span&gt;&lt;span class="py-src-op"&gt;(&lt;/span&gt;&lt;span class="py-src-variable"&gt;id&lt;/span&gt;&lt;span class="py-src-op"&gt;=&lt;/span&gt;&lt;span class="py-src-string"&gt;"content"&lt;/span&gt;&lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-op"&gt;]&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;        &lt;span class="py-src-op"&gt;)&lt;/span&gt;&lt;span class="py-src-newline"&gt;
&lt;/span&gt;&lt;span class="py-src-nl"&gt;
&lt;/span&gt;&lt;span class="py-src-dedent"&gt;&lt;/span&gt;&lt;span class="py-src-endmarker"&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href="http://argv0.net:8080" rel="nofollow"&gt;Live demo here&lt;/a&gt;. Try &lt;code&gt;http://flickr.com/services/feeds/photos_public.gne?tags=cats&amp;format=rss_200&lt;/code&gt; as a url, for a slideshow of people's cat pictures on &lt;a href="http://flickr.com"&gt;Flickr&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The magic here is the &lt;code&gt;@livepage.handler(byId('input').value)&lt;/code&gt; decorator, which basically says "pass me the value of the node with the id of 'input'".  Within the handler, we call the 'set' method on the client, which allows us to change the contents of the users HTML page (another useful &lt;code&gt;client&lt;/code&gt; method is &lt;code&gt;sendScript&lt;/code&gt;, which allows you to send a chunk of Javascript for immediate evaluation to the user's browser.&lt;/p&gt;&lt;p&gt;Here's the &lt;a href="http://argv0.net/static/ajaxrss/ajaxrss.py"&gt;source&lt;/a&gt;, and a &lt;a href="http://argv0.net/static/ajaxrss/ajaxrss.tac"&gt;&lt;code&gt;.tac&lt;/code&gt;&lt;/a&gt; file that you can launch with &lt;code&gt;twistd -noy ajaxrss.tac&lt;/code&gt;&lt;/p&gt;</description>
    </item><item>
            <title>Site Update</title>
            <link>http://argv0.net/2005/6/20/site-update</link>
            <comments>http://argv0.net/2005/6/20/site-update/#comments</comments>
            <pubDate>Mon, 20 Jun 2005 17:15:54 GMT</pubDate>
            <category>python</category><category>intrablog</category>
            <guid>http://argv0.net/2005/6/20/site-update</guid>
            <description>&lt;p&gt;I just imported a bunch of old, mostly python-related content from my PyCS blog into here - I'm pretty sure it won't appear new to various aggregators like PlanetPython, but in case it does, consider this a preemptive apology.&lt;/p&gt;</description>
    </item><item>
            <title>Housekeeping</title>
            <link>http://argv0.net/2005/6/16/housekeeping</link>
            <comments>http://argv0.net/2005/6/16/housekeeping/#comments</comments>
            <pubDate>Thu, 16 Jun 2005 15:31:15 GMT</pubDate>
            <category>python</category><category>news</category>
            <guid>http://argv0.net/2005/6/16/housekeeping</guid>
            <description>&lt;div class="post"&gt;&lt;p&gt;Apologies to anyone who was reading this site with an aggregator for the last 24 hours or so.  I changed to code to make all the links absolute (so syncing the HTML content to community sites like PyCS works), but neglected to fix the RSS feeds, so they got an extra http://argv0.net at the beginning of all the links.&lt;/p&gt;&lt;p&gt;Speaking of RSS, you can get feeds of only certain tags by subscribing to links like &lt;a href="http://argv0.net/tags/python/RSS/full"&gt;http://argv0.net/tags/python/RSS/full&lt;/a&gt;.  You can use multiple tags as well, as in &lt;a href="http://argv0.net/tags/python+politics+catblogging/RSS/full"&gt;http://argv0.net/tags/python+politics+catblogging/RSS/full&lt;/a&gt;.  Nifty, eh?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update&lt;/b&gt;: The comments are fixed now, too. &lt;/b&gt;
&lt;/div&gt;</description>
    </item><item>
            <title>I'm Back</title>
            <link>http://argv0.net/2005/6/15/im-back</link>
            <comments>http://argv0.net/2005/6/15/im-back/#comments</comments>
            <pubDate>Wed, 15 Jun 2005 18:07:30 GMT</pubDate>
            <category>intrablog</category><category>python</category><category>news</category>
            <guid>http://argv0.net/2005/6/15/im-back</guid>
            <description>&lt;div class="post"&gt;&lt;p&gt;I have a bad habit of abandoning blogs, this one being no exception.  I have an excuse, though- the workload from my real job has really ramped up lately, killing most of my free time.  I also installed Tiger on my Powerbook and lost my PyDS installation, and there was no way I was going to install that beast again.&lt;p&gt;&lt;p&gt;So, I finally found a few minutes to kick my stalled blogging project, Minnow, into a good enough state where I can use it for my own blog.   The silver lining in all the "real" work is that it's all been in Python, &lt;a href="http://peak.telecommunity.com"&gt;PEAK&lt;/a&gt; specifically, so once work slows down, I'll be able to do the rewrite of Minnow I started at PyCon, based on PEAK and some other cool stuff I learned about there.&lt;/p&gt;&lt;p&gt;I haven't finished moving over the content from the old blog, so there may be broken links and various wierdnesses - feel free to report them to me.  The blog software is bound to have bugs in it as well, so bear with me - I'll get this place in order soon.&lt;/p&gt;

&lt;p&gt;Update: BTW, Anyone accessing this blog at the pycs.net URL should switch over to &lt;a href="http://argv0.net"&gt;http://www.argv0.net&lt;/a&gt;, as I'll only be syncing posts to PyCS for a few days&lt;/p&gt;
&lt;/div&gt;</description>
    </item><item>
            <title>More PyCon</title>
            <link>http://argv0.net/2005/3/23/more-pycon</link>
            <comments>http://argv0.net/2005/3/23/more-pycon/#comments</comments>
            <pubDate>Thu, 24 Mar 2005 04:05:36 GMT</pubDate>
            <category>python</category><category>pycon</category>
            <guid>http://argv0.net/2005/3/23/more-pycon</guid>
            <description>&lt;p&gt;Lots of great talks today, most notably Donovan Preston's talk on &lt;a href="http://nevow.com"&gt;Nevow&lt;/a&gt;, and Bob Ippolito's pair of talks on &lt;a href="http://pyobjc.sourceforge.net"&gt;pyobjc&lt;/a&gt;.  I missed the PyPy and Type Inference talks due to a hair-on-fire work emergency, so hopefully they got that one on tape.&lt;/p&gt;

&lt;p&gt;Ted Leung is keeping &lt;a href="http://sauria.com/blog"&gt;notes&lt;/a&gt; of the presentations, taken by various Pythonistas using &lt;a href="http://www.codingmonkeys.de/subethaedit/"&gt;SubEthaEdit&lt;/a&gt;, a collaborative e
ditor that lets multiple users take notes over a Rendezvous network.  I'd never used it in that fashion until today, and was very impressed by how powerful it was&lt;/p&gt;

&lt;p&gt;Finally, if you're in the DC area and like beer, check out &lt;a href="http://www.brickskeller.org/"&gt;The Brickskeller&lt;/a&gt; (warning: horrible web design ahead).  They have over 1000 different bottled beers from all over the world.  I had some local DC ales, which were really good, and a few funky Belgian ones.  Definitely a great spot, but probably not amenable to the 20+ dinner groups that conferences like this seem to spawn.&lt;/p&gt;
</description>
    </item><item>
            <title>PyCon</title>
            <link>http://argv0.net/2005/3/22/pycon</link>
            <comments>http://argv0.net/2005/3/22/pycon/#comments</comments>
            <pubDate>Wed, 23 Mar 2005 05:16:00 GMT</pubDate>
            <category>python</category><category>pycon</category>
            <guid>http://argv0.net/2005/3/22/pycon</guid>
            <description>&lt;p&gt;I got to the convention center today around 2, after walking about 4 miles in the wrong direction from my hotel.   While I was on the plane, the Twisted/Divmod folks released &lt;a href="http://twistedmatrix.com"&gt;Twisted 2.0&lt;/a&gt; and &lt;a href="http://nevow.com"&gt;Nevow 0.4&lt;/a&gt;, which is very cool, of course.  I'll probably use Nevow 0.4 in Minnow (which I'll put up for download soon, I promise).&lt;/p&gt;
&lt;p&gt;I spent some time rounding out the XML-RPC APIs for Minnow (a rant on the state of those APIs later), and hacking together a couple quick CRUD screens for web-based weblog administration.&lt;/p&gt;
&lt;p&gt;Anyways, it was great meeting/seeing everyone - what a great community!  All the sprint rooms are packed with all sorts of different people, old and young, hacking together,  Quite a sight to behold- I don't think any other language has such a vibrant and active community..&lt;/p&gt;
</description>
    </item><item>
            <title>PyCon Bound!</title>
            <link>http://argv0.net/2005/3/21/pycon-bound</link>
            <comments>http://argv0.net/2005/3/21/pycon-bound/#comments</comments>
            <pubDate>Tue, 22 Mar 2005 05:58:40 GMT</pubDate>
            <category>python</category><category>pycon</category>
            <guid>http://argv0.net/2005/3/21/pycon-bound</guid>
            <description>&lt;p&gt;I'm all packed, ready to hit the sack and make my way to DC in the morning.  I should be over by the convention center around noon, so look out for me :)&lt;/p&gt;</description>
    </item><item>
            <title>Minnow</title>
            <link>http://argv0.net/2005/3/8/minnow</link>
            <comments>http://argv0.net/2005/3/8/minnow/#comments</comments>
            <pubDate>Wed, 09 Mar 2005 04:41:52 GMT</pubDate>
            <category>python</category><category>minnow</category>
            <guid>http://argv0.net/2005/3/8/minnow</guid>
            <description>&lt;p&gt;Naming software is one of the hardest parts of my job.  I think it's hard for everyone (at least in Python-land, judging from the amount of Python software named PySomethingOrOther).  So I'm naming my yet-to-be-written blogging package Minnow, after my cat.  Now we can move on. &lt;/p&gt;

&lt;p&gt;I'm really thankful for all the feedback I've received regarding features.  It will certainly help guide me as I design this thing.  I'd love to hear more ideas.&lt;/p&gt;

&lt;p&gt;Here is a rough list of features/design goals I've adopted so far&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;REST-based HTTP api: A tag search should be possible using something like http://myblogaddress.org/tags/tag1+tag2 (Shawn Wheatley)&lt;/li&gt;
&lt;li&gt;The other ReST: Minnow should parse ReStructuredText, including easy highlighting of Python code snippets.&lt;/li&gt;
&lt;li&gt;Multiple posting interfaces: Minnow should accept posts from editors like MarsEdit, from the commandline, the web, or email.&lt;/li&gt;
&lt;li&gt;Easy deployment:  I like the flexibility of the &lt;a href="http://roundup.sourceforge.net"&gt;Roundup&lt;/a&gt; issue tracker in this regard.  Robust commandline tools for creating and managing blog "instances".&lt;/li&gt;
&lt;li&gt;Standard features: RSS, tags, search, archives, trackbacks, comments, etc.
&lt;li&gt;Nifty features:  Maybe a built-in moblog, integration with &lt;a href="http://del.icio.us"&gt;del.icio.us&lt;/a&gt;, who knows. 
&lt;/ul&gt;
&lt;p&gt;There's still some open ends.  How much effort, if any,  should be spent on different storage backends?  I think I'm willing to accept whatever &lt;a href="http://sqlobject.org"&gt;SQLObject&lt;/a&gt; offers, which is most open-source RDBMS's.  I could add another thin layer above SQLObject and support things like a textfile backend, but that can always be done later.&lt;/p&gt;
&lt;p&gt;How important is the ability to generate static HTML, or can the whole thing be dynamic?&lt;/p&gt;
&lt;p&gt;What about presentation?  Right now, I'm prototyping using &lt;a href="http://lesscode.org/projects/kid"&gt;Kid&lt;/a&gt;, which I'm really liking so far.  I suppose as long as theres a nice API for the data model, replacing the templating system will be trivial for those who want something else.  For the first version, users will have to be comfortable with seeing some exposed wires, as there probably won't be any higher-level 'skinning' facilities than the page templates themselves.&lt;/p&gt; 

&lt;p&gt;I realize that the number of dependencies is quite large (Twisted, SQLite, PySQLite, SQLObject, Kid... whew.. that is a lot), but it's not completely unreasonable, and a lot of people have these things inst
alled already.&lt;/p&gt;

&lt;p&gt;Obviously, there's still a bit to figure out.  I need to take a look at some of the current blogging systems to get an idea of the state of the art, and kick around this prototype some more.   In the next few days, I'll set up a Wiki as a place to brainstorm.  Again, your suggestions, advice, flames, etc. are encouraged.&lt;/p&gt;</description>
    </item><item>
            <title>What Does Your Code Taste Like?</title>
            <link>http://argv0.net/2005/2/6/what-does-your-code-taste-like</link>
            <comments>http://argv0.net/2005/2/6/what-does-your-code-taste-like/#comments</comments>
            <pubDate>Sun, 06 Feb 2005 06:09:20 GMT</pubDate>
            <category>python</category><category>design</category>
            <guid>http://argv0.net/2005/2/6/what-does-your-code-taste-like</guid>
            <description>&lt;p&gt;Martin Fowler introduced the concept of "code smells" in his book &lt;i&gt;Refactoring&lt;/i&gt;, which I think is a clever way of explaining vague aesthetic notions in an intuitive, sensory way.  I'm currently reading &lt;a
 href="http://mitpress.mit.edu/sicp/full-text/book/book.html"&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;, the following two passages of which made me reflect on how I relate to code on a sensory level, a level more intangible and personal than one of classes, functions, filenames, and line numbers.&lt;/p&gt;

&lt;blockquote&gt;
Every computer program is a model, hatched in the mind, of a real or mental process. These processes, arising from human experience and thought, are huge in number, intricate in detail, and at any time only pa
rtially understood. They are modeled to our permanent satisfaction rarely by our computer programs. Thus even though our programs are carefully handcrafted discrete collections of symbols, mosaics of interlock
ing functions, they continually evolve: we change them as our perception of the model deepens, enlarges, generalizes until the model ultimately attains a metastable place within still another model with which 
we struggle. The source of the exhilaration associated with computer programming is the continual unfolding within the mind and on the computer of mechanisms expressed as programs and the explosion of percepti
on they generate. If art interprets our dreams, the computer executes them in the guise of programs!&lt;/blockquote&gt;

...

&lt;blockquote&gt;Master software engineers have the ability to organize programs so that they can be reasonably sure that the resulting processes will perform the tasks intended. They can visualize the behavior of their systems in advance. They know how to structure programs so that unanticipated problems do not lead to catastrophic consequences, and when problems do arise, they can debug their programs. Well-designed computational systems, like well-designed automobiles or nuclear reactors, are designed in a modular manner, so that the parts can be constructed, replaced, and debugged separately.&lt;/blockquote&gt;

&lt;p&gt;After some reflection, I realized that below the surface, I have a mostly auditory model of program execution.  For example, a script that processes logfiles has a simple, repetitive rhythm - one that probably varies with the nature of the process and it's input data.  Algorithmic code I "hear" similarly, except the rhythm is more complex and accentuated, and varies according to the nature of the process -   Dijkstra sounds different than a binary search.&lt;/p&gt;

&lt;p&gt;Visualization is the most common way of expressing program execution as sensory data, like these call graphs of recursion and generator expressions in Python code:&lt;/p&gt;
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;&lt;img src="http://argv0.net/static/recursion.jpg"&gt;&lt;/td&gt;&lt;td&gt;&lt;img src="http://argv0.net/static/genexp.jpg"&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;But visualization is, in my opinion, a relatively high-level abstraction, and not the most personal, at least not for me.  They say smell is the most emotionally evocative and memory-stimulating of the sens
es, and after a few weeks on vacation, I find myself forgetting what family members and close friends look like.  Not completely, but the mental picture isn't as sharp, even after only a short time away.

&lt;p&gt;I mentioned the sound of my code to my cube-neighbor Greg, half-expecting him to tell me to lay off the LSD.  He didn't think I was crazy, and related his internal model to me, one that was more visual - "textures" was the main abstraction he seemed to have.&lt;/p&gt;

&lt;p&gt;I think a large part of the learning curve involved with learning new codebases, even after reading the API docs, knowing the module layout, maybe even reading some of the source, is the lack of a low level
 sensory model of how that code runs.  I know I have one of these for Twisted (and asynchronous programming in general), and it differs from that of threaded code, but I'm afraid I lack the language to describ
e it, because its components are so integral to &lt;i&gt;all&lt;/i&gt; the abstractions I build, including language.&lt;/p&gt;

&lt;p&gt;Expressible or not, I think exploring and understanding one's own low-level models of how their programs behave is valuable.  Does anyone have other interesting models?  Can any chefs out there taste their code?  Or should I lay off the LSD :) ?&lt;/p&gt;</description>
    </item><item>
            <title>Python Module and Package Patterns</title>
            <link>http://argv0.net/2005/1/30/python-module-and-package-patterns</link>
            <comments>http://argv0.net/2005/1/30/python-module-and-package-patterns/#comments</comments>
            <pubDate>Mon, 31 Jan 2005 01:51:12 GMT</pubDate>
            <category>python</category><category>design</category>
            <guid>http://argv0.net/2005/1/30/python-module-and-package-patterns</guid>
            <description>&lt;p&gt;I was reading &lt;a href="http://naeblis.cx/rtomayko/"&gt;Ryan Tomayko&lt;/a&gt;'s recent &lt;a href="http://naeblis.cx/rtomayko/2005/01/23/no-rails-for-python"&gt;article&lt;/a&gt; about the success of &lt;a href="http://www.rubyonr
ails.org"&gt;Ruby on Rails&lt;/a&gt;, and he raises a couple of excellent questions about package and module layout and design that have been bothering me lately:&lt;/p&gt;

&lt;blockquote class="greybox"&gt;This may sound silly but I waste a ton of time trying to organize my project's source files.
&lt;ul&gt;
&lt;li&gt;How should database scripts, templates, other web resources, scripts, documentation, etc. be organized?&lt;/li&gt;
&lt;li&gt;How should my packages be laid out? Do I create separate sub-packages for model, view, and controller? How about just separate modules? Or should I organize by object, keeping the model, view, and controll
er implementations in a single module? I've tried all of these approaches and found that each has pros and cons but that consistency is always king.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another aspect of Rails that I appreciated is that it seems to promote&lt;97&gt;and possibly even require&lt;97&gt;a strict organizational structure of source files. This structure can be generated for you by helper sc
ripts.&lt;/p&gt;

&lt;p&gt;This is the kind of stuff I think is underrated. It significantly lowers the barrier to entry for new programmers to get moving with the framework and lowers the amount of time it takes for experienced prog
rammers to create new projects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not silly at all, actually.  I spent a lot of time doing this too.  It's trickier than it may seem, and getting it right can greatly ease the barriers to entry for would-be developers and extenders of one's
 work.  For many people, including myself, this is still somewhat of an afterthought, nowhere near the typical "design" tasks on the priority list.&lt;/p&gt;

&lt;p&gt;I don't think much about package layout up-front. I'll typically start with a single main package, with subpackages organized by functional category ('protocols', 'scripts', 'utilities', core', etc).  Event
ually, it becomes apparent that one or more of these packages are unnecessary, and they'll get moved back to the top level.  As the API approaches completion, typically new packages get created that weren't en
visioned at the beginning. Finally, a top-level facade module or two that offer convenience APIs and define the main API of the package.&lt;/p&gt;

&lt;p&gt;I've also noticed a few other distinct package layout patterns in popular Python software:&lt;/p&gt;

&lt;h4&gt;The Single Python File&lt;/h4&gt;

&lt;p&gt;RSS.py and SOAP.py come to mind here.  These modules are usually protocol implementations with few dependencies, and are well-suited for this format.&lt;/p&gt;
&lt;p&gt;Psychologically, adding one of these to a project doesn't feel as 'heavyweight' a dependency as adding a distutils-based tarball does -  which is not really true - but it's one of the peculiarities of a mod
ule's marriage to the filesystem.  I was never really comfortable with the Smalltalk approach, where the code I'm extending is a monolithic image, that includes the IDE and all manner of other cruft.  When I'm
 working with someone elses code, a part of me wants to know what &lt;i&gt;file&lt;/i&gt; a given class is in.&lt;/p&gt;

&lt;h4&gt;The Messy Flat Namespace&lt;/h4&gt;

&lt;p&gt;These are common.  The Python standard library is one, but an excusable one given the nature of it's evolution.  Small teams and single developers are more able to design and maintain a sensible module hier
archy, yet the MFN layout is common among packages that should know better (including many of my earlier efforts).&lt;/p&gt;

&lt;h4&gt;Script Package&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://twistedmatrix.com"&gt;Twisted&lt;/a&gt; and &lt;a href="http://peak.telecommunity.com"&gt;PEAK&lt;/a&gt; use this one, where the logic of command-line scripts is kept in modules in a 'scripts' package,  instanti
ated by a single frontend script (`twistd` and `peak`, respectively).&lt;/p&gt;

&lt;p&gt;The script module invoked is usually responsible for returning an object that conforms to a some sort of 'Command' or 'Application' interface.&lt;/p&gt;

&lt;h4&gt;Facade Module&lt;/h4&gt;

&lt;p&gt;__init__.py is one of these - an abstraction point for the functionality of the modules in a package. Frameworks like PEAK and &lt;a href="http://www.zope.org"&gt;Zope&lt;/a&gt; have extended package conventions, usual
ly including an 'api' and 'interfaces' module. &lt;/p&gt;

&lt;p&gt;Advanced versions of the Facade module, as seen in PEAK, support funky things like lazy loading and module inheritance.&lt;/p&gt;&lt;hr/&gt;&lt;br/&gt;
 
These patterns address module layout, but none address what to do with the &lt;i&gt;other&lt;/i&gt; project files, static templates, images, and data that should probably live 'closer' to the code than /usr/share or /var/
whatever. It would be nice to have a distutils binary format that does something like py2app and py2exe do - put everything in a single executable for deployment.  There are many cases where one doesn't want t
o tell a customer to install Python, or where one doesn't trust a customer not to bollocks his copy of Python.  And again, the Single File is nice.&lt;/p&gt;

&lt;p&gt;Finally, I'll agree with Ryan that this stuff is indeed underrated.  One major difference between my personal projects and work projects is the amount of time spent on ease-of-use bells and whistles like stub code generation in the latter.&lt;/p&gt;	</description>
    </item><item>
            <title>pyunparse 0.2: A Python AST Printer/Unparser</title>
            <link>http://argv0.net/2005/1/27/pyunparse--a-python-ast-printerunparser</link>
            <comments>http://argv0.net/2005/1/27/pyunparse--a-python-ast-printerunparser/#comments</comments>
            <pubDate>Thu, 27 Jan 2005 21:22:24 GMT</pubDate>
            <category>python</category>
            <guid>http://argv0.net/2005/1/27/pyunparse--a-python-ast-printerunparser</guid>
            <description>&lt;p&gt;Here's &lt;a href="http://argv0.net/pyunparse/pyunparse.py"&gt;pyunparse 0.2&lt;/a&gt;.  Mostly cosmetic improvements, but I'm not so ashamed of the code, and it should be easier to grok and modify.  Please download it if you are using the old version.&lt;/p&gt;</description>
    </item><item>
            <title>Going to PyCon!</title>
            <link>http://argv0.net/2005/1/26/going-to-pycon</link>
            <comments>http://argv0.net/2005/1/26/going-to-pycon/#comments</comments>
            <pubDate>Thu, 27 Jan 2005 05:01:04 GMT</pubDate>
            <category>python</category>
            <guid>http://argv0.net/2005/1/26/going-to-pycon</guid>
            <description>&lt;p&gt;My itinerary for PyCon just hit my inbox.  This will be my first one, and the lineup of talks this year has me really looking forward to going. I can also provide several anonymous Pythonistas with the beers I
 owe them. :&amp;gt;&lt;/p&gt;
</description>
    </item><item>
            <title>pyunparse: From AST to Python Source</title>
            <link>http://argv0.net/2005/1/25/pyunparse-from-ast-to-python-source</link>
            <comments>http://argv0.net/2005/1/25/pyunparse-from-ast-to-python-source/#comments</comments>
            <pubDate>Tue, 25 Jan 2005 22:45:36 GMT</pubDate>
            <category>python</category>
            <guid>http://argv0.net/2005/1/25/pyunparse-from-ast-to-python-source</guid>
            <description>&lt;p&gt;I just got done hacking up a proof-of-concept Python "unparser" that converts Python Abstract Syntax Trees to concrete Python source code.  Pyunparse is intended to be used as a debugging aid for apps that 
use the compiler.ast classes.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href="http://argv0.net/pyunparse/index.html"&gt;pyunparse&lt;/a&gt; page for more information, or to download the script. &lt;/p&gt;
</description>
    </item><item>
            <title>py2dot: Visualizing Python Syntax Trees with Graphviz</title>
            <link>http://argv0.net/2005/1/21/pydot-visualizing-python-syntax-trees-with-graphviz</link>
            <comments>http://argv0.net/2005/1/21/pydot-visualizing-python-syntax-trees-with-graphviz/#comments</comments>
            <pubDate>Fri, 21 Jan 2005 06:39:12 GMT</pubDate>
            <category>python</category>
            <guid>http://argv0.net/2005/1/21/pydot-visualizing-python-syntax-trees-with-graphviz</guid>
            <description>&lt;p&gt;py2dot is a useful script I wrote that generates Graphviz ".dot" files from Python source code. The output images can be used to teach parsing concepts, or as cubicle art:&lt;/p&gt;
&lt;p align="center"&gt;
&lt;img src="http://argv0.net/py2dot/factorial-1-small.png"&gt;
&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href="http://argv0.net/py2dot/index.html"&gt;py2dot page&lt;/a&gt; for more details or &lt;a href="http://argv0.net/py2dot/py2dot.py"&gt;click here&lt;/a&gt; to download.&lt;/p&gt;

&lt;p&gt;py2dot requires &lt;a href="http://www.graphviz.org"&gt;Graphviz&lt;/a&gt; and &lt;a href="http://www.python.org/2.4"&gt;Python 2.4&lt;/a&gt;&lt;/p&gt;
</description>
    </item><item>
            <title>Bytecodehacks Are Back!</title>
            <link>http://argv0.net/2004/12/20/bytecodehacks-are-back</link>
            <comments>http://argv0.net/2004/12/20/bytecodehacks-are-back/#comments</comments>
            <pubDate>Mon, 20 Dec 2004 22:37:00 GMT</pubDate>
            <category>python</category>
            <guid>http://argv0.net/2004/12/20/bytecodehacks-are-back</guid>
            <description>&lt;p&gt;Bytecodehacks was a great package for doing evil things with python bytecode - inline functions, semantic macros, design by contract - all sorts of good stuff.  Unfortunately, it stopped  working after Python 2.0.&lt;/p&gt;

&lt;p&gt;Enter Christian Tismer of Stackless fame, who has &lt;a href="http://mail.python.org/pipermail/python-announce-list/2004-July/003280.html"&gt;re-released&lt;/a&gt; a bytecodehacks package that works with newer Pythons.&lt;/p&gt;

&lt;p&gt;It *nearly* works out of the box with Python 2.4 too, with one minor change.  Apparently the SET_LINENO instruction  was removed in 2.4, but a couple of modules in bytecodehacks depend on it.  I fixed this by 
adding a stub SET_LINENO class in ops.py:&lt;/p&gt;

&lt;pre&gt;
class SET_LINENO:
      pass
&lt;/pre&gt;

&lt;p&gt;That seems to fix it for me.  Thanks, Christian!&lt;/p&gt;</description>
    </item>
</channel>
</rss>
