<?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; work</title>
	<atom:link href="http://code.davidjanes.com/blog/category/work/feed/" rel="self" type="application/rss+xml" />
	<link>http://code.davidjanes.com/blog</link>
	<description></description>
	<lastBuildDate>Fri, 03 Feb 2012 00:49:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Atom as a Rosetta Stone for WORK objects</title>
		<link>http://code.davidjanes.com/blog/2009/01/19/atom-as-a-rosetta-stone-for-work-objects/</link>
		<comments>http://code.davidjanes.com/blog/2009/01/19/atom-as-a-rosetta-stone-for-work-objects/#comments</comments>
		<pubDate>Mon, 19 Jan 2009 11:31:04 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[pipe cleaner]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=408</guid>
		<description><![CDATA[WORK &#8211; Web Object Records &#8211; is a way of describing messages we pass over the web: a single header object called the &#8220;meta&#8221; and zero or more objects called &#8220;items&#8221;. Each object can be encoded as a JSON record, though we can access invidual items within each WORK object using a WORK Path which [...]]]></description>
			<content:encoded><![CDATA[<p><em><a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">WORK</a> &#8211; Web Object Records &#8211; is a way of describing messages we pass over the web: a single header object called the &#8220;meta&#8221; and zero or more objects called &#8220;items&#8221;. Each object can be encoded as a JSON record, though we can access invidual items within each WORK object using a <a href="http://code.davidjanes.com/blog/2008/11/21/work-paths/">WORK Path</a> which allows quite a bit of latitude for type coercision and vagarities in packaging.</em></p>
<p><a href="http://code.davidjanes.com/blog/category/pipe-cleaner/">Pipe Cleaner</a> is a project I&#8217;ve been working on for the last two months that allows one to script data using WORK, to accomplish tasks such as remixing and filtering RSS feeds, read or produce <a href="http://www.opml.org/">OPML</a>, make JSON interfaces and so forth. I actually have one live deployment which I will blog about soon and hope to have it beta productized for March.</p>
<p><a href="http://atomenabled.org/">Atom</a> is a standard for syndicating feeds, not unsimilar to RSS but with a richer better described vocabulary. I already have one major &#8220;project&#8221; built around Atom: the <a href="http://microformats.org/wiki/hatom">hAtom microformat</a> for describing microcontent and information that can be syndicated. hAtom has also been morphed by Microsoft to produce the <a href="http://microformats.org/wiki/hatom">Web Slice format</a>, so you may be seeing that about. Atom is conforms to WORK: there&#8217;s a &#8220;feed&#8221; meta header and zero or more &#8220;entry&#8221; items.</p>
<p>With Pipe Cleaner I&#8217;m trying not only to make a way where feeds and other data can be remixed, <em>but also make it easy to do so</em>! To do that, I&#8217;ve decided that be default, even though you are working with (say) OPML or RSS, we&#8217;ll translate all the terms to their Atom equivalents as best as possible. You&#8217;ll have to read the spec yourselves, but here&#8217;s a quick rundown of common elements, not all required by any means:</p>
<ul>
<li><code>author</code>, with possible sub-fields <code>uri</code> and <code>email</code></li>
<li><code>content</code> &#8211; the body</li>
<li><code>summary</code> &#8211; a summary of the body; currently my feeling is that content &amp; summary must always be HTML</li>
<li><code>updated</code> &#8211; when last updated</li>
<li><code>created</code> &#8211; when created, assume to be updated if not present</li>
<li><code>link</code> &#8211; the main URI</li>
<li><code>links</code> &#8211; for alternate URIs (this is a variance from the Atom spec; it should be easy to find the main URI for an element; I may reconsider this before release)</li>
<li><code>id</code> &#8211; a unique identifier</li>
<li><code>category</code> &#8211; tags, encoded in a sub-field term</li>
</ul>
<p>Note that I&#8217;m not slavish about making the output conformant to all the SHOULDs, MUSTs, etc. that are in the Atom spec: my pragmatic programming approach says &#8220;do the best we can&#8221; and if the user needs better, they can walk the extra mile.</p>
<p>Here&#8217;s some examples of data that&#8217;s been run through Pipe Cleaner, translating to Atom upon input and translating back to whatever is needed upon output. The JSON (actually pretty printed JSON) output is the most instructive for what&#8217;s going to inside Pipe Cleaner.</p>
<h4>RSS Feed</h4>
<ul>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/rss.original.xml">source rss</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/rss.json.txt">rss -&gt; json</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/rss.opml.xml">rss -&gt; opml</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/rss.rss.xml">rss -&gt; rss</a></li>
</ul>
<h4>OPML Data</h4>
<p>Note how the OPML is &#8220;flattened&#8221;, with hierarchy being encoded into the Category. This can be turned off if needed.</p>
<ul>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/opml.original.xml">source opml</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/opml.json.txt">opml -&gt; json</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/opml.opml.xml">opml -&gt; opml</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/opml.rss.xml">opml -&gt; rss</a></li>
</ul>
<h4>hCard microformat (in HTML)</h4>
<p>Note the neat namespacing in the RSS output. The OPML is almost devoid of useful information, further consideration is needed.</p>
<ul>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcard.original.html">source hcard</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcard.json.txt">hcard -&gt; json</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcard.opml.xml">hcard -&gt; opml</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcard.rss.xml">hcard -&gt; rss</a></li>
</ul>
<h4>hCalendar microformat (in HTML)</h4>
<p>Similar to hCard. We&#8217;ll probably also (or exclusively) encode the hCalendar data in an <a href="http://en.wikipedia.org/wiki/XCal">xCal</a> extension.</p>
<ul>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcalendar.original.html">source hcalendar</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcalendar.json.txt">hcalendar -&gt; json</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcalendar.opml.xml">hcalendar -&gt; opml</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hcalendar.rss.xml">hcalendar -&gt; rss</a></li>
</ul>
<h4>hAtom microformat (in HTML)</h4>
<p>hAtom -&gt; RSS is basically turning an hAtom page into a feed!</p>
<ul>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hatom.original.html">source hatom</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hatom.json.txt">hatom -&gt; json</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hatom.opml.xml">hatom -&gt; opml</a></li>
<li><a href="http://code.davidjanes.com/examples/2009-01-19/xlate/hatom.rss.xml">hatom -&gt; rss</a></li>
</ul>
<h4>Source example</h4>
<p>Since no blog post is complete without a little source code, here&#8217;s a Pipe Cleaner script to parse the hCard document. If you&#8217;re following closely, the output format is selected by the user at runtime. All the other scripts are of similar terseness.</p>
<pre>import module:api_microformat;
api_microformat.HCard uri:"http://tantek.com/" to:items meta:meta;</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2009/01/19/atom-as-a-rosetta-stone-for-work-objects/feed/</wfw:commentRss>
		<slash:comments>0</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>A brief survey of Yahoo Pipes as a DQT</title>
		<link>http://code.davidjanes.com/blog/2008/12/11/brief-survey-of-yahoo-pipes/</link>
		<comments>http://code.davidjanes.com/blog/2008/12/11/brief-survey-of-yahoo-pipes/#comments</comments>
		<pubDate>Thu, 11 Dec 2008 12:19:55 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[djolt]]></category>
		<category><![CDATA[dqt]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[semantic web]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=325</guid>
		<description><![CDATA[Yahoo Pipes is a visual editor of mashups, allowing you to take data from sources on the net, transform them in various interesting ways and output the result as Atom, RSS or JSON. The primary downside Pipes of course is that you&#8217;re totally dependent on Yahoo for the infrastructure: it runs at Yahoo pulling feeds [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://code.davidjanes.com/examples/2008-12-13/pipes.png" alt="MacFUSE" style="border: 0 0 10px 10px; float: right;" /><a href="http://pipes.yahoo.com/">Yahoo Pipes</a> is a visual editor of mashups, allowing you to take data from sources on the net, transform them in various interesting ways and output the result as Atom, RSS or JSON. The primary downside Pipes of course is that you&#8217;re totally dependent on Yahoo for the infrastructure: it runs at Yahoo pulling feeds that have to be accessable through the public Internet.</p>
<p>It&#8217;s easy to use Pipes: just <a href="http://pipes.yahoo.com/pipes/docs?doc=overview">go to this page</a> and start working with the sample example Pipe. You&#8217;ll need a Yahoo login ID, but most of us have that anyway. I&#8217;ve created an example that uses Yahoo Pipes to feed a Djolt template <a href="http://code.davidjanes.com/examples/2008-12-11/dqt2/">which you can see here</a>.</p>
<p>We can analyze Pipes in the terms of <a href="http://code.davidjanes.com/blog/2008/12/09/introducing-dqt-dataquerytransformtemplate/">the DQT paradigm we&#8217;ve outlined in the previous post</a>.</p>
<h4>Data Sources and Queries</h4>
<p>Sources and Queries are merged (quite logically) in the Pipes interface. <a href="http://pipes.yahoo.com/pipes/docs?doc=sources">You can read in depth documentation here</a>.</p>
<ul>
<li>Fetch CSV</li>
<li>Feed Autodiscovery &#8211; outputs syndication feeds found on a page (<a href="http://pipes.yahoo.com/pipes/pipe.info?_id=jAZaeHvH3RGDaUk__w6H4A">RSS feeds on a CBC page</a>)</li>
<li>Fetch Feed</li>
<li>Fetch Page &#8211; will read a page and parse the contents with a reg</li>
<li>Fetch Site Feed &#8211; this is the logical combination of Fetch Feed and Fetch Autodiscovery</li>
<li>Flickr &#8211; find images by tag near a location (<a href="http://pipes.yahoo.com/pipes/pipe.info?_id=oPG38nvH3RG0QpVRrbQIDg">photos of cats in Toronto</a>)</li>
<li>Google Base &#8211; look up information in Google Base</li>
<li>Item Builder &#8211; a way of building new items from existing items</li>
<li>Yahoo Local</li>
<li>Yahoo Search</li>
</ul>
<h4>Transforms</h4>
<p>The <a href="http://pipes.yahoo.com/pipes/docs?doc=operators">operator documentation can be read here</a>.</p>
<ul>
<li>Count</li>
<li>Filter</li>
<li>Location Extractor &#8211; a geocoder that magically looks for locations</li>
<li>Loop</li>
<li>Regex</li>
<li>Rename</li>
<li>Reverse</li>
<li>Sort</li>
<li>Split</li>
<li>Sub-element &#8211; pulls a particular sub-element of an item and makes that the item. This is very much like WORK path manipulation</li>
<li>Tail</li>
<li>Truncate</li>
<li>Union</li>
<li>Unique</li>
<li>Web Service</li>
</ul>
<p>Plus a number of specialized data services, for dealing with elements such as dates.</p>
<h4>Templates</h4>
<p>Pipes does not provide an arbitrary Djolt-like template producing HTML. Instead, they provide a number of pre-made code templates that output well known data types, including RSS, JSON and Atom (and some stranger choices, like PHP).</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/12/11/brief-survey-of-yahoo-pipes/feed/</wfw:commentRss>
		<slash:comments>0</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 [...]]]></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>Toronto Fires</title>
		<link>http://code.davidjanes.com/blog/2008/11/22/toronto-fires/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/22/toronto-fires/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 21:19:58 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[djolt]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[maps]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=249</guid>
		<description><![CDATA[Here&#8217;s a little mashup I&#8217;ve been putting together for the last few days: Toronto Fires. It&#8217;s taking the data listed here on the City of Toronto&#8217;s Fire Services &#8220;Active Accidents&#8221;, scraping it (by pretending HTML is XHTML and treating it as WORK objects), geocoding it (using our WORK Google API) and mapping it (using this [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a little mashup I&#8217;ve been putting together for the last few days: <a href="http://code.davidjanes.com/examples/2008-11-22/fires/">Toronto Fires</a>.</p>
<p>It&#8217;s taking the data listed here on the <a href="http://www.toronto.ca/fire/cadinfo/livecad.htm">City of Toronto&#8217;s Fire Services &#8220;Active Accidents&#8221;</a>, scraping it (by pretending HTML is XHTML and treating it as <a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">WORK</a> objects), geocoding it (using our <a href="http://code.davidjanes.com/blog/2008/11/18/work-api-teaser-iii-google-api/">WORK Google API</a>) and mapping it (using <a href="http://code.davidjanes.com/blog/category/maps/">this information</a>).</p>
<p>This is very much a work in progress, but here&#8217;s a few more things that are involved:</p>
<ul>
<li>we read <code>body.table.tr.td[1].table.tr[1].td.table.tr</code> as a list to get the rows in the table</li>
<li>we map those rows into the Geocoder use a new magic technology we&#8217;ll be explaining in the next few days: <a href="http://www.djangoproject.com/">Djolt</a> &#8211; <a href="http://www.djangoproject.com/">Django</a>-like <a href="http://docs.djangoproject.com/en/dev/ref/templates/builtins/">templates</a></li>
<li>the output program is just one big Djolt template</li>
</ul>
<p>I&#8217;m not quite satisfied with how the current page is constructed: I want the final result to be much more simple.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/22/toronto-fires/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WORK paths</title>
		<link>http://code.davidjanes.com/blog/2008/11/21/work-paths/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/21/work-paths/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 21:03:46 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[ideas]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=244</guid>
		<description><![CDATA[A WORK object is simply a way of looking of any JSON-like dictionary &#8211; it&#8217;s an &#8220;attitude&#8221;. The primary difference is in how we use that dictionary, especially in the context of using APIs. Here&#8217;s a rough overview of the thre the WORK is the interface &#8211; we don&#8217;t need to write specialized methods to [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">WORK object</a> is simply a way of looking of any <a href="http://www.json.org/">JSON</a>-like dictionary &#8211; it&#8217;s an &#8220;attitude&#8221;. The primary difference is in how we use that dictionary, especially in the context of using APIs. Here&#8217;s a rough overview of the thre</p>
<ul>
<li>the WORK <em>is </em>the interface &#8211; we don&#8217;t need to write specialized methods to deal with an API because we know what we&#8217;re looking for anyway. It&#8217;s not like we spend weeks looking at our API interface &#8211; typically, it&#8217;d be more minutes (once it&#8217;s coded) in a typically programming session</li>
<li>what is in the WORK is defined by how we want to use it. For example, if we want an Integer, we ask for an integer for the WORK: it may be stored as a string, a boolean, an integer, or a float; it doesn&#8217;t matter. When using WORK objects we expect to the conversion to be done for us at runtime</li>
<li>if you are looking for a list in the WORK and there&#8217;s another type of object, we pretend that it&#8217;s in a list of length 1</li>
<li>if you are looking for an object (by key) and you find a list, look in the first object in the list</li>
</ul>
<p>These rules are written from a pragmatic vision of using APIs: data is sometimes in lists, sometimes it isn&#8217;t. Sometimes we know the types being sent on the wire, sometimes it&#8217;s just strings.</p>
<p>In order to use WORK objects efficiently, we define a &#8220;dot-path&#8221; for accessing items that may be hierarchically nested. We&#8217;ll address the type coercion issue in another post. To illustrate our point, we&#8217;ll be working with the following WORK object</p>
<pre>{
  "name" : "Sally Jones",
  "age" : 22,
  "hobbies" : [ "Skiing", "Windsurfing", "Chillaxing" ],
  "sites" : {
    "facebook" : "http://www.facebook.com",
    "gmail" : "http://gmail.com",
  },
  "address" : [
    {
      "street" : "1 Main Street",
      "city", "Toronto",
      "province" : "Ontario",
    },
    {
      "street" : "RR4",
      "city", "Bala",
      "province" : "Ontario",
    }
  ]
}</pre>
<p>Here&#8217;s a few dot-paths and the value they&#8217;ll retrieve:</p>
<ul>
<li>path: <code>name</code><br />
value: <code>"Sally Jones"</code></li>
<li>path: <code>hobbies</code><br />
value: <code>[ "Skiing", "Windsurfing", "Chillaxing" ]</code></li>
<li>path: <code>hobbies[1]</code><br />
value: <code>"Windsurfing"</code></li>
<li>path: <code>address.street</code><br />
value: <code>"1 Main Street"</code><br />
&#8230; this demonstrates seeing a list where we want a dictionary and just looking at the first object in the list</li>
<li>path: <code>sites[0].facebook</code><br />
value: <code>"http://www.facebook.com"</code><br />
&#8230; this is an example of looking a list, not finding it and assuming there&#8217;s an list of length 1 there. <code>sites[1].facebook</code> would return null.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/21/work-paths/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Work API Teaser III &#8211; Google API</title>
		<link>http://code.davidjanes.com/blog/2008/11/18/work-api-teaser-iii-google-api/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/18/work-api-teaser-iii-google-api/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 10:26:50 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=229</guid>
		<description><![CDATA[Here&#8217;s an example of implementing an API with many different endpoints. It&#8217;s the Google AJAX Search API which lets you access all of Google&#8217;s search engines programmatically! A few notes: In the Javascript API Google provides &#8220;branding&#8221; functions to make sure search results are properly attributed. There doesn&#8217;t seem to be a corresponding AJAX call [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s an example of implementing an API with many different endpoints. It&#8217;s the <a href="http://code.google.com/apis/ajaxsearch/documentation/reference.html#_intro_fonje">Google AJAX Search API</a> which lets you access all of Google&#8217;s search engines programmatically! A few notes:</p>
<ul>
<li>In the Javascript API Google provides &#8220;branding&#8221; functions to make sure search results are properly attributed. There doesn&#8217;t seem to be a corresponding AJAX call &#8212; that is, it&#8217;s probably implemented directly in the Javascript &#8212; but I&#8217;d still like to provide a corresponding function. It would be nice if API providers actually gave a branding end-point</li>
<li>The code doesn&#8217;t support (yet) multi-page results: coming soon</li>
<li>The clever bit is in <code>_item_path</code>, which describes how to pull <a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">WORK</a> result objects out of the AJAX result</li>
<li>all this code is actually available right now, via SVN: the instructions are <a href="http://code.google.com/p/pybm/source/checkout">here</a>. This library is standalone (and is in fact the basis for many of the other projects I have on Google code)</li>
<li>The Google API requires a <code>_http_referer</code>: the URL of the site that&#8217;s using the results</li>
<li>The Google API <em>does not</em> require an API key, but you can pass one (in the constructor or in individual search calls) under the key <code>api_key</code>. <em>You can use the same API key that <a href="http://code.davidjanes.com/blog/2008/11/07/how-to-use-the-google-maps-api/">you&#8217;ve created for Google Maps</a>.</em></li>
</ul>
<p>Here&#8217;s the Google API class: quite simple. I&#8217;ll probably extend each individual search function to provide all the known parameters by name, rather than passing in a <code>**ad</code> catch-all.</p>
<pre>class Google(bm_api.API):
    _base_query = {
        "v" : "1.0",
    }

    _item_path = "responseData.results"
    _meta_path = "responseData.cursor"
    _convert2work = bm_work.JSON2WORK()

    def __init__(self, _http_referer, **ad):
        bm_api.API.__init__(self, _http_referer = _http_referer, **ad)

    def WebSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/web"
        self.SearchOn(q = q, **ad)

    def LocalSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/local"
        self.SearchOn(q = q, **ad)

    def VideoSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/video"
        self.SearchOn(q = q, **ad)

    def BlogSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/blogs"
        self.SearchOn(q = q, **ad)

    def NewsSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/news"
        self.SearchOn(q = q, **ad)

    def BookSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/books"
        self.SearchOn(q = q, **ad)

    def ImageSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/images"
        self.SearchOn(q = q, **ad)

    def PatentSearch(self, q, **ad):
        self._uri_base = "http://ajax.googleapis.com/ajax/services/search/patentNew"
        self.SearchOn(q = q, **ad)</pre>
<p>Here&#8217;s how you use it:</p>
<pre>
api_key = os.environ["GMAPS_APIKEY"]
referer = "http://code.davidjanes.com"
query = "Paris Hilton"

api = Google(key = api_key, _http_referer = referer)
api.VideoSearch(query)

for item in api.IterItems():
    pprint.pprint(item)
</pre>
<p>Here&#8217;s an example of a results, searching for &#8220;Paris Hilton&#8221; in Videos. I tried searching in Patents without luck.</p>
<pre>{'@Index': 0,
 '@Page': 1,
 u'GsearchResultClass': u'GvideoSearch',
 u'content': u"Paris Hilton's new video clip for 'Nothing In This World'",
 u'duration': u'204',
 u'playUrl': u'http://www.youtube.com/v/...',
 u'published': u'Thu, 12 Oct 2006 09:33:23 PDT',
 u'publisher': u'www.youtube.com',
 u'rating': u'4.52872',
 u'tbHeight': u'240',
 u'tbUrl': u'http://0.gvt0.com/vi/Ki2M3-2W-cQ/0.jpg',
 u'tbWidth': u'320',
 u'title': u'Paris Hilton - Nothing In This World',
 u'titleNoFormatting': u'Paris Hilton - Nothing In This World',
 u'url': u'http://www.google.com/url?q=...',
 u'videoType': u'YouTube'}</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/18/work-api-teaser-iii-google-api/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Work API Teaser II &#8211; Praized API</title>
		<link>http://code.davidjanes.com/blog/2008/11/12/work-api-teaser-ii-praized-api/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/12/work-api-teaser-ii-praized-api/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 23:46:19 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[demo]]></category>
		<category><![CDATA[ideas]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[semantic web]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=212</guid>
		<description><![CDATA[Implementing a merchant search using the Praized API took about 10 minutes (mainly finding the right documentation), using my WORK framework: class PraizedMerchants(bm_api.API): """See: http://code.google.com/p/praized/wiki/A_Second_Tutorial_Search""" _uri_base = "http://api.praized.com/apitribe/merchants.xml" _meta_path = "community" _item_path = "merchants.merchant" _page_max_path = 'pagination.page_count' _page_max = -1 def __init__(self, api_key, slug = "apitribe", **ad): bm_api.API.__init__(self, api_key = api_key, **ad) self._uri_base = "http://api.praized.com/%s/merchants.xml" [...]]]></description>
			<content:encoded><![CDATA[<p>Implementing a merchant search using the <a href="http://praizedmedia.com/">Praized</a> <a href="http://praizedmedia.com/en/api">API</a> took about 10 minutes (<a href="http://code.google.com/p/praized/wiki/A_Second_Tutorial_Search">mainly finding the right documentation</a>), using my WORK framework:</p>
<pre>class PraizedMerchants(bm_api.API):
    """See: http://code.google.com/p/praized/wiki/A_Second_Tutorial_Search"""

    _uri_base = "http://api.praized.com/apitribe/merchants.xml"
    _meta_path = "community"
    _item_path = "merchants.merchant"
    _page_max_path = 'pagination.page_count'
    _page_max = -1

    def __init__(self, api_key, slug = "apitribe", **ad):
        bm_api.API.__init__(self, api_key = api_key, **ad)

        self._uri_base = "http://api.praized.com/%s/merchants.xml" % slug

    def CustomizePageURI(self, page_index):
        if page_index &gt; 1:
            return  "page=%s" % page_index</pre>
<p>Partially hardcoding &#8216;apitribe&#8217; as a &#8216;community slug&#8217; is probably a bad idea. Anyhoo, here&#8217;s how you call it&#8230;</p>
<pre>api_key = os.environ["PRAIZED_APIKEY"]
api = PraizedMerchants(api_key = api_key, slug = "david-janess-code")
api.SearchOn(
    q = "Bistro",
    l = "Toronto",
)
for item in api.IterItems():
    print json.dumps(item, indent = 1)</pre>
<p>&#8230; and a set if results, somewhat edited below. I&#8217;ll have to figure out what that &#8220;permalink&#8221; is all about (I&#8217;ve edited it to shorten it)  &#8230; it could be something neat, but I haven&#8217;t quite grasped all the ins and outs of what Praized wants to accomplish as a business.</p>
<pre>{
 "@Index": 0,
 "@Page": 1,
 "short_url": "http://przd.com/zAU-7",
 "pid": "af5bebd604f3d1517a8113e0a2e8cc58",
 "updated_at": "2008-10-04T20:49:34Z",
 "phone": "(416) 585-7896",
 "permalink":
   ".../praized/places/ca/ontario/toronto/coffee-supreme-bistro?l=Toronto&amp;q=Bistro",
 "name": "Coffee Supreme Bistro",
 "created_at": "2008-10-04T20:49:34Z",
 "location": {
  "city": {
   "name": "Toronto"
  },
  "country": {
   "code": "CA",
   "name_fr": "Canada",
   "name": "Canada"
  },
  "longitude": "-79.384071",
  "regions": {
   "province": "Ontario"
  },
  "postal_code": "M5J 1T1",
  "latitude": "43.646347",
  "street_address": "40 University Avenue"
 }
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/12/work-api-teaser-ii-praized-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WORK API Teaser</title>
		<link>http://code.davidjanes.com/blog/2008/11/12/work-teaser/</link>
		<comments>http://code.davidjanes.com/blog/2008/11/12/work-teaser/#comments</comments>
		<pubDate>Wed, 12 Nov 2008 14:41:38 +0000</pubDate>
		<dc:creator>David Janes</dc:creator>
				<category><![CDATA[ideas]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[semantic web]]></category>
		<category><![CDATA[work]]></category>

		<guid isPermaLink="false">http://code.davidjanes.com/blog/?p=206</guid>
		<description><![CDATA[Following from the concepts I wrote about yesterday, here&#8217;s two examples of API parsers using a WORK model. RSS 2.0 Class definition &#8211; that&#8217;s the whole thing there!: class RSS20(API): _item_path = "channel.item" _meta_path = "channel" def __init__(self, uri): API.__init__(self) self._uri_base = uri Using it: api = RSS20(uri = 'http://feeds.feedburner.com/DavidJanesCode') for item in api.IterItems(): print [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.davidjanes.com/blog/2008/11/11/work-web-object-records/">Following from the concepts I wrote about yesterday</a>, here&#8217;s two examples of API parsers using a <a href="http://code.davidjanes.com/blog/category/work/">WORK</a> model.</p>
<h4>RSS 2.0</h4>
<p>Class definition &#8211; that&#8217;s the whole thing there!:</p>
<pre>class RSS20(API):
    _item_path = "channel.item"
    _meta_path = "channel"

    def __init__(self, uri):
        API.__init__(self)

        self._uri_base = uri</pre>
<p>Using it:</p>
<pre>api = RSS20(uri = 'http://feeds.feedburner.com/DavidJanesCode')
for item in api.IterItems():
    print "-", item['title']</pre>
<p>Results:</p>
<pre>- WORK - Web Object Records
- Syntax Error on Line 1
- Adding MapField to inputEx
- Switching between mapping APIs and universal zoom levels
- How to dynamically load map APIs
- How to use the Google Maps API
- How to use the Microsoft Virtual Earth API
- Tip - how to get your browser’s User Agent
- How to use the MapQuest API
- How to use the Yahoo Maps Service AJAX API
- How to detect internal link jumps
- GenX - first public demonstration
- Amazon’s OpenSearch: mostly useless
- More style updates
- How to do multi-column multilingual full text searching in Oracle
- Tip - fixing broken menus over form on IE6 and IE7
- New style for this weblog
- AUMFP - Demo
- Tip - use mod_rewrite to redirect to subdirectory
- AUMFP - The Almost Universal Microformats Parser</pre>
<h4>Amazon ECS</h4>
<p>This will probably end up replacing <a href="http://code.davidjanes.com/blog/2008/10/19/pyecs-the-python-amazon-ecs-api/">PyECS</a>!</p>
<p>Class definition:</p>
<pre>class AmazonECS(API):
    _base_query = {
        "Sort" : "relevancerank",
        "Operation" : "ItemSearch",
        "Version" : "2008-08-19",
        "ResponseGroup" : [ "Small", ],
    }
    _uri_base = "http://ecs.amazonaws.com/onca/xml"
    _meta_path = "Items.Request"
    _item_path = "Items.Item"
    _page_max_path = 'Items.TotalPages'
    _item_max_path = 'Items.TotalResults'
    _page_max = -1

    def __init__(self, **ad):
        API.__init__(self, **ad)

    def CustomizePageURI(self, page_index):
        if page_index == 1:
            return

        return  "%s=%s" % ( "ItemPage", page_index )</pre>
<p>Using it:</p>
<pre>api = AmazonECS(AWSAccessKeyId = os.environ["AWS_ECS_ACCESSKEYID"])
api.SearchOn(
    Keywords = "Larry Niven",
    SearchIndex = "Books",
    Condition = "New",
)
for item in api.IterItems():
    print "-", item['ItemAttributes.Title']</pre>
<p>Results &#8230; note that this fetching many pages of results:</p>
<pre>- Fleet of Worlds
- Juggler of Worlds
- Escape from Hell
- Inferno
- N-Space
- The Ringworld Engineers (Ringworld)
- The Draco Tavern
- Legacy of Heorot: Legacy of Heorot
- Footfall
- A WORLD OUT OF TIME (ORBIT BOOKS)
- The Burning City (Hardback)
- Protector
- Burning Tower
- Three Books of Known Space
- Ringworld Throne
- Tales of Known Space: The Universe of Larry Niven
- Scatterbrain
- Ringworld
- Lucifer's Hammer
<em>... (continues) ...</em></pre>
]]></content:encoded>
			<wfw:commentRss>http://code.davidjanes.com/blog/2008/11/12/work-teaser/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

