<?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>THENSYS</title>
	<atom:link href="http://www.thensys.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://www.thensys.com</link>
	<description>We are the music-makers, And we are the dreamers of dreams</description>
	<lastBuildDate>Wed, 09 Feb 2011 23:21:17 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Installing Python Packages on Newer Ubuntu&#8217;s with easy_install</title>
		<link>http://www.thensys.com/?p=90</link>
		<comments>http://www.thensys.com/?p=90#comments</comments>
		<pubDate>Wed, 09 Feb 2011 23:20:29 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=90</guid>
		<description><![CDATA[for the longest time I&#8217;ve been installing packages using &#8211;prefix=/usr/local with easy_install. This seems to be the correct place to put them packages, since they are not managed by Ubuntu.
Newer versions of Ubuntu have split /usr/local/lib/pythonX.X/site-packages into 2.
/usr/local/lib/pythonX.X/site-packages works with versions of python installed that are not part of the base system (under /usr/local/bin/python) and [...]]]></description>
			<content:encoded><![CDATA[<p>for the longest time I&#8217;ve been installing packages using &#8211;prefix=/usr/local with easy_install. This seems to be the correct place to put them packages, since they are not managed by Ubuntu.</p>
<p>Newer versions of Ubuntu have split /usr/local/lib/pythonX.X/site-packages into 2.</p>
<p>/usr/local/lib/pythonX.X/site-packages works with versions of python installed that are not part of the base system (under /usr/local/bin/python) and /usr/local/lib/pythonX.X/dist-packages is for user-installed packages that use the version of python that ships with Ubuntu.</p>
<p>I personally use the Python the operating system comes from, so if I want to install packages using easy_install the right command is:</p>
<pre>
 easy_install --prefix=/usr/local  \
      --install-dir=/usr/local/lib/python2.6/dist-packages PACKAGE-NAME
</pre>
<p>the &#8211;prefix will take care of scripts and data while &#8211;install-dir will take care of the non-standard site-packages.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=90</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing Framework-less Python WSGI Applications for Fun and Profit</title>
		<link>http://www.thensys.com/?p=72</link>
		<comments>http://www.thensys.com/?p=72#comments</comments>
		<pubDate>Fri, 23 Jul 2010 03:33:03 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Software Design]]></category>
		<category><![CDATA[WSGI]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=72</guid>
		<description><![CDATA[Learn how to write well structured Python WSGI web applications without using a framework. ]]></description>
			<content:encoded><![CDATA[<p>After writing WSGI applications over the past year or so, I&#8217;ve decided that the best general strategy to approach application design is to think of each request with the following steps:</p>
<div style='width:203px; margin: 0px auto'>
  <img src="http://www.thensys.com/wp-content/uploads/2010/07/wsgi-site-design.png" alt="Logical organization of WSGI middleware" />
</div>
<p>Every block of the diagram is a WSGI application (middleware) save the adapter and request handler. Here is an overview of each block:</p>
<h3>Common Middleware</h3>
<p>Common Middleware applies to all requests across the entire site. This may be none or many. For intranet systems, common middleware includes session management (beaker), authentication/login screen, and user tracking. For a public site, common middleware could be gzip compression or localization negotiation. Nearly all sites will have some exception handling middleware that emails you when something AWFUL happens (Ooops!).</p>
<p>This is also a common place to put middleware that handles specific exceptions that triggers actions. This style of programming may be controversial in some circles, but no one can deny the practical benefit of being able to raise HTTPRedirect(&#8217;/login&#8217;) from any where and have it send the user to the given screen. I could actually write a whole post on designing site-wide middleware. Some day I just might!</p>
<h3>Dispatcher</h3>
<p>The purpose of the dispatcher is to examine the incoming request and invoke another WSGI application to handle the request. There are quite a few existing dispatching modules floating around the net, and I&#8217;ve written a few myself. I&#8217;ll explore them later, but I want to make one point: routes is not a dispatcher. Routes would be common middleware that sets an environ variable (routing_args) that would be used by a dispatcher to find a handler. The publicly-available dispatcher I&#8217;ve had the most experience with is Ian Bicking&#8217;s paste.urlparser. I&#8217;ve used it to good effect.</p>
<p>Object-request brokers (ORB&#8217;s) also fall into this category. I&#8217;ll just say that the ORB should invoke a method on an object with a WSGI interface. Everything should be WSGI all the way until the very final step.</p>
<h3>Application Middleware</h3>
<p>Now, for some requests, the WSI application that is invoked by the dispatcher is the end of the road. It handles the request and that is that. However, one is missing out on many time saving (and code saving) layers that can be built here.</p>
<p>The most common application middleware I&#8217;ve used is secondary dispatching middleware. Let&#8217;s say that you&#8217;re doing a good old HTML form with submit handler. The best thing to do here is to use an application-level dispatcher that works on HTTP Method. I have a module with 3 WSI applications. The site dispatcher sends the request to the &#8220;main&#8221; WSGI application. This WSGI application then sends the request to one of the other 2 dispatchers depending on the REQUEST_METHOD. Something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">application = MethodDispatch<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
@application
<span style="color: #ff7700;font-weight:bold;">def</span> get<span style="color: black;">&#40;</span>start_response, environ<span style="color: black;">&#41;</span>:
     <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
@application
<span style="color: #ff7700;font-weight:bold;">def</span> post<span style="color: black;">&#40;</span>start_response, environ<span style="color: black;">&#41;</span>:
     <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>There are countless other ways of deciding different applications to run, but this is just to wet the appetite. I know their are &#8220;everything and the kitchen sink&#8221; dispatching systems that could take care of this a level up, but I like the locality of this approach. Like all the other categories, there is a lot more I can say about this block. Another time!</p>
<h3>Request-specific Middleware</h3>
<p>Request middleware applies to a single request made by the browser. I have found that decorators are a great way to introduce middleware at the request level. It&#8217;s hard to talk about request-specific middleware without also talking about adapters, so I&#8217;ll move on.</p>
<h3>Adapters</h3>
<p>An adapter breaks the chain from WSGI to another interface. WSGI is great as a standard, but trying to write your application logic using it as an interface is not very fun. Adapters are right at the top of ways I increase my productivity writing these web applications. The idea is simple: What kind of interface works best for this particular kind of request?</p>
<p>If the request is for JSON data. It might be best to have the procedure return a data structure that is turned into JSON and sent back to the browser. If a mako template gets used to render a HTML page, maybe a good interface would be to have a mako object passed into the request handler so that it can populate the template with data. When the request ends, the mako template is automatically rendered.</p>
<p>These adapters should not be generalized solutions to fit everyone&#8217;s potential use cases. They are very easy to write yourself. If you have a few ways mako templates can be handled, have a few different mako adapters. In the past, I&#8217;ve tried to write complex, catch-all type adapters. I&#8217;ve learned that simple, application-specific adapters are definitely the way to go.</p>
<p>Application-specific middleware can be used in tandem with adapters to augment the adapters functionality. The middleware can do something before or after the adapter (and handler) runs, so you can customize to your hearts content. As always though KISS!</p>
<p>To give an example of adapters and application middleware in action, here is a piece of real code:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> app.<span style="color: black;">wsgilib</span> <span style="color: #ff7700;font-weight:bold;">as</span> W
reg = W.<span style="color: black;">PathDispatch</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
application = reg.<span style="color: black;">get_wsgi_app</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
@reg.<span style="color: black;">default</span>
@W.<span style="color: black;">mako</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ppayment.tmpl'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span>req, res<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
@reg
@W.<span style="color: black;">json</span>
<span style="color: #ff7700;font-weight:bold;">def</span> trans_search<span style="color: black;">&#40;</span>req, res<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> eq<span style="color: black;">&#40;</span>key, field, values<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;%s = %%s&quot;</span> <span style="color: #66cc66;">%</span> field<span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span>values<span style="color: black;">&#91;</span>key<span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> ilike<span style="color: black;">&#40;</span>key, field, values<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;%s ILIKE %%s&quot;</span> <span style="color: #66cc66;">%</span> field<span style="color: black;">&#93;</span>, <span style="color: black;">&#91;</span>values<span style="color: black;">&#91;</span>key<span style="color: black;">&#93;</span><span style="color: black;">&#93;</span>
    <span style="color: #808080; font-style: italic;"># Tons of SQL/database code snipped</span>
    res<span style="color: black;">&#91;</span><span style="color: #483d8b;">'sql'</span><span style="color: black;">&#93;</span> = sql
    res<span style="color: black;">&#91;</span><span style="color: #483d8b;">'transactions'</span><span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span><span style="color: #008000;">dict</span><span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> cursor<span style="color: black;">&#93;</span></pre></div></div>

<p>here W.json and W.mako adapt the WSGI interface into a more application-programmer friendly interface. I&#8217;m creating webob request objects and custom derived webob response objects as arguments for the request handler. PathDispatch is just a simple dispatcher that selects a registered method based on what&#8217;s in PATH_INFO.</p>
<p>When I say simple, I mean &#8220;SIMPLE&#8221;</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> PathDispatch<span style="color: black;">&#40;</span><span style="color: #008000;">dict</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__call__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, func<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'/%s'</span> <span style="color: #66cc66;">%</span> func.__name__<span style="color: black;">&#93;</span> = func
        <span style="color: #ff7700;font-weight:bold;">return</span> func
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> default<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, func<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span><span style="color: black;">&#91;</span><span style="color: #008000;">None</span><span style="color: black;">&#93;</span> = func
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> lookup<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, path_info<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span><span style="color: black;">&#91;</span>path_info<span style="color: black;">&#93;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyError</span>:
            <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span><span style="color: black;">&#91;</span><span style="color: #008000;">None</span><span style="color: black;">&#93;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> get_wsgi_app<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> wsgi<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">app</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> app<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, req, res<span style="color: black;">&#41;</span>:
        proc = <span style="color: #008000;">self</span>.<span style="color: black;">lookup</span><span style="color: black;">&#40;</span>req.<span style="color: black;">path_info</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> proc<span style="color: black;">&#40;</span>req, res<span style="color: black;">&#41;</span></pre></div></div>

<p>The simplicity of this utility code is key. It should be easy and fun to hack on, transparent and not require a huge cognitive load to understand.</p>
<p>I&#8217;ve only scratched the surface. I hope to explore each level in greater detail in future posts!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=72</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pausing the terminal in an OS independent way in Python</title>
		<link>http://www.thensys.com/?p=66</link>
		<comments>http://www.thensys.com/?p=66#comments</comments>
		<pubDate>Tue, 15 Jun 2010 20:13:01 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=66</guid>
		<description><![CDATA[
import os
import sys
import tty
&#160;
def pause&#40;&#41;:
    &#34;&#34;&#34; Prompt the user to press a key to continue. Should probably use a pager
    most of the time though.
    &#34;&#34;&#34;
    if sys.platform in &#40;'win32', 'win64'&#41;:
        os.system&#40;'PAUSE'&#41;
    elif [...]]]></description>
			<content:encoded><![CDATA[
<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">tty</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> pause<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Prompt the user to press a key to continue. Should probably use a pager
    most of the time though.
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">sys</span>.<span style="color: #dc143c;">platform</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">'win32'</span>, <span style="color: #483d8b;">'win64'</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">os</span>.<span style="color: black;">system</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'PAUSE'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: black;">isatty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdout</span>.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Press any key to continue'</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">tty</span>.<span style="color: black;">setraw</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: black;">fileno</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            <span style="color: #dc143c;">sys</span>.<span style="color: black;">stdin</span>.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">finally</span>:
            <span style="color: #dc143c;">os</span>.<span style="color: black;">system</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;stty sane&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'good times'</span>
pause<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'CLOBBER<span style="color: #000099; font-weight: bold;">\n</span>'</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">100</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=66</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Abandoned Python Projects</title>
		<link>http://www.thensys.com/?p=63</link>
		<comments>http://www.thensys.com/?p=63#comments</comments>
		<pubDate>Tue, 18 May 2010 03:04:25 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Software Design]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=63</guid>
		<description><![CDATA[A catalog of my projects that never made it to maturity, cut off before their prime!]]></description>
			<content:encoded><![CDATA[<p>I don&#8217;t know about you, but I&#8217;ve abandoned many, if not dozens, of projects over the years. I get a cute little idea, implement it as a library (maybe?). I might even use it on a real project. At some point, however, I decide that the idea wasn&#8217;t that great after all.</p>
<p>I&#8217;ve also spent a great deal of time reimplementing the same type of code before. My prime example is HTML form libraries. They&#8217;re so very easy to start writing, but there comes a point when the codes collapses on top of itself due to its complexity or inflexibility. I must&#8217;ve written 5 server-side HTML form generation libraries at this point.</p>
<p>I would like to believe that I&#8217;ve learned some things with all of these attempts. So about a year ago, I started to catalog all of the dead projects and libraries that I have worked on or conceptualized over the years. I just wanted to capture the fact that I&#8217;d already been down that road.</p>
<p>Most of these projects were attempts at solving general, classes of problems. If I&#8217;ve learned one thing, it&#8217;s that general solutions are <strong>very hard to design</strong>.</p>
<p>Eventually, the abandoned projects catalog project found its way on the abandoned projects pile (I do love recursion don&#8217;t ya know). </p>
<p>I ran across the file in my Someday directory and thought that some of these might be interesting to share. Or maybe someone knows of completed libraries in production that do these things!</p>
<h3>The Block Parser</h3>
<p>The idea behind block parse was to create a way to specify a lot of different<br />
kinds of artifacts in a file, have different parsers for each type of artifact<br />
and have these things turned into Python objects.</p>
<p>Each artifact in the file would be represented as a text block, the type of the<br />
object on the first line (with possibly some preamble or header information)<br />
and then the body of the artifact would be indented under the header.</p>
<p>The main motivation was to create some kind of templating schema for SQL<br />
because embedding SQL in code is so ugly. I wanted to be able to create my own<br />
simple syntaxes and have them load into Python.</p>
<p>I have come to realize that it&#8217;s just easier to use a Python class with a<br />
specific interface and pass off instances of that class to a loader. If syntax<br />
really is prohibitive, additional files can be provided to the loader to create<br />
the runtime object, along with Python objects.</p>
<h3>Overlay Config Parser</h3>
<p>This was an attempt at reimplementing apache&#8217;s hierarchical configuration<br />
system. In apache, configuration inherits from parent directories and so<br />
the total configuration of a particular file system location is an<br />
aggregate of all configurations up the hierarchy. I really like how this<br />
configuration system works. Configuration variables are inherited from parent<br />
objects in the hierarchy, and can be overridden or augmented.</p>
<p>It turned out that it would be a lot of work to write a general configuration<br />
system based on these rules. It&#8217;s easiest to assume that the hierarchy is a<br />
file system, or at least formatted like a file system path<br />
(/parent/child/grandchild).</p>
<p>This project might have some merit, but as of right now I can&#8217;t justify the<br />
time it would take to write it. I don&#8217;t really have a use for it as of now<br />
anyway.</p>
<h3>SQL Pipe</h3>
<p>SQL pipe was the result of playing with an idea I had on how to organize code.<br />
This organization was called seed/step. Seed/Step worked like this:</p>
<p>An object would be constructed which would serve as the seed. This object would<br />
have a lot of members that were blank and needed to be populated.</p>
<p>Step objects would be applied to the seed, which would populate the seed with<br />
objects. I can&#8217;t exactly remember how it worked, but there were some<br />
interesting ideas there.</p>
<p>The result was a linearlized sequence of commands that built a complex<br />
structure, like a SQL query. </p>
<p>Ultimately, it turned out to be a very complicated builder pattern. The calling<br />
sequences concerning how the objects were put together were very complex. The<br />
library failed to separate the interface from the implementation, so a lot of<br />
strange syntactic sugar had to be introduced for the code to look passable.</p>
<p>For example, here is code to create a select query:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">select_pipe<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>
    <span style="color: #dc143c;">select</span>.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">table</span>, <span style="color: #483d8b;">&quot;po_id&quot;</span>, <span style="color: #483d8b;">&quot;po_id&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
    <span style="color: #dc143c;">select</span>.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">table</span>, <span style="color: #483d8b;">&quot;po_number&quot;</span>, <span style="color: #483d8b;">&quot;PO_No&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
    <span style="color: #dc143c;">select</span>.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;orders&quot;</span>, <span style="color: #483d8b;">&quot;dt_number&quot;</span>, <span style="color: #483d8b;">&quot;DT_No&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
    <span style="color: #dc143c;">select</span>.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">table</span>, <span style="color: #483d8b;">&quot;phone&quot;</span>, <span style="color: #483d8b;">&quot;Phone&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
    <span style="color: #dc143c;">select</span>.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">table</span>, <span style="color: #483d8b;">&quot;status&quot;</span>, <span style="color: #483d8b;">&quot;Status&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
    expr.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot; DATE_FORMAT(purchase_order.date, 'YYYYMMDD') as Date&quot;</span><span style="color: black;">&#41;</span>,
    expr.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot; CONCAT(employee.last_name,', ',employee.first_name) as Employee&quot;</span><span style="color: black;">&#41;</span>,
    <span style="color: #dc143c;">select</span>.<span style="color: black;">l</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;vendor&quot;</span>, <span style="color: #483d8b;">&quot;company&quot;</span>, <span style="color: #483d8b;">&quot;Vendor&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">baseSeed</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>The baseSeed was a seed that had a lot of other information added to it. This<br />
expression only specified what columns to return. The baseSeed() provided the<br />
actual tables, join structures and conditionals.</p>
<p>As I&#8217;ve said, a simple builder would&#8217;ve worked better.</p>
<h3>The Dicer</h3>
<p>The dicer was a fun little project that build a minilanguage to query complex<br />
Python data structures. For example: lists of dicts, whose values had lists. An<br />
example unit test:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">data = <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;foo&quot;</span> : <span style="color: black;">&#91;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;bar&quot;</span> : <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span>,
                 <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;bar&quot;</span> : <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span>,
                 <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;bar&quot;</span> : <span style="color: #ff4500;">3</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span>,
        <span style="color: #483d8b;">&quot;spam&quot;</span> : <span style="color: black;">&#91;</span>
             <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;ham&quot;</span> : <span style="color: black;">&#123;</span>
                 <span style="color: #483d8b;">&quot;eggs&quot;</span> : <span style="color: #483d8b;">&quot;monty!&quot;</span>
             <span style="color: black;">&#125;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span>,
        <span style="color: #483d8b;">&quot;neo&quot;</span> : <span style="color: #483d8b;">&quot;5&quot;</span>
       <span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">assert</span> dicer<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;foo[:].bar&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span> == <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> dicer<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;foo.bar&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span> == <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">2</span>, <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> dicer<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;foo[2].bar&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span> == <span style="color: #ff4500;">3</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> dicer<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;spam.ham.eggs&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span> == <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;monty!&quot;</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> dicer<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;neo&quot;</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>data<span style="color: black;">&#41;</span> == <span style="color: #483d8b;">&quot;5&quot;</span></pre></div></div>

<p>Looking back, the dicer really does seem like a neat utility with a very<br />
focused purpose and clean interface. I believe it was originally written to<br />
parse out complex configuration data. I should really remember to try and use<br />
the dicer some more.</p>
<p>One thing I don&#8217;t like about the dicer is its use of lex and yacc packages,<br />
which create parsetab.py files everywhere. This would have to be retooled if I<br />
wanted to release the dicer to the public.</p>
<h3>The Stamper</h3>
<p>The stamper was an exercise in writing a validation library that had basic<br />
logic support.  I believe it was inspired from some examples in SICP.</p>
<p>For example, the stamper has a predicate expression when:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">r = when<span style="color: black;">&#40;</span>have<span style="color: black;">&#40;</span><span style="color: #483d8b;">'first_name'</span><span style="color: black;">&#41;</span>, have<span style="color: black;">&#40;</span><span style="color: #483d8b;">'last_name'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> r<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'first_name'</span> : <span style="color: #483d8b;">'a'</span>, <span style="color: #483d8b;">'last_name'</span> : <span style="color: #483d8b;">'b'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span> == <span style="color: #008000;">True</span></pre></div></div>

<p>Here, &#8216;r&#8217; becomes the stamper and the dict literal is the record which is<br />
tested against. There were also stamps that allowed for custom procedures to be<br />
plugged in and used, like match, which would take a procedure and return the<br />
result of applying that procedure to the value for the field.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> is_phone_number_alt1<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'^<span style="color: #000099; font-weight: bold;">\(</span><span style="color: #000099; font-weight: bold;">\d</span>{3}<span style="color: #000099; font-weight: bold;">\)</span> <span style="color: #000099; font-weight: bold;">\d</span>{3}-<span style="color: #000099; font-weight: bold;">\d</span>{4}$'</span>, <span style="color: #008000;">str</span><span style="color: black;">&#41;</span>
&nbsp;
rec = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'first_name'</span> : <span style="color: #483d8b;">'John'</span>,
    <span style="color: #483d8b;">'last_name'</span> : <span style="color: #483d8b;">'Smith'</span>,
    <span style="color: #483d8b;">'phone_number'</span> : <span style="color: #483d8b;">'444-444-4444'</span>,
    <span style="color: #483d8b;">'cell_phone'</span> : <span style="color: #483d8b;">'333-333-3333'</span>
<span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">assert</span> match<span style="color: black;">&#40;</span>is_phone_number, <span style="color: #483d8b;">'phone_number'</span><span style="color: black;">&#41;</span><span style="color: black;">&#40;</span>rec<span style="color: black;">&#41;</span> == <span style="color: #008000;">True</span></pre></div></div>

<p>The checking could get decently complex:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">rule = when<span style="color: black;">&#40;</span><span style="color: #008000;">all</span><span style="color: black;">&#40;</span>have<span style="color: black;">&#40;</span><span style="color: #483d8b;">'length'</span><span style="color: black;">&#41;</span>, have<span style="color: black;">&#40;</span><span style="color: #483d8b;">'width'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>,
                check<span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x, y: x == y, <span style="color: black;">&#91;</span><span style="color: #483d8b;">'length'</span>, <span style="color: #483d8b;">'width'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> rule<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'length'</span> : <span style="color: #483d8b;">'2'</span>, <span style="color: #483d8b;">'width'</span> : <span style="color: #483d8b;">'2'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span> == <span style="color: #008000;">True</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> rule<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'length'</span> : <span style="color: #483d8b;">'2'</span>, <span style="color: #483d8b;">'width'</span> : <span style="color: #483d8b;">'1'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span> == <span style="color: #008000;">False</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> rule<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'length'</span> : <span style="color: #483d8b;">'1'</span>, <span style="color: #483d8b;">'width'</span> : <span style="color: #483d8b;">'2'</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span> == <span style="color: #008000;">False</span></pre></div></div>

<p>This rule assures that the record has a square when dimensions are provided.</p>
<p>You know, the stamper is pretty powerful, but one thing it&#8217;s lacking is any<br />
notion of types. I believe the stamper is type agnostic. It would need to have<br />
much better error reporting capabilities than returning True or False for it to<br />
be useful in a real system.</p>
<p>I also wonder what the pay off is of going through the trouble of building this<br />
functional representation of these rules. It would seem that the stamper should<br />
really be a middle man between some declarative data of rules and the<br />
processing of those rules. In this event, why have all the syntactic sugar?</p>
<p>The stamper might be an example of me trying to turn Python into Scheme.</p>
<p>And I&#8217;ve saved the best for last:</p>
<h3>Casrel</h3>
<p>Casrel was an exploration in designing data files. Casrel data is short for<br />
CAScading RELation. Each data file consists of a set of data definitions,<br />
grouped as properties on objects. The layout was inspired by CSS. For example,<br />
an account table definition pulled from a database would be:</p>
<pre>
account
    schema-name: public
    relation-type: table
    read-only: no

account.account_name
    label: account_name
    sql-domain: varchar
    type: varchar
    read-only: no
    sql-required: no
    required: no
    maximum-length: 255

account.label
    label: label
    sql-domain: varchar
    type: varchar
    read-only: no
    sql-required: yes
    required: yes
    maximum-length: 255

account.owner_name
    label: owner_name
    sql-domain: varchar
    type: varchar
    read-only: no
    sql-required: no
    required: no
    maximum-length: 255

account.account_type
    label: account_type
    sql-domain: account_type
    type: account_type
    read-only: no
    sql-required: no
    required: no
</pre>
<p>The object specifier consists of a series of dotted properties, forming a<br />
hierarchy to a parent object. account.account_name describes properties on the<br />
account_name object, which is a member of the account object.</p>
<p>One interesting property of this file format is that it effectively builds a<br />
tree of data without the multi-level indentation or curly-brace structure that<br />
is common in other file formats. The hierarchy is implicit in how the object<br />
labels are written.</p>
<p>Casrel was designed to define metadata for applications to use to create forms,<br />
SQL data definitions and other information. It&#8217;s purpose was to serve as a<br />
central point of truth for schema data.</p>
<p>The cascading nature of casrel was that it supported merging the attribute<br />
values on objects from multiple definitions (the same way CSS works).</p>
<p>This could allow specific properties to be overridden and object hierarchies to<br />
be piece-meal, depending on the situation.</p>
<p>Take, for example, a customer table definition that is created by inspecting a<br />
SQL table.</p>
<pre>
customer.first_name
    label: first_name
    type: varchar
    maximum-length: 255
</pre>
<p>On a particular form, you want to show a field for the first_name, you can<br />
override the label attribute to be more user friendly, and also add in another<br />
attribute:</p>
<pre>
customer.first_name
    label: First Name
    help: The common name of the person
</pre>
<p>This merges to form:</p>
<pre>
customer.first_name
    label: First Name
    type: varchar
    maximum-length: 255
    help: The common name of the person
</pre>
<p>In the source code, this operation is called a &#8220;join&#8221; though I think that merge<br />
would be a better term to use.</p>
<p>There are many more ideas that could be incorporated into the data format,<br />
wildcards or regular expression matching for example:</p>
<pre>
# Set the default type on customer fields to be varchar
customer.*
    type: varchar
    maximum-length: 255
</pre>
<p>or more xpath-like expressions:</p>
<pre>
# Set the maximum-length on customer fields with the type attribute of varchar
customer.[type=varchar]
    maximum-length: 25
</pre>
<p>Using wildcards, regular expressions of xpath-esque expressions, you could<br />
build collections of attributes that could be bundled (and then applied by<br />
using a special matching attribute that had no bearing on the real data<br />
definition.) Would have to come up with a jargon term for this attribute. Maybe<br />
a class (since it&#8217;s function is the same as using a css class to define a<br />
common set of attributes for use on specific objects.)</p>
<pre>
# a custom type to be used for fields
*.[x-type=zipcode]
    type: varchar
    maximum-length: 10
    match-expression: \d{5}(?:-\d{4})

# This would expand
customer.zip_code
    x-type: zipcode
</pre>
<p>All of these are exciting ideas, but I&#8217;m constantly reminded that there are<br />
many similar technologies out there that, with some post processing, could<br />
provide all of the functionality mentioned above. XML, JSON, XPATH, XSLT, YAML,<br />
INI, CSS. The list is long and varied.</p>
<p>This project was actually abandoned because too much time was being spent on<br />
it, another victim of feature creep. I decided that too much time was going<br />
into this library, so I just settled on YAML to define data values.</p>
<p>Using YAML turned out to be the worst of both worlds. It provided no real<br />
benefit from just using python code. The lesson here is that, unless you are<br />
creating new means of combination and more functionality than simple data<br />
definitions, you&#8217;re wasting your time using a data language.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=63</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Turtle Sets the Bar for Python Programming</title>
		<link>http://www.thensys.com/?p=60</link>
		<comments>http://www.thensys.com/?p=60#comments</comments>
		<pubDate>Wed, 12 May 2010 23:07:04 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=60</guid>
		<description><![CDATA[Last week I was showing a non-programmer friend the basics of coding. We did some interactive programming using the logo-inspired turtle package that comes with Python Tkinter. We did some fun things like drawing random pinwheels.
The final program we wrote drew the tri-force from &#8220;The Legend of Zelda.&#8221; Here&#8217;s the code:

from turtle import *
&#160;
def triangle&#40;size&#41;:
 [...]]]></description>
			<content:encoded><![CDATA[<p>Last week I was showing a non-programmer friend the basics of coding. We did some interactive programming using the logo-inspired turtle package that comes with Python Tkinter. We did some fun things like drawing random pinwheels.</p>
<p>The final program we wrote drew the tri-force from &#8220;The Legend of Zelda.&#8221; Here&#8217;s the code:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">turtle</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> triangle<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>:
    begin_fill<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: black;">&#41;</span>:
        forward<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
        left<span style="color: black;">&#40;</span><span style="color: #ff4500;">120</span><span style="color: black;">&#41;</span>
    end_fill<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> triforce<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>:
    color<span style="color: black;">&#40;</span><span style="color: #483d8b;">'yellow'</span><span style="color: black;">&#41;</span>
    triangle<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
    right<span style="color: black;">&#40;</span><span style="color: #ff4500;">120</span><span style="color: black;">&#41;</span>
    forward<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
    left<span style="color: black;">&#40;</span><span style="color: #ff4500;">120</span><span style="color: black;">&#41;</span>
    triangle<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
    forward<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
    triangle<span style="color: black;">&#40;</span>size<span style="color: black;">&#41;</span>
&nbsp;
triforce<span style="color: black;">&#40;</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span>
done<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Don&#8217;t you wish all programming was like that? What if your ajax-driven Python web application&#8217;s code was that simple and elegant?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=60</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python AMQPlib Common Idioms</title>
		<link>http://www.thensys.com/?p=47</link>
		<comments>http://www.thensys.com/?p=47#comments</comments>
		<pubDate>Thu, 12 Nov 2009 07:56:01 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=47</guid>
		<description><![CDATA[I&#8217;ve been looking at implementing AMQP for quite some time now to replace our globs of ad-hoc system communication, and so far I&#8217;ve been enjoying learning the technology. I&#8217;ve been going over the AMQP spec, Rabbit MQ&#8217;s Documentation and have read Rabbits and Warrens a handful of times.
One thing that I&#8217;m yet to run across [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been looking at implementing AMQP for quite some time now to replace our globs of ad-hoc system communication, and so far I&#8217;ve been enjoying learning the technology. I&#8217;ve been going over the <a href="http://jira.amqp.org/confluence/download/attachments/720900/amqp.0-10.pdf?version=1">AMQP spec</a>, <a href="http://www.rabbitmq.com/documentation.html">Rabbit MQ&#8217;s Documentation</a> and have read <a href="http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/">Rabbits and Warrens</a> a handful of times.</p>
<p>One thing that I&#8217;m yet to run across is some examples of the common patterns you can do with AMQP and how to write them with amqplib. I&#8217;d like for this page to help answer the question, &#8220;so what do I do with it?&#8221; after someone has learned about channels, exchanges, queues and routing keys. When looking at the following examples, you will notice a lot of similarities in the code, but it&#8217;s the small differences that causes the nuances that have given me the most insight.</p>
<h2>Set up</h2>
<p>Below is the channel setup (and python script initialization) that all of these examples will use. This configuration worked fine for me on Ubuntu after installing the .deb file from the rabbit-mq website.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #ff7700;font-weight:bold;">from</span> amqplib <span style="color: #ff7700;font-weight:bold;">import</span> client_0_8 <span style="color: #ff7700;font-weight:bold;">as</span> amqp
conn = amqp.<span style="color: black;">Connection</span><span style="color: black;">&#40;</span>host=<span style="color: #483d8b;">&quot;localhost:5672 &quot;</span>, userid=<span style="color: #483d8b;">&quot;guest&quot;</span>,
    password=<span style="color: #483d8b;">&quot;guest&quot;</span>, virtual_host=<span style="color: #483d8b;">&quot;/&quot;</span>, insist=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
chan = conn.<span style="color: black;">channel</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Broadcast</h2>
<p>When broadcasting, a producer sends out messages to the queue and does not care about who receives them or if their is someone at the other end to receive them. Consumers join and leave the exchange at their leisure. Providing sports score updates is an example where broadcasting would be appropriate. Every time a team scores, a message is sent out to all interested parties with what happened and the new score. Many clients would only want to know scores that happen in real time. Scores that happen in the past would be of no consequence.</p>
<p>When broadcasting, the <strong>exchange name</strong> alone identifies the destination of the message.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">chan.<span style="color: black;">exchange_declare</span><span style="color: black;">&#40;</span>exchange=<span style="color: #483d8b;">&quot;score_updates&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;fanout&quot;</span>, durable=<span style="color: #008000;">False</span>,
                      auto_delete=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Produce Script</span>
msg = amqp.<span style="color: black;">Message</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;AL 24: FL 7<span style="color: #000099; font-weight: bold;">\n</span>Touch down by Tim Tebow&quot;</span><span style="color: black;">&#41;</span>
chan.<span style="color: black;">basic_publish</span><span style="color: black;">&#40;</span>msg, exchange=<span style="color: #483d8b;">&quot;score_updates&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Consume Script</span>
queue = chan.<span style="color: black;">queue_declare</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;</span>, durable=<span style="color: #008000;">False</span>, exclusive=<span style="color: #008000;">True</span>, auto_delete=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> score_update_callback<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># tell person using this device</span>
    <span style="color: #ff7700;font-weight:bold;">pass</span>
chan.<span style="color: black;">basic_consume</span><span style="color: black;">&#40;</span>queue=queue<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, callback=score_update_callback, no_ack=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></div></div>

<h2>Notify</h2>
<p>This idiom allows consumers to subscribe to events and guarantee that all messages get delivered, even when the consumer is not running. The setup is similar to broadcast with the following exceptions: The queues are given explicit names that relate to the consumer. The name selection must be coordinated across all consumers to be sure they don&#8217;t overlap. Queues are made durable and persistent, giving them permanency. In this scheme a consumer should be ran at least once to register its queue. After the initial run, messages sent to the exchange will start to pile up in the queue for the consumer to process.</p>
<p>Let&#8217;s say that data records entered in one system should be sent to numerous other systems across an enterprise. The Notifier is the way to go.</p>
<p>When notifying, the <strong>exchange name</strong> alone identifies the destination of the message.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">chan.<span style="color: black;">exchange_declare</span><span style="color: black;">&#40;</span>exchange=<span style="color: #483d8b;">&quot;notify.patient.add&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;fanout&quot;</span>, durable=<span style="color: #008000;">True</span>,
                      auto_delete=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Producer</span>
msg = amqp.<span style="color: black;">Message</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;given:John<span style="color: #000099; font-weight: bold;">\n</span>surname:Smith&quot;</span>, delivery_mode=<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
chan.<span style="color: black;">basic_publish</span><span style="color: black;">&#40;</span>msg, exchange=<span style="color: #483d8b;">&quot;notify.patient.add&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Consumer for Scheduling System</span>
chan.<span style="color: black;">queue_declare</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;notify.patient.add.scheduling&quot;</span>, durable=<span style="color: #008000;">True</span>, auto_delete=<span style="color: #008000;">False</span>,
                            exclusive=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
chan.<span style="color: black;">queue_bind</span><span style="color: black;">&#40;</span>queue=<span style="color: #483d8b;">&quot;notify.patient.add.scheduling&quot;</span>, exchange=<span style="color: #483d8b;">&quot;notify.patient.add&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> scheduling_patient_add<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>:
     <span style="color: #808080; font-style: italic;"># add to local database maybe?</span>
     chan.<span style="color: black;">basic_ack</span><span style="color: black;">&#40;</span>msg.<span style="color: black;">delivery_tag</span><span style="color: black;">&#41;</span>
&nbsp;
chan.<span style="color: black;">basic_consume</span><span style="color: black;">&#40;</span>queue=<span style="color: #483d8b;">&quot;notify.patient.add.scheduling&quot;</span>,
                            callback=scheduling_patient_add<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Consumer for Reporting System</span>
chan.<span style="color: black;">queue_declare</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;notify.patient.add.reporting&quot;</span>, durable=<span style="color: #008000;">True</span>, auto_delete=<span style="color: #008000;">False</span>,
                            exclusive=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
chan.<span style="color: black;">queue_bind</span><span style="color: black;">&#40;</span>queue=<span style="color: #483d8b;">&quot;notify.patient.add.reporting&quot;</span>, exchange=<span style="color: #483d8b;">&quot;notify.patient.add&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> reporting_patient_add<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>:
     <span style="color: #808080; font-style: italic;"># add to local database maybe?</span>
     chan.<span style="color: black;">basic_ack</span><span style="color: black;">&#40;</span>msg.<span style="color: black;">delivery_tag</span><span style="color: black;">&#41;</span>
&nbsp;
chan.<span style="color: black;">basic_consume</span><span style="color: black;">&#40;</span>queue=<span style="color: #483d8b;">&quot;notify.patient.add.reporting&quot;</span>,
                            callback=reporting_patient_add<span style="color: black;">&#41;</span></pre></div></div>

<p>It&#8217;s important that each consumer has it&#8217;s own queue uniquely named. We don&#8217;t want<br />
different consumers gobbling up each other&#8217;s messages.</p>
<h2>Request/Response</h2>
<p>This one took me the longest to figure out. It&#8217;s an implementation of the standard request/response idiom ubiquitously found in client/server computing. This is also the underlying mechanism to RPC, so if you&#8217;re looking to do your own RPC protocol on top of AMQP, then this is the way to go.</p>
<p>I learned the proper way to implement this by looking at the source code of rabbit mq&#8217;s java client library along with reading the specification, so if anyone has any pointers to make this code better, I&#8217;d love to hear them!</p>
<p>The idea is to use two queues. One for sending the request and one for the response.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">chan.<span style="color: black;">exchange_declare</span><span style="color: black;">&#40;</span>exchange=<span style="color: #483d8b;">&quot;api&quot;</span>, <span style="color: #008000;">type</span>=<span style="color: #483d8b;">&quot;direct&quot;</span>, durable=<span style="color: #008000;">False</span>,
                      auto_delete=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Responder/Callee/Server</span>
chan.<span style="color: black;">queue_declare</span><span style="color: black;">&#40;</span>queue=<span style="color: #483d8b;">&quot;add_patient&quot;</span>, durable=<span style="color: #008000;">False</span>,
    exclusive=<span style="color: #008000;">False</span>, auto_delete=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
chan.<span style="color: black;">queue_bind</span><span style="color: black;">&#40;</span>exchange=<span style="color: #483d8b;">&quot;api&quot;</span>, queue=<span style="color: #483d8b;">&quot;add_patient&quot;</span>, routing_key=<span style="color: #483d8b;">&quot;add_patient&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> add_patient<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>:
    reply = amqp.<span style="color: black;">Message</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Return Value&quot;</span><span style="color: black;">&#41;</span>
    chan.<span style="color: black;">basic_publish</span><span style="color: black;">&#40;</span>reply, routing_key=msg.<span style="color: black;">reply_to</span><span style="color: black;">&#41;</span>
chan.<span style="color: black;">basic_consume</span><span style="color: black;">&#40;</span>queue=<span style="color: #483d8b;">&quot;add_patient&quot;</span>, callback=add_patient, no_ack=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Requester/Caller/Client</span>
reply_queue = chan.<span style="color: black;">queue_declare</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;&quot;</span>, durable=<span style="color: #008000;">False</span>, exclusive=<span style="color: #008000;">True</span>,
                                                auto_delete=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
reply_queue = reply_queue<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>
msg = amqp.<span style="color: black;">Message</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Test message!&quot;</span><span style="color: black;">&#41;</span>
msg.<span style="color: black;">properties</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;reply_to&quot;</span><span style="color: black;">&#93;</span> = reply_queue
chan.<span style="color: black;">basic_publish</span><span style="color: black;">&#40;</span>msg, exchange=<span style="color: #483d8b;">&quot;api&quot;</span>, routing_key=<span style="color: #483d8b;">&quot;add_patient&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> handle_response<span style="color: black;">&#40;</span>msg<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Response:&quot;</span>, msg.<span style="color: black;">body</span>
chan.<span style="color: black;">basic_consume</span><span style="color: black;">&#40;</span>queue=reply_queue, callback=handle_response, no_ack=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
chan.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>There is a lot going on in this example, so I&#8217;ll try to go through it step-by-step. In this scenario the exchange is defined as a container, while the queue is the application end point. The caller creates a temporary, exclusive queue to serve as a response channel for the responder. AMQP messages have a standard reply_to field for just this purpose.</p>
<p>In this case, the response queue is defined in the global exchange, since it is only temporary and is passed by name to the responder.</p>
<p>Something that  I didn&#8217;t get much time to go in to is the choice of which queues and exchanges to make durable and set auto delete. In request and response, you generally do not want messages to persist and pile up in the queue if no responder is running, so a time out mechanism will have to be implemented in the application layer. I&#8217;m sure there are many other considerations that I haven&#8217;t thought about. But I&#8217;ll hopefully cross those paths when I come to them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=47</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WSGI DIY Application</title>
		<link>http://www.thensys.com/?p=41</link>
		<comments>http://www.thensys.com/?p=41#comments</comments>
		<pubDate>Sun, 04 Oct 2009 06:51:36 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[WSGI]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=41</guid>
		<description><![CDATA[
# feed me to mod_wsgi
import os
&#160;
from beaker.middleware import SessionMiddleware
from paste import httpexceptions
from paste.exceptions.errormiddleware import ErrorMiddleware
from paste.urlparser import make_url_parser
&#160;
site_dir = os.path.abspath&#40;os.path.dirname&#40;__file__&#41;&#41;
app_dir = os.path.join&#40;site_dir, 'apps'&#41;
&#160;
os.environ.update&#40;&#123;
     'DBURI': 'postgres://XX:XXXX@localhost/XX',
     'MAKO_CACHE_DIR': '/tmp/XX_mako',
     'MAKO_TEMPLATE_DIR': '%s/mako' % app_dir
&#125;&#41;
&#160;
application = make_url_parser&#40;&#123;&#125;, app_dir, 'XX.apps'&#41;
application = SessionMiddleware&#40;application, &#123;
    'session.cookie_expires': 30000,
 [...]]]></description>
			<content:encoded><![CDATA[
<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># feed me to mod_wsgi</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> beaker.<span style="color: black;">middleware</span> <span style="color: #ff7700;font-weight:bold;">import</span> SessionMiddleware
<span style="color: #ff7700;font-weight:bold;">from</span> paste <span style="color: #ff7700;font-weight:bold;">import</span> httpexceptions
<span style="color: #ff7700;font-weight:bold;">from</span> paste.<span style="color: #dc143c;">exceptions</span>.<span style="color: black;">errormiddleware</span> <span style="color: #ff7700;font-weight:bold;">import</span> ErrorMiddleware
<span style="color: #ff7700;font-weight:bold;">from</span> paste.<span style="color: black;">urlparser</span> <span style="color: #ff7700;font-weight:bold;">import</span> make_url_parser
&nbsp;
site_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">abspath</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>__file__<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
app_dir = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>site_dir, <span style="color: #483d8b;">'apps'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span>.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span>
     <span style="color: #483d8b;">'DBURI'</span>: <span style="color: #483d8b;">'postgres://XX:XXXX@localhost/XX'</span>,
     <span style="color: #483d8b;">'MAKO_CACHE_DIR'</span>: <span style="color: #483d8b;">'/tmp/XX_mako'</span>,
     <span style="color: #483d8b;">'MAKO_TEMPLATE_DIR'</span>: <span style="color: #483d8b;">'%s/mako'</span> <span style="color: #66cc66;">%</span> app_dir
<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
application = make_url_parser<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>, app_dir, <span style="color: #483d8b;">'XX.apps'</span><span style="color: black;">&#41;</span>
application = SessionMiddleware<span style="color: black;">&#40;</span>application, <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'session.cookie_expires'</span>: <span style="color: #ff4500;">30000</span>,
    <span style="color: #483d8b;">'session.type'</span> : <span style="color: #483d8b;">'file'</span>,
    <span style="color: #483d8b;">'session.data_dir'</span> : <span style="color: #483d8b;">'/tmp/XX_session'</span>,
    <span style="color: #483d8b;">'session.key'</span> : <span style="color: #483d8b;">'_sid'</span>
<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
application = httpexceptions.<span style="color: black;">HTTPExceptionHandler</span><span style="color: black;">&#40;</span>application<span style="color: black;">&#41;</span>
application = ErrorMiddleware<span style="color: black;">&#40;</span>application, debug=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=41</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>First Thoughts on WSGI and Paste</title>
		<link>http://www.thensys.com/?p=30</link>
		<comments>http://www.thensys.com/?p=30#comments</comments>
		<pubDate>Tue, 28 Jul 2009 02:33:15 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[WSGI]]></category>

		<guid isPermaLink="false">http://www.thensys.com/?p=30</guid>
		<description><![CDATA[My first look at WSGI]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve finally had some time to look into WSGI, and I&#8217;m starting my first project using it. I made the jump because of how easy <a href='http://code.google.com/p/modwsgi/'>mod_wsgi</a> was to get working. I particularly like daemon mode where multiple processes can be configured to run the same application. If, on a particular instance, a wsgi application goes horribly wrong (like calls into a shared object that causes a seg fault), mod_wsgi will happily replace the process with a new copy. I find process isolation in a production environment to be manditory. So go mod_wsgi!</p>
<p>I&#8217;ve found Ian Bicking&#8217;s work on <a href='http://www.pythonpaste.org'>Python Paste</a> to be most illuminating and good brain food to chew on. I particularly enjoyed his article on <a href='http://pythonpaste.org/do-it-yourself-framework.html'>a do-it-yourself framework</a>.</p>
<p>The smorgasbord approach to pure WSGI development is very appealing: simple interfaces, low coupling, transparent code, small contexts. It really embodies the values I&#8217;ve developed over the years writing Python. <a href='http://www.wsgi.org/wsgi/Middleware_and_Utilities'>Middleware</a> is absolutely scrumptious, and I hope to have some packages suitable for release to the rest of the community after I finish this first project.</p>
<p>So far, I&#8217;m using:</p>
<ul>
<li><a href='http://beaker.groovie.org/'>Beaker</a></li>
<li><a href='http://pythonpaste.org/url-parsing-with-wsgi.html'>paste.urlparser</a></li>
<li><a href='http://pythonpaste.org/webob/'>webob</a></li>
</ul>
<p>I have to say that so far, I&#8217;ve been very impressed with paste.urlparser. I&#8217;ve written and used so many web dispatch systems over the years, and this one really seems to get it right.</p>
<p>The fact that the dispatch sends to the module level is perfect. Other systems, like <a href='http://www.cherrypy.org'>cherrypy</a> require you to explicitly import all modules we controller code, usually resulting in many import statements in __init__ modules. paste.urlparser, automatically scans for modules with WSGI applications.</p>
<p>Each module, and in turn each file, is its own application. Simple, clean and to the point. Convention over Configuration.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=30</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automated Ignore Files with Subversion</title>
		<link>http://www.thensys.com/?p=5</link>
		<comments>http://www.thensys.com/?p=5#comments</comments>
		<pubDate>Thu, 10 May 2007 20:08:12 +0000</pubDate>
		<dc:creator>jeremy</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://test.thensys.com/?p=5</guid>
		<description><![CDATA[We always have tons of garbage files lying around that we don&#8217;t want going into version control. Subversion&#8217;s svn:ignore property doesn&#8217;t have the best documentation around. So, in order help out, here are two little scripts that work in tandem to ignore whatever you want.
The easiest way is to place .svnignore files in all of [...]]]></description>
			<content:encoded><![CDATA[<p>We always have tons of garbage files lying around that we don&#8217;t want going into version control. Subversion&#8217;s svn:ignore property doesn&#8217;t have the best documentation around. So, in order help out, here are two little scripts that work in tandem to ignore whatever you want.</p>
<p>The easiest way is to place .svnignore files in all of your directories that you wish to ignore files in. This file has a list of patterns or file names, one on each line, that should be ignored in this directory.</p>
<p>For example, to ignore foo.py and bar.py the file would have something like this:</p>
<pre>
   foo.py
   bar.py
</pre>
<p>Now, what if we have a set of files that we want to ignore across a project? The easiest way is to write scripts that automatically manage these .svnignore files.</p>
<p>In one project, we have template directories named &#8216;t&#8217; with compiled cheetah files that we do not want in subversion. However, we need the __init__.py files in those directories to be in subversion.</p>
<p>Here is a python script to manage those ignore files:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #483d8b;">&quot;&quot;&quot; Adds all python files in directories named t except
for __init__.py to the .svnignore files in those
directories recursively from the current directory.
&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">glob</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> root, dirs, files <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">walk</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">curdir</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">basename</span><span style="color: black;">&#40;</span>root<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>lt<span style="color: #66cc66;">;&gt;</span> <span style="color: #483d8b;">'t'</span>:
        <span style="color: #ff7700;font-weight:bold;">continue</span>
    files = <span style="color: #dc143c;">glob</span>.<span style="color: #dc143c;">glob</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s/*.py&quot;</span> <span style="color: #66cc66;">%</span> root<span style="color: black;">&#41;</span>
    files = <span style="color: black;">&#91;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">basename</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> files<span style="color: black;">&#93;</span>
    files = <span style="color: black;">&#91;</span>f <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> files <span style="color: #ff7700;font-weight:bold;">if</span> f <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">'__init__.py'</span><span style="color: black;">&#93;</span>
    ignore_path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>root, <span style="color: #483d8b;">'.svnignore'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>ignore_path<span style="color: black;">&#41;</span>:
        igh = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>ignore_path<span style="color: black;">&#41;</span>
        ignores = <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>f.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">True</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> igh<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        igh.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        ignores = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    ignores.<span style="color: black;">update</span><span style="color: black;">&#40;</span><span style="color: #008000;">dict</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#40;</span>f, <span style="color: #008000;">True</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> files<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    igh = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>ignore_path, <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> ignore <span style="color: #ff7700;font-weight:bold;">in</span> ignores.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        igh.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #66cc66;">%</span> ignore<span style="color: black;">&#41;</span>
    igh.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>If a ignore file exists, we pull it in and update it with what we want to ignore. It&#8217;s always important that scripts do not break any previous work. So if I manually put an entry in the .svnignore file, the script better not erase it.</p>
<p>Alright, so there we go. We now have ignore files everywhere. The other piece of the puzzle is a script that uses these ignore files and sets the svn properties on the directories.</p>
<p>So here is the last piece of the puzzle:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #483d8b;">&quot;&quot;&quot; Sets the contents of all .svnignore files to svn:ignore properties
recursively in the current directory. Also attemps to add the
.svnignore file to subversion.
&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">for</span> root, dirs, files <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">walk</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">curdir</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #483d8b;">'.svnignore'</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> files:
        <span style="color: #ff7700;font-weight:bold;">continue</span>
    path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>root, <span style="color: #483d8b;">'.svnignore'</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">system</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'svn propset svn:ignore -F &quot;%s&quot; &quot;%s&quot;'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>path, root<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">os</span>.<span style="color: black;">system</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'svn add &quot;%s&quot;'</span> <span style="color: #66cc66;">%</span> path<span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.thensys.com/?feed=rss2&amp;p=5</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
