<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>David Janes&#039; Code Weblog &#187; pybm</title>
	<atom:link href="http://code.davidjanes.com/blog/category/pybm/feed/" rel="self" type="application/rss+xml" />
	<link>http://code.davidjanes.com/blog</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 11 Apr 2010 12:32:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Creating OPML subscription lists using Pipe Cleaner</title>
		<link>http://code.davidjanes.com/blog/2009/01/25/creating-opml-subscription-lists-using-pipe-cleaner/</link>
		<comments>http://code.davidjanes.com/blog/2009/01/25/creating-opml-subscription-lists-using-pipe-cleaner/#comments</comments>
		<pubDate>Sun, 25 Jan 2009 16:40:30 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[authentication]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[pipe cleaner]]></category>
		<category><![CDATA[pybm]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=433</guid>
		<description><![CDATA[Here&#8217;s a neat API I completed this morning, called api_feeds. It takes a URL (or a list of them) and transforms them into:

the home page associated with the URL
the feed(s) for the URL
the name of the home page

If you&#8217;re following along at home, this is essentially the information needed for a single outline in an [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a neat API I completed this morning, called <code>api_feeds</code>. It takes a URL (or a list of them) and transforms them into:</p>
<ul>
<li>the home page associated with the URL</li>
<li>the feed(s) for the URL</li>
<li>the name of the home page</li>
</ul>
<p>If you&#8217;re following along at home, this is essentially the information needed for a single <code>outline</code> in an <a href="http://www.opml.org/spec2#subscriptionLists">OPML subscription list</a>.</p>
<p>Here&#8217;s a simple python example:</p>
<pre>api = api_feeds.OneFeed()
api.request = {
    "uri" : "http://code.davidjanes.com/blog/2009/01/23/transparently-working-with-oauath/",
}

pprint.pprint(api.response, width = 1)</pre>
<p>And here&#8217;s what the output looks like:</p>
<pre>{'link': u'http://code.davidjanes.com/blog',
 'links': [{'href': u'http://feeds.feedburner.com/DavidJanesCode',
            'rel': 'alternate',
            'type': u'application/rss+xml'}],
 'title': u"David Janes' Code Weblog"}</pre>
<p>There&#8217;s actually quite a bit going on here behind the scenes, most of it using code I didn&#8217;t initially write but have quite heavily hacked: the <a href="http://www.feedparser.org/">Universal Feed Parser</a> and the <a href="http://pypi.python.org/pypi/feedfinder/1.371">Feed Finder</a>.</p>
<p>What becomes really interesting what happens when we combine this with other modules. Here&#8217;s an example of how we can build an OPML subscription list from all the posts I&#8217;ve tagged &#8220;python&#8221; and &#8220;django&#8221; in <a href="http://delicious.com/dpjanes/python+django">del.icio.us</a>. The code looks up each link I&#8217;ve bookmarked, does the feed discovery above, filters out items that don&#8217;t have feeds, and outputs as OPML. Note the neat pipeline type aspect to the code:</p>
<pre>api_delicious = api_delicious.PostsList(tag = "python django")
api_many = api_feeds.ManyFeeds(require_feed = True)
api_opml = api_opml.OPMLWriter()

api_many.items = api_delicious.items
api_opml.items = api_many.items

print api_opml.Produce()</pre>
<p>Producing the following OPML:</p>
<pre>&lt;opml encoding="utf-8" version="2.0"&gt;
  &lt;head&gt;
    &lt;title&gt;[Untitled]&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;outline htmlUrl="http://push.cx"
      rssUrl="http://push.cx/feed"
      text="Push cx"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://crankycoder.com"
      rssUrl="http://crankycoder.com/feed/"
      text="crankycoder.com"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://blog.dowski.com"
      rssUrl="http://blog.dowski.com/feed/"
      text="the occasional occurrence"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://www.b-list.org/feeds/entries/"
      rssUrl="http://feeds2.feedburner.com/b-list-entries"
      text="The B-List: Latest entries"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://blog.thescoop.org"
      rssUrl="http://blog.thescoop.org/feed/"
      text="The Scoop"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://effbot.org"
      rssUrl="http://effbot.org/zone/rss.xml"
      text="effbot.org"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://blog.disqus.net"
      rssUrl="http://feeds.feedburner.com/BigHeadLabs"
      text="Disqus"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://blog.ianbicking.org"
      rssUrl="http://blog.ianbicking.org/feed/atom/"
      text="Ian Bicking: a blog"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://antoniocangiano.com"
      rssUrl="http://feeds.feedburner.com/ZenAndTheArtOfRubyProgramming"
      text="Zen and the Art of Programming"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://www.carthage.edu/webdev"
      rssUrl="http://www.carthage.edu/webdev/?feed=rss2"
      text="carthage webdev"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://www.eweek.com"
      rssUrl="http://www.eweek.com/rss-feeds-13.xml"
      text="Application Development - RSS Feeds"
      type="rss"/&gt;
    &lt;outline htmlUrl="http://jeffcroft.com/"
      rssUrl="http://feeds.feedburner.com/jeffcroft/blog"
      text="JeffCroft.com: Latest blog entries"
      type="rss"/&gt;
  &lt;/body&gt;
&lt;/opml&gt;</pre>
<p>This will be just as terse (terser, probably) when written as a Pipe Cleaner script; I&#8217;m just struggling over how to introduce the authentication code gracefully into the scripts.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2009/01/25/creating-opml-subscription-lists-using-pipe-cleaner/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Transparently working with OAuath</title>
		<link>http://code.davidjanes.com/blog/2009/01/23/transparently-working-with-oauath/</link>
		<comments>http://code.davidjanes.com/blog/2009/01/23/transparently-working-with-oauath/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 10:03:45 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[authentication]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[pipe cleaner]]></category>
		<category><![CDATA[pybm]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=414</guid>
		<description><![CDATA[This is part one of two posts I&#8217;m going to write about OAuth; the second will be somewhat more critical in tone. Before I criticize &#8211; and I know it&#8217;s hard to put together technologically things like OAuth &#8211; I want to actually accomplish something with it, so I at least I appear that I [...]]]></description>
			<content:encoded><![CDATA[<p>This is part one of two posts I&#8217;m going to write about <a href="http://oauth.net/">OAuth</a>; the second will be somewhat more critical in tone. Before I criticize &#8211; and I know it&#8217;s hard to put together technologically things like OAuth &#8211; I want to actually accomplish something with it, so I at least I appear that I have somewhat of a clue about it. This is a report of what I&#8217;ve done.</p>
<p><code>bm_uri</code> is a libary and tool I&#8217;ve written for working with URIs, and in particular <code>http://</code> and <code>https://</code> URLs. Here are some of the advantages of using <code>bm_uri</code> over all the normal Python <code>urllib</code> and <code>urllib2</code> methods:</p>
<ul>
<li>downloads are cached; if a URL is temporarily not available, <code>bm_uri</code> will return the cached version, likewise if it has been downloaded in the near past, the cached version will be returned rather than hitting the net again</li>
<li>downloads can be <em>cooked</em>, meaning converted into a more useful form such as TIDY-cleaned up HTML, JSON, Unicode text and so forth</li>
<li><code>bm_uri</code> handles all the protocol stuff for you (such as User-Agent, Last-Modified and so forth) so you don&#8217;t have to</li>
<li>authentication is handled &#8220;invisibly&#8221; as possible for you &#8230; at least after the initial setup</li>
</ul>
<p>Here is an example of accessing a OAuth resource using <code>bm_uri</code> returning my current location from <a href="http://fireeagle.yahoo.net/">Fire Eagle</a> as a Python object. From a programming point of a view, I believe I have reduced this to close to the minimum number of steps possible. Here&#8217;s the setup phase:</p>
<pre>import bm_uri
import bm_oauth
import pprint

bm_cfg.cfg.initialize()

bm_oauth.OAuth(service_name = "fireeagle")</pre>
<p>Here&#8217;s using it in code &#8211; note how there&#8217;s no reference to OAuth here whatsoever.</p>
<pre>loader = bm_uri.JSONLoader('https://fireeagle.yahooapis.com/api/0.1/user.json?format=json')
loader.Load()

pprint.pprint(loader.GetCooked())</pre>
<p>And here&#8217;s the output of the program:</p>
<pre>{u'stat': u'ok',
 u'user': {u'location_hierarchy': [{u'best_guess': True,
         u'geometry': {u'coordinates': [-79.418426513699998,
                   43.731891632100002],
              u'type': u'Point'},
         u'id': 572261,
         u'label': None,
         u'level': 1,
         u'level_name': u'postal',
         u'located_at': u'2008-03-19T04:09:30-07:00',
...
         u'name': u'Canada',
         u'normal_name': None,
         u'place_id': u'EESRy8qbApgaeIkbsA',
         u'woeid': 23424775}],
     u'readable': True,
     u'writable': False}}</pre>
<h4>Gather information</h4>
<p>The devil is in the details, obviously and with OAuth, the little satan is doing the initial setup. Here&#8217;s how I did this for Fire Eagle &#8211; there&#8217;ll be something analogous for whatever service you are using:</p>
<ul>
<li>Log in or sign up (obviously)</li>
<li>Go to the <a href="http://fireeagle.yahoo.net/developer">Developers&#8217; Page</a></li>
<li>Click on <a href="https://fireeagle.yahoo.net/developer/create">Create a New App</a></li>
<li>Copy the &#8220;Consumer Key&#8221; and the &#8220;Consumer Secret&#8221; &#8230; these will be long-ish strings of nonsense</li>
<li>Find out the Request Token URL, the Access Token URL, and the Authorization URL. These are public knowledge and for Fire Eagle are:
<ul>
<li>https://fireeagle.yahooapis.com/oauth/request_token</li>
<li>https://fireeagle.yahooapis.com/oauth/access_token</li>
<li>http://fireeagle.yahoo.net/oauth/authorize</li>
</ul>
</li>
</ul>
<p><em>Note how Yahoo has conveniently made that last URL similar looking to the others, but not quite the same. Thanks!</em></p>
<p>However you implement OAuth, you&#8217;re probably going to need to be able to persist information to disk or database. As documented here several weeks ago, <a href="http://code.davidjanes.com/blog/2009/01/09/thinking-about-configuration/">we already have that covered</a> with our bm_cfg module. In <code>~/.cfg/fireeagle.json</code>, create the following JSON format file:</p>
<pre>{
 "fireeagle": {
  "api_uri" : "https://fireeagle.yahooapis.com/",
  "oauth_access_token_url": "https://fireeagle.yahooapis.com/oauth/access_token",
  "oauth_authorization_url": "http://fireeagle.yahoo.net/oauth/authorize",
  "oauth_consumer_key": "ABCDEFGHIJKL",
  "oauth_consumer_secret": "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
  "oauth_token_url": "https://fireeagle.yahooapis.com/oauth/request_token",
 }
}</pre>
<p>The only new item here is the <code>api_uri</code>: that&#8217;s the prefix of URLs that <code>bm_uri</code> will use OAuth with.</p>
<h4>Set it up</h4>
<p>Next you have to do all sorts of OAuth stuff to actually work with OAuth. If the <em>why</em> interests you, <a href="http://oauth.net/core/1.0/">please go read the spec</a>! I&#8217;m more of <em>how</em> person myself, and this is what we need to do:</p>
<ul>
<li>run: <code>python bm_uri.py --service fireeagle --authorize</code></li>
<li>this will pop up a browser window; grant your application access and then&#8230;</li>
<li>run: <code>python bm_uri.py --service fireeagle --exchange</code></li>
</ul>
<p>And that&#8217;s it &#8211; you should now be able to just work with the Fire Eagle API in bm_uri without even having to know OAuth is there!</p>
<h4>End notes</h4>
<ul>
<li>the current implementation only works with HTTP/<a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a> GET; POST to come soon, DELETE and PUT as needed</li>
<li><code>bm_uri</code>, <code>bm_config</code> and the rest of the code is freely licensed and available <a href="http://code.google.com/p/pybm/">here</a>. It is a constantly changing product, albeit converging on perfection in my own mind ;-)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2009/01/23/transparently-working-with-oauath/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Pipe Cleaner</title>
		<link>http://code.davidjanes.com/blog/2008/12/18/pipe-cleaner/</link>
		<comments>http://code.davidjanes.com/blog/2008/12/18/pipe-cleaner/#comments</comments>
		<pubDate>Thu, 18 Dec 2008 23:38:21 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[djolt]]></category>
		<category><![CDATA[dqt]]></category>
		<category><![CDATA[html / javascript]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[jd]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[pipe cleaner]]></category>
		<category><![CDATA[pybm]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=372</guid>
		<description><![CDATA[I&#8217;ve been working (in my decreasing available spare time) on a project to pull together into a project called &#8220;Pipe Cleaner&#8221; all the various concepts I&#8217;ve been mentioning on this blog: Web Object Records (WORK) for API Access and object manipulation, Djolt for generating text from templates, Data/Query/Transform/Template (DQT) for transforming data and JD for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working (in my decreasing available spare time) on a project to pull together into a project called &#8220;Pipe Cleaner&#8221; all the various concepts I&#8217;ve been mentioning on this blog: <a href="http://code.davidjanes.com/blog/category/work/">Web Object Records (WORK</a>) for API Access and object manipulation, <a href="http://code.davidjanes.com/blog/category/djolt/">Djolt</a> for generating text from templates, <a href="http://code.davidjanes.com/blog/category/dqt/">Data/Query/Transform/Template</a> (DQT) for transforming data and <a href="http://code.davidjanes.com/blog/category/jd/">JD</a> for scripting these elements together. The pieces came together this morning enough to put a demo together and here it is &#8211; <a href="http://code.davidjanes.com/examples/2008-12-18/gmaps3/">the Toronto Fires Pt II Demo</a>.</p>
<p>How, you may ask, does this differ from <a href="http://code.davidjanes.com/blog/2008/11/22/toronto-fires/">the original Toronto Fires Demo</a>? The answer is how it is put together, which we describe here.</p>
<h4>Index.dj</h4>
<p>This is the Djolt template that generates the output. The data fed to this template is generate by the JD script, described in the next section.</p>
<pre>&lt;html&gt;
&lt;head&gt;
    &lt;link rel="stylesheet" type="text/css" href="css.css" /&gt;
    {{ gmaps.js|safe }}
&lt;/head&gt;
&lt;body&gt;
&lt;div id="content_wrapper"&gt;
    &lt;div id="map_wrapper"&gt;
        {{ gmaps.html|safe }}
    &lt;/div&gt;
    &lt;div id="text_wrapper"&gt;
{% for incident in incidents %}
    &lt;div id="{{ incident.IncidentNumber }}"&gt;
        {{ incident.body_sb|safe }}
    &lt;/div&gt;
{% endfor %}
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Quite simple &#8230; as you can see, most of the data is being pulled in from elsewhere. The elsewhere is provided by the script described in the next section.</p>
<h4>Index.jd</h4>
<p>This is the script that pull all the pieces together. Note that I&#8217;m not 100% happy with the way the data is imported, I would like the geocoding to become part of this data flow too. In the next release perhaps.</p>
<p>First we pull in the &#8220;fire&#8221; module that we wrote in the previous Map examples. This is doing exactly what you think: importing a Python module. We may have to increase the security or restrict this to working with an API for general purpose use.</p>
<pre>import module:"fire";</pre>
<p>Next we define two headers &#8211; one that is going to appear in the Google Maps popup, the next that is going to appear in the sidebar. They need to be different as they refer to themselves. Note that the sidebar header &#8220;breaks&#8221; the encapsulation of Google Maps &#8211; this seems to be unavoidable. The <code>to:"fitem.head.map"</code> and <code>to:"fitem.head.sb"</code> are manipulating a WORK dictionary to store values.</p>
<p>Note also here that we&#8217;ve extended JD to accept Python multiline strings &#8211; this was unavoidable if JD was to be useful to me.</p>
<pre>set to:"fitem.head.map" value:"""
&lt;h3&gt;
&lt;a href="#{{ IncidentNumber }}"&gt;{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}
&lt;/h3&gt;
""";

set to:"fitem.head.sb" value:"""
&lt;h3&gt;
{% if latitude and longitude %}
&lt;a href="javascript:js_maps.map.panTo(new GLatLng({{ latitude }}, {{ longitude }}))"&gt;*
{% endif %}
&lt;a href="#{{ IncidentNumber }}"&gt;{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}
&lt;/h3&gt;
""";</pre>
<p>The next block defines the text of the body used to describe a fire incident. It follows much the same pattern as the previous block.</p>
<pre>set to:"fitem.body" value:"""
&lt;p&gt;
Alarm Level: {{ AlarmLevel }}
&lt;br /&gt;
Incident Type: {{ IncidentType }}
&lt;br /&gt;
City: {{ City }}
&lt;br /&gt;
Street: {{ Street }} ({{ CrossStreet }})
&lt;br /&gt;
Units: {{ Units }}
&lt;/p&gt;
""";</pre>
<p>This is a map: it is translating the values in <code>fire.GetGeocodeIncidents</code> into a new format and storing that in <code>incidents</code>. The format that we were are storing it in is understood by the Google Maps generating module.</p>
<p>We may rename this translate, as the word map is somewhat overloaded.</p>
<pre>map from:"fire.GetGeocodedIncidents" to:"incidents" map:{
    "latitude" : "{{ latitude }}",
    "longitude" : "{{ longitude }}",
    "title" : "{{ AlarmLevel}}: {{ IncidentType }} on {{ RawStreet }}",
    "uri" : "{{ HOME_URI }}#{{ IncidentNumber }}",
    "body" : "{{ *fitem.head.map|safe }}{{ *fitem.body|safe }}",
    "body_sb" : "{{ *fitem.head.sb|safe }}{{ *fitem.body|safe }}",
    "IncidentNumber" : "{{ IncidentNumber }}"
};</pre>
<p>Next we set up the &#8220;meta&#8221; (see <a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">WORK meta description</a> if you&#8217;re not following along) for the maps. The <code>render_value:true</code> declaration makes PC interpret the templates in strings). We then call our Google Maps generating code (which are actually more Pipe Cleaners) and that gets fed to the Djolt template we first showed you. Clear? Maybe not, we&#8217;ll have more examples coming&#8230;</p>
<pre>set to:"map_meta" render_value:true value:{
    "id" : "maps",
    "latitude" : 43.67,
    "longitude" : -79.38,
    "uzoom" : -13,
    "gzoom" : 13,
    "api_key" : "{{ cfg.gmaps.api_key|otherwise:'...mykey...' }}",
    "html" : {
        "width" : "1024px",
        "height" : "800px"
    }
};

load template:"gmaps.js" items:"incidents" meta:"map_meta";
load template:"gmaps.html" items:"incidents" meta:"map_meta";</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/12/18/pipe-cleaner/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Coding backwards for simplicity</title>
		<link>http://code.davidjanes.com/blog/2008/12/08/coding-backwards-for-simplicity/</link>
		<comments>http://code.davidjanes.com/blog/2008/12/08/coding-backwards-for-simplicity/#comments</comments>
		<pubDate>Mon, 08 Dec 2008 21:58:57 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[djolt]]></category>
		<category><![CDATA[dqt]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[pybm]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=311</guid>
		<description><![CDATA[I haven&#8217;t been posting as much as I like here for the last three weeks, not because of lack of ideas but because I haven&#8217;t been able to consolidate what I&#8217;ve been working on into a coherent thought. I&#8217;m trying to come up with a overreaching conceptual arch that covers WORK, Djolt and the various [...]]]></description>
			<content:encoded><![CDATA[<p>I haven&#8217;t been posting as much as I like here for the last three weeks, not because of lack of ideas but because I haven&#8217;t been able to consolidate what I&#8217;ve been working on into a coherent thought. I&#8217;m trying to come up with a overreaching conceptual arch that covers <a href="http://code.davidjanes.com/blog/category/work/">WORK</a>, <a href="http://code.davidjanes.com/blog/category/djolt/">Djolt</a> and the various API interfaces I&#8217;ve been coded. Tentatively and horribly, I&#8217;m calling this Data/Query/Transform/Template right now though I&#8217;m expecting this to change.</p>
<p>The first demo of this &#8230; without further explanation &#8230; <strong><a href="http://code.davidjanes.com/examples/2008-12-08/dqtt1/">can be seen here</a></strong>. More details about what this is actually demonstrating (besides formatting this blog) will be forthcoming.</p>
<p>What I want to draw attention to in this post is <em>how</em> I coded this. What I&#8217;ve been doing for the last several weeks is <em>coding backwards</em>: I start with what I want the final code to look like and then figure out all the libraries, little languages and so forth that would be needed to code that. After several false starts, my conceptual logjam broke about a week ago and code started radically simplifying.</p>
<p>The ideal code, in my mind, is almost entirely static declarations: no loops, no if statements, no while statements, no goto-type statements (god help us). We simply specify how the parts are connected, and hope that we can abstract the complexity into the libraries that make this all happen. The code that you see below is actually post all my conceptualizing: I just wanted to write some code and since I had almost all the parts together it fell together quite nicely:</p>
<pre>import bm_wsgi
import bm_io

import djolt
import api_feed

from bm_log import Log

class Application(bm_wsgi.SimpleWrapper):
    def __init__(self, *av, **ad):
        bm_wsgi.SimpleWrapper.__init__(self, *av, **ad)

    def CustomizeSetup(self):
        self.html_template_src = bm_io.readfile("index.dj")
        self.html_template = djolt.Template(self.html_template_src)

        self.context = djolt.Context()
        self.context["paramd"] = {
            "feed" : "http://feeds.feedburner.com/DavidJanesCode",
            "template" : """\
&lt;ul&gt;
{% for item in data.items %}
	&lt;li&gt;&lt;a href="{{ item.link }}"&gt;{{ item.title }}&lt;/a&gt;&lt;/li&gt;
{% endfor %}
""",
        }
        self.context.Push()
        self.context["paramd"] = self.paramd
        self.context["data"] = api_feed.RSS20(self.context.as_string("paramd.feed"))

    def CustomizeContent(self):
        yield   self.html_template.Render(self.context)

if __name__ == '__main__':
    Application.RunCGI()</pre>
<p>There&#8217;s almost nothing there! In particular, note:</p>
<ul>
<li><code>bm_wsgi.SimpleWrapper</code> handles all the WSGI interface work, including determining when to output HTML headers, error trapping, and Unicode to UTF-8 encoding</li>
<li>the most complicated part of the application is setting up the <code>Context</code>. In particular, note that self.paramd is automatically populated by the <code>QUERY_STRING</code> passed to the application, and the double setting we do here allows us to have default values.</li>
<li>If you want to see the HTML template that drives the application <a href="http://code.davidjanes.com/examples/2008-12-08/dqtt1/index.dj">it is here</a>. Note two variations from Django templates: the <code>{% asis %}</code> block which doesn&#8217;t intrepret it&#8217;s content as Djolt code and the <code>{{ *paramd.template|safe }}</code> variable which<em> <a href="http://code.davidjanes.com/blog/2008/12/04/djolt-indirection/">interprets the variable&#8217;s contents as a template</a></em>.</li>
<li>Methods called <code>Customize</code>-something are my convention for framework functions, i.e. methods that will be called for us rather than methods we call.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/12/08/coding-backwards-for-simplicity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Djolt &#8211; Django-like Templates</title>
		<link>http://code.davidjanes.com/blog/2008/11/28/djolt-django-like-templates/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/28/djolt-django-like-templates/#comments</comments>
		<pubDate>Fri, 28 Nov 2008 21:34:39 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[djolt]]></category>
		<category><![CDATA[pybm]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=277</guid>
		<description><![CDATA[Djolt is a reimplementation of Django&#8217;s template language in Python. Why do this?

I like the Django template language
I wanted something that small and independent of Django
I wanted something that will work with WORK paths (this was the real deal breaker for using Django)
I wanted something that I could take and reimplement in Javascript and maybe [...]]]></description>
			<content:encoded><![CDATA[<p>Djolt is a reimplementation of <a href="http://docs.djangoproject.com/en/dev/topics/templates/">Django&#8217;s template language</a> in Python. Why do this?</p>
<ul>
<li>I like the Django template language</li>
<li>I wanted something that small and independent of Django</li>
<li>I wanted something that will work with <a href="http://code.davidjanes.com/blog/2008/11/21/work-paths/">WORK paths</a> (this was the real deal breaker for using Django)</li>
<li>I wanted something that I could take and reimplement in Javascript and maybe Java too</li>
<li>Some template engines, <a href="http://www.cheetahtemplate.org/">Cheetah</a> for example, are far too heavy for the kind of light-weight applications I have in mind; <em>note that I&#8217;ve had great success with Cheetah in the past </em></li>
<li>Some template engines, <a href="http://www.python.org/doc/2.6/library/string.html#format-string-syntax">such as that in Python 2.6</a>, are for too underfeatured</li>
</ul>
<p>However, if you&#8217;re really looking for the whole Django template experience and don&#8217;t want to use Djolt, just <a href="http://www.b-list.org/weblog/2007/sep/22/standalone-django-scripts/">start here</a>.</p>
<h4>How do I get it?</h4>
<p>Djolt is packaged as part of the <a href="http://code.google.com/p/pybm/">pybm</a> library.</p>
<h4>How do I use it?</h4>
<pre>import djolt

t = djolt.Template("""
&lt;ul&gt;
{% for name in names %}
&lt;li&gt;{{ name }}&lt;/li&gt;
{% endfor %}
&lt;/ul&gt;
""")
print t.Render({
    "names" : [ "Johnny", "Jack", "Ray", "Mary &amp; Sam", ]
})</pre>
<p>Which gives the results:</p>
<pre>&lt;ul&gt;
&lt;li&gt;Johnny&lt;/li&gt;
&lt;li&gt;Jack&lt;/li&gt;
&lt;li&gt;Ray&lt;/li&gt;
&lt;li&gt;Mary &amp;amp; Sam&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>Note the &#8220;autoescaping&#8221; of the <code>&amp;</code> character.</p>
<h4>What tags does it define?</h4>
<ul>
<li>autoescape/endautoescape</li>
<li>if/else/endif</li>
<li>equal/endequal</li>
<li>for/endfor</li>
<li>notequal/notendequal</li>
</ul>
<p>It does not implement blocks.</p>
<h4>What filters does it define?</h4>
<ul>
<li>add</li>
<li>cut</li>
<li>default (see otherwise below)</li>
<li>default_if_none</li>
<li>divisibleby</li>
<li>first</li>
<li>join</li>
<li>last</li>
<li>length</li>
<li>length_is</li>
<li>linebreaks</li>
<li>lower</li>
<li>pluralize</li>
<li>random</li>
<li>safe (respecting all the Django autoescape rules)</li>
<li>slug</li>
<li>upper</li>
</ul>
<p>Unimplemented filters are due to laziness and will be done &#8220;on demand&#8221;. We also introduce a few new filters:</p>
<ul>
<li> jslug &#8211; like slug, but more Javascript friendly</li>
<li> otherwise &#8211; like default, except the empty string/empty values trigger the filter also</li>
</ul>
<h4>Are their differences between Djolt and Django templates?</h4>
<ul>
<li>Djolt tags suck up whitespace if they&#8217;re on a line by themselves</li>
<li>If Djolt cannot resolve a variable, it resolves to the appropriate &#8220;empty&#8221; value (as opposed to failing). This is keeping in line with <a href="http://code.davidjanes.com/blog/category/work/">WORK</a> philosophy</li>
</ul>
<p>Beyond that you should be able to use most Django template examples (that don&#8217;t use block/implements) as-is.</p>
<h4>Is it extensible?</h4>
<p>Yes. You can add your own tags and filters by following the examples in code (<code>djolt_nodes.py</code> and <code>djolt_filters.py</code> respectively).</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/28/djolt-django-like-templates/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WORK &#8211; Web Object Records</title>
		<link>http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/#comments</comments>
		<pubDate>Tue, 11 Nov 2008 16:37:42 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[ideas]]></category>
		<category><![CDATA[pybm]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[semantic web]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=181</guid>
		<description><![CDATA[Introduction
As technologists, we&#8217;re all familiar with REST &#8211; Representational State Transfer:
Representational state transfer (REST) is a style of software architecture for distributed hypermedia systems such as the World Wide Web. As such, it is not strictly a method for building what are sometimes called &#8220;web services.&#8221; The terms “representational state transfer” and “REST” were introduced [...]]]></description>
			<content:encoded><![CDATA[<h4>Introduction</h4>
<p>As technologists, we&#8217;re all familiar with <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST &#8211; Representational State Transfer</a>:</p>
<p style="padding-left: 30px;"><strong>Representational state transfer</strong> (<strong>REST</strong>) is a style of <a title="Software architecture" href="http://en.wikipedia.org/wiki/Software_architecture">software architecture</a> for distributed <a title="Hypermedia" href="http://en.wikipedia.org/wiki/Hypermedia">hypermedia</a> systems such as the <a title="World Wide Web" href="http://en.wikipedia.org/wiki/World_Wide_Web">World Wide Web</a>. As such, it is not strictly a method for building what are sometimes called &#8220;<a class="mw-redirect" title="Web services" href="http://en.wikipedia.org/wiki/Web_services">web services</a>.&#8221; The terms “representational state transfer” and “REST” were introduced in <a title="2000" href="http://en.wikipedia.org/wiki/2000">2000</a> in the doctoral dissertation of <a title="Roy Fielding" href="http://en.wikipedia.org/wiki/Roy_Fielding">Roy Fielding</a>, <sup id="cite_ref-0" class="reference"><a href="http://en.wikipedia.org/wiki/Representational_State_Transfer#cite_note-0"></a></sup>one of the principal authors of the <a title="Hypertext Transfer Protocol" href="http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">Hypertext Transfer Protocol</a> (HTTP) specification.</p>
<p>REST talks about how we address and use information on the World Wide Web. I&#8217;d like to introduce the concept of<strong> WORK -  Web Object Records</strong> &#8211; which defines how we <em>think about data</em> being transmitted across the web.</p>
<p>WORK is <em>not</em> a descriptive standard &#8211; it is not telling you what to do, it&#8217;s describing what you <em>are</em> doing. The hope is that by having a delineated description of what we are doing, we can then write tools to cut through the babel of API standards being currently promulgated by a multitude of vendors; we can standardize the unstandarded.</p>
<h4>Defintion</h4>
<p>A WORK item:</p>
<ul>
<li>is conceptually a <a href="http://www.json.org/">JSON</a>-like dictionary, consisting of string keys and object values</li>
<li>each value in the dictionary is a (usually-) shallow JSON-like object, that is:
<ul>
<li>a dictionary, list or basic value type</li>
</ul>
</li>
<li>the basic value types are Unicode strings, floating point numbers, integers and booleans</li>
<li>the difference between strings and other basic value types is fuzzy (data encoded in XML, HTML form data)</li>
<li>null/None is rarely explicitly sent, instead it is the absence of a value being defined</li>
<li>the difference between a list of objects and a single object is fuzzy and fluid (XML children)</li>
<li>the data model defined implicitly by &#8220;what you see&#8221; is as useful as formal definition elsewhere</li>
<li>there are no cycles or explicit ways of cross referencing within a WORK item</li>
<li>WORK items can &#8211; and often are &#8211; nested within another WORK item, but only one level deep</li>
</ul>
<h4>Benefits</h4>
<p>Because we technologists inherently use a WORK model of data, it explains:</p>
<ul>
<li>why we prefer XML over CSV &#8211; because we like to store more that a single atomic value in a &#8220;cell&#8221;</li>
<li>why we prefer JSON to XML &#8211; because we think about data as JSON-like WORK objects, not as nested text constructs</li>
<li>why we don&#8217;t adopt RDF (in it&#8217;s variants) for transmitting data, implementing APIs and so forth &#8211; because we don&#8217;t think in graphs</li>
<li>why we find it easier to work with web data in Python and Ruby than in Java &#8211; because those languages explicitly use the same model for <em>storing</em> data as we <em>think</em> about the data</li>
</ul>
<h4>Examples</h4>
<p>Here are a few examples of how one can view common API / feed results as WORK items.</p>
<h5>RSS feeds</h5>
<p><a href="http://cyber.law.harvard.edu/rss/rss.html">RSS</a> is defined by a two level WORK hierarchy. The first level is:</p>
<pre>{
  "channel" : CHANNEL-WORK,
  "item" : [ ITEM-WORK, ITEM-WORK, ... ]
}</pre>
<p>A ITEM-WORK looks like:</p>
<pre>{
  "title" : STRING,
  "link" : STRING,
  "description" : STRING
}</pre>
<p>If you look at at the XML for a RSS feed with only 1 ITEM, there&#8217;s no way to tell without reading the spec than ITEM repeats. This is what we mean by saying that the difference between a single object and a list is sometimes fuzzy.</p>
<h5>White Pages API</h5>
<p>The <a href="http://www.whitepages.com/landing/api">White Pages API</a> is also a two level WORK hierarchy (this pattern is very very common). Here&#8217;s the first level, slightly more complicated than RSS due to the XML serialization:</p>
<pre>{
 "meta" : META-WORK,
 "listings" : {
   "listing" : [ LISTING-WORK, LISTING-WORK, ... ]
 }
}</pre>
<p>A LISTING-WORK looks like:</p>
<pre>{
  "geodata" : OBJECT,
  "phonenumbers" : OBJECT,
  "business" : { "businessname" : "Fred's Pizza" },
  "address" : OBJECT
}</pre>
<p>The OBJECTs above in the White Pages API are somewhat complicated, but tractable (as we shall see in another post)</p>
<h5>Amazon AWS API</h5>
<p>The <a href="http://aws.amazon.com/associates/">Amazon Associates Web Service</a> allows one to retrieve information about Amazon products via XML responses. The response is a little convoluted but still recognizable:</p>
<pre>{
 "Items" : {
   "RequestHeader" : REQUEST-HEADER-WORK,
   "Item" : [ ITEM-WORK, ITEM-WORK, ... ]
 },
 "OperationRequest" : { ... }</pre>
<p>The individual ITEM-WORK describe products:</p>
<pre>{
 "ASIN" : STRING,
 "ImageSets": {
   "ImageSet": {
    "LargeImage": {
     "URL": "http://ecx.images-amazon.com/images/I/31e55zf53VL.jpg",
     "Width": "300",
     "Height": "300"
   },
  },
 "ItemAttributes": {
   "Title": "Under a Blood Red Sky - Deluxe Edition CD/DVD",
   "Manufacturer": "Island",
   "ProductGroup": "Music",
   "Artist": "U2"
 }
}</pre>
<h5>Google search result</h5>
<p>We can also look at HTML pages as if they&#8217;re returning data as WORK items. This could be explicit if rules such as microformats or RDFa were used,  or once again it could be just a convenient way of modeling the data. Here&#8217;s a hypothetical WORK item for a <a href="http://www.google.ca/search?hl=en&amp;q=bombardier&amp;btnG=Google+Search&amp;meta=">single result returned from a Google</a>:</p>
<pre>{
 "title" : "Bombardier Inc. - Bombardier - Home",
 "url " : "http://www.bombardier.com/",
 "description" : "Manufacturers of a large range of regional...",
 "links" : [
  {
   "title" : "Careers",
   "url" : "...",
  },
  {
   "title" : "Business Aircraft",
   "url" : "...",
  },
  ...
 ]
}</pre>
<h4>Conclusion</h4>
<p>WORK gives us a powerful way of looking at &#8211; at simplifying &#8211; data that&#8217;s retrieved over the Internet via REST calls. If we can view API results as being made up of standardized components &#8211; WORK items &#8211; then the amount of work we need to do to work with <em>new </em>APIs can be absolutely minimized.</p>
<p>Designing and writing some of these tools is my next task.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
