<?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>Ian Bicking: a blog &#187; Search Results  &#187;  pylons</title>
	<atom:link href="http://blog.ianbicking.org/?s=pylons&#038;feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://blog.ianbicking.org</link>
	<description></description>
	<lastBuildDate>Wed, 18 Aug 2010 17:39:06 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>WebTest HTTP testing</title>
		<link>http://blog.ianbicking.org/2010/04/02/webtest-http-testing/</link>
		<comments>http://blog.ianbicking.org/2010/04/02/webtest-http-testing/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 22:27:37 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=215</guid>
		<description><![CDATA[
I&#8217;ve yet to see another testing system for local web testing that I like as much as WebTest&#8230; which is perhaps personal bias for something I wrote, but then I don&#8217;t have that same bias towards everything I&#8217;ve written.  Many frameworks build in their own testing systems but I don&#8217;t like the abstractions &#8212; [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I&#8217;ve yet to see another testing system for local web testing that I like as much as <a class="reference external" href="http://pythonpaste.org/webtest/">WebTest</a>&#8230; which is perhaps personal bias for something I wrote, but then I don&#8217;t have that same bias towards everything I&#8217;ve written.  Many frameworks build in their own testing systems but I don&#8217;t like the abstractions &#8212; they touch lots of internal things, or skip important steps of the request, or mock out things that don&#8217;t need to be mocked out.  WSGI can make this testing easy.</p>
<p>There&#8217;s also a hidden feature here: because WSGI is basically just describing HTTP, it can be a means of representing not just incoming HTTP requests, but also outgoing HTTP requests.  If you are running local tests against your application using WebTest, with just a little tweaking you can turn those tests into HTTP tests (i.e., actually connect to a socket).  But doing this is admittedly not obvious; hence this post!</p>
<p>Here&#8217;s what a basic WebTest test looks like:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> webtest <span class="kw1">import</span> TestApp<br />
<span class="kw1">import</span> json<br />
<br />
wsgi_app = acquire_wsgi_application_somehow<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
app = TestApp<span class="br0">&#40;</span>wsgi_app<span class="br0">&#41;</span><br />
<br />
<span class="kw1">def</span> test_login<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; resp = app.<span class="me1">post</span><span class="br0">&#40;</span><span class="st0">'/login'</span>, <span class="kw2">dict</span><span class="br0">&#40;</span>username=<span class="st0">'guest'</span>, password=<span class="st0">'guest'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; resp.<span class="me1">mustcontain</span><span class="br0">&#40;</span><span class="st0">'login successful'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; resp = resp.<span class="me1">click</span><span class="br0">&#40;</span><span class="st0">'home'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; resp.<span class="me1">mustcontain</span><span class="br0">&#40;</span><span class="st0">'&lt;a href=&quot;/profile&quot;&gt;guest&lt;/a&gt;'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="co1"># Or with a little framework integration:</span><br />
&nbsp; &nbsp; <span class="kw1">assert</span> resp.<span class="me1">templatevars</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'username'</span><span class="br0">&#41;</span> == <span class="st0">'guest'</span><br />
<br />
<span class="co1"># Or an API test:</span><br />
<span class="kw1">def</span> test_user_query<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; resp = app.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'/users.json'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">assert</span> <span class="st0">'guest'</span> <span class="kw1">in</span> resp.<span class="me1">json</span><span class="br0">&#91;</span><span class="st0">'userList'</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; user_info = <span class="kw2">dict</span><span class="br0">&#40;</span>username=<span class="st0">'guest2'</span>, password=<span class="st0">'guest2'</span>, name=<span class="st0">'Guest'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; resp = app.<span class="me1">post</span><span class="br0">&#40;</span><span class="st0">'/users.json'</span>, content_type=<span class="st0">'application/json'</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; body=json.<span class="me1">dumps</span><span class="br0">&#40;</span>user_info<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">assert</span> resp.<span class="me1">json</span> == user_info<br />
&nbsp;</div>
<p>The <tt class="docutils literal"><span class="pre">app</span></tt> object is a wrapper around the WSGI application, and each of those methods runs a request and gets the response.  The response object is a WebOb response with several additional helpers for testing (things like <tt class="docutils literal"><span class="pre">.click()</span></tt> which finds a link in HTML and follows it, or <tt class="docutils literal"><span class="pre">.json</span></tt> which loads the body as JSON).</p>
<p>You <em>don&#8217;t</em> have to be using a WSGI-centric framework like Pylons to use WebTest, it works fine with anything with a WSGI frontend, which is just about everything.  But the point of my post: you don&#8217;t have to use it with a WSGI application at all.  Using <a class="reference external" href="http://pythonpaste.org/wsgiproxy/">WSGIProxy</a>:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">urlparse</span><br />
<br />
<span class="kw1">if</span> <span class="kw3">os</span>.<span class="me1">environ</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'TEST_REMOTE'</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">from</span> wsgiproxy.<span class="me1">exactproxy</span> <span class="kw1">import</span> proxy_exact_request<br />
&nbsp; &nbsp; wsgi_app = proxy_exact_request<br />
&nbsp; &nbsp; parsed = <span class="kw3">urlparse</span>.<span class="me1">urlsplit</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">environ</span><span class="br0">&#91;</span><span class="st0">'TEST_REMOTE'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; app = TestApp<span class="br0">&#40;</span>proxy_exact_request, extra_environ=<span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'wsgi.scheme'</span>: parsed.<span class="me1">scheme</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'HTTP_HOST'</span>: parsed.<span class="me1">netloc</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">'SERVER_NAME'</span>: parsed.<span class="me1">netloc</span><span class="br0">&#125;</span><span class="br0">&#41;</span><br />
<span class="kw1">else</span>:<br />
&nbsp; &nbsp; wsgi_app = acquire_wsgi_application_somehow<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; app = TestApp<span class="br0">&#40;</span>wsgi_app<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>It&#8217;s a little crude to control this with an environmental variable (<tt class="docutils literal"><span class="pre">$TEST_REMOTE</span></tt>), but it&#8217;s an easy way to pass an option in when there&#8217;s no better way (and many test runners don&#8217;t make options easy).  The <tt class="docutils literal"><span class="pre">extra_environ</span></tt> option puts in the host and scheme information into each request (the default host WebTest puts in is <tt class="docutils literal"><span class="pre">http://localhost</span></tt>).  WSGIProxy lets you send a request to any host, kind of bypassing DNS, so <tt class="docutils literal"><span class="pre">SERVER_NAME</span></tt> is actually the server the request goes to, while <tt class="docutils literal"><span class="pre">HTTP_HOST</span></tt> is the value of the Host header.</p>
<p>Going over HTTP there are a couple features that won&#8217;t work.  For instance, you can pass information about your application back to the test code by putting values in <tt class="docutils literal"><span class="pre">environ['paste.testing_variables']</span></tt> (which is how you&#8217;d make <tt class="docutils literal"><span class="pre">resp.templatevars</span></tt> work in the first example).  It&#8217;s also possible to use <tt class="docutils literal"><span class="pre">extra_environ</span></tt> to pass information into your application, for example to get your application to mock out user authentication; this is fairly safe because in production no request can put those same special keys into the environment (using custom HTTP headers means you must carefully filter requests in production).  But custom environ values won&#8217;t work over HTTP.</p>
<p>The thing that got me thinking about this is the work I&#8217;m doing on <a class="reference external" href="http://cloudsilverlining.org">Silver Lining</a>, where I am taking apps and rearranging the code and modifying the database configuration ad setup to fit this deployment system.  It would be really nice having done that to be able to run some functional tests, and I really want to run them over HTTP.  If an application has tests using something like Selenium or Windmill that would also work great, but those tools can be a bit more challenging to work with and applications still need smaller tests anyway, so being able to reuse tests like these would be most useful.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/04/02/webtest-http-testing/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>What Does A WebOb App Look Like?</title>
		<link>http://blog.ianbicking.org/2010/03/12/a-webob-app-example/</link>
		<comments>http://blog.ianbicking.org/2010/03/12/a-webob-app-example/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 23:50:30 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=192</guid>
		<description><![CDATA[
Lately I&#8217;ve been writing code using WebOb and just a few other small libraries.  It&#8217;s not entirely obvious what this looks like, so I thought I&#8217;d give a simple example.
I make each application a class.  Instances of the class are &#34;configured applications&#34;.  So it looks a little like this (for an application [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Lately I&#8217;ve been writing code using WebOb and just a few other small libraries.  It&#8217;s not entirely obvious what this looks like, so I thought I&#8217;d give a simple example.</p>
<p>I make each application a class.  Instances of the class are &quot;configured applications&quot;.  So it looks a little like this (for an application that takes one configuration parameter, <tt class="docutils literal"><span class="pre">file_path</span></tt>):</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">class</span> Application<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, file_path<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">file_path</span> = file_path<br />
&nbsp;</div>
<p>Then the app needs to be a WSGI app, because that&#8217;s how I roll.  I use <a class="reference external" href="http://pythonpaste.org/webob/modules/dec.html">webob.dec</a>:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> webob.<span class="me1">dec</span> <span class="kw1">import</span> wsgify<br />
<span class="kw1">from</span> webob <span class="kw1">import</span> exc<br />
<span class="kw1">from</span> webob <span class="kw1">import</span> Response<br />
<br />
<span class="kw1">class</span> Application<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, file_path<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">file_path</span> = file_path<br />
&nbsp; &nbsp; @<span class="co1">wsgify</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__call__</span><span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> Response<span class="br0">&#40;</span><span class="st0">'Hi!'</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Somewhere separate from the application you actually instantiate <tt class="docutils literal"><span class="pre">Application</span></tt>.  You can use <a class="reference external" href="http://pythonpaste.org/deploy/">Paste Deploy</a> for that, configure it yourself, or just do something ad hoc (a lot of mod_wsgi <tt class="docutils literal"><span class="pre">.wsgi</span></tt> files are like this, basically).</p>
<p>I use <a class="reference external" href="http://pythonpaste.org/webob/reference.html#exceptions">webob.exc</a> for things like <tt class="docutils literal"><span class="pre">exc.HTTPNotFound()</span></tt>.  You can raise that as an exception, but I mostly just return the object (to the same effect).</p>
<p>Now you have Hello World.  I then sometimes do something terrible, I start handling URLs like this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
@<span class="co1">wsgify</span><br />
<span class="kw1">def</span> <span class="kw4">__call__</span><span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> req.<span class="me1">path_info</span> == <span class="st0">'/'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">index</span><span class="br0">&#40;</span>req<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">elif</span> req.<span class="me1">path_info</span>.<span class="me1">startswith</span><span class="br0">&#40;</span><span class="st0">'/view/'</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">view</span><span class="br0">&#40;</span>req<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> exc.<span class="me1">HTTPNotFound</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>This is lazy and a very bad idea.  So you want a dispatcher.  There are several (e.g., <a class="reference external" href="http://pypi.python.org/pypi/selector/">selector</a>).  I&#8217;ll use <a class="reference external" href="http://routes.groovie.org">Routes</a> here&#8230; the latest release makes it a bit easier (though it could still be streamlined a bit).  Here&#8217;s a pattern I think makes sense:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> routes <span class="kw1">import</span> Mapper<br />
<br />
<span class="kw1">class</span> Application<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw2">map</span> = Mapper<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw2">map</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'index'</span>, <span class="st0">'/'</span>, method=<span class="st0">'index'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw2">map</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'view'</span>, <span class="st0">'/view/{item}'</span>, method=<span class="st0">'view'</span><span class="br0">&#41;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, file_path<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">file_path</span> = file_path<br />
<br />
&nbsp; &nbsp; @<span class="co1">wsgify</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__call__</span><span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; results = <span class="kw2">self</span>.<span class="kw2">map</span>.<span class="me1">routematch</span><span class="br0">&#40;</span>environ=req.<span class="me1">environ</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> results:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> exc.<span class="me1">HTTPNotFound</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; match, route = results<br />
&nbsp; &nbsp; &nbsp; &nbsp; link = URLGenerator<span class="br0">&#40;</span><span class="kw2">self</span>.<span class="kw2">map</span>, req.<span class="me1">environ</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; req.<span class="me1">urlvars</span> = <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, match<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; kwargs = match.<span class="kw3">copy</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; method = kwargs.<span class="me1">pop</span><span class="br0">&#40;</span><span class="st0">'method'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; req.<span class="me1">link</span> = link<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">getattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, method<span class="br0">&#41;</span><span class="br0">&#40;</span>req, **kwargs<span class="br0">&#41;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">def</span> index<span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span class="kw1">def</span> view<span class="br0">&#40;</span><span class="kw2">self</span>, req, item<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp;</div>
<p>Another way you might do it is to skip the class, which means skipping a clear place for configuration.  I don&#8217;t like that, but if you don&#8217;t care about that, then it looks like this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">def</span> index<span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; ...<br />
<span class="kw1">def</span> view<span class="br0">&#40;</span><span class="kw2">self</span>, req, item<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; ...<br />
<br />
<span class="kw2">map</span> = Mapper<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
<span class="kw2">map</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'index'</span>, <span class="st0">'/'</span>, view=index<span class="br0">&#41;</span><br />
<span class="kw2">map</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'view'</span>, <span class="st0">'/view/{item}'</span>, view=view<span class="br0">&#41;</span><br />
<br />
@<span class="co1">wsgify</span><br />
<span class="kw1">def</span> application<span class="br0">&#40;</span>req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; results = <span class="kw2">map</span>.<span class="me1">routematch</span><span class="br0">&#40;</span>environ=req.<span class="me1">environ</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> results:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> exc.<span class="me1">HTTPNotFound</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; match, route = results<br />
&nbsp; &nbsp; link = URLGenerator<span class="br0">&#40;</span><span class="kw2">map</span>, req.<span class="me1">environ</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; req.<span class="me1">urlvars</span> = <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, match<span class="br0">&#41;</span><br />
&nbsp; &nbsp; kwargs = match.<span class="kw3">copy</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; view = kwargs.<span class="me1">pop</span><span class="br0">&#40;</span><span class="st0">'view'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; req.<span class="me1">link</span> = link<br />
&nbsp; &nbsp; <span class="kw1">return</span> view<span class="br0">&#40;</span>req, **kwargs<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Then <tt class="docutils literal"><span class="pre">application</span></tt> is pretty much boilerplate.  You could put configuration in the request if you wanted, or use some other technique (like <a class="reference external" href="http://pypi.python.org/pypi/Contextual">Contextual</a>).</p>
<p>I talked some with <a class="reference external" href="http://be.groovie.org/">Ben Bangert</a> about what he&#8217;s trying with these patterns, and he&#8217;s doing something reminiscent of Pylons controllers (but without the rest of Pylons) and it looks more like this (with my own adaptations):</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">class</span> BaseController<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; special_vars = <span class="br0">&#91;</span><span class="st0">'controller'</span>, <span class="st0">'action'</span><span class="br0">&#93;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, request, link, **config<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">request</span> = request<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">link</span> = link<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> name, value <span class="kw1">in</span> config.<span class="me1">items</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">setattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, name, value<span class="br0">&#41;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__call__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; action = <span class="kw2">self</span>.<span class="me1">request</span>.<span class="me1">urlvars</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'action'</span>, <span class="st0">'index'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">hasattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, <span class="st0">'__before__'</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.__before__<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; kwargs = req.<span class="me1">urlsvars</span>.<span class="kw3">copy</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> attr <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">special_vars</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> attr <span class="kw1">in</span> kwargs:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">del</span> kwargs<span class="br0">&#91;</span>attr<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">getattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, action<span class="br0">&#41;</span><span class="br0">&#40;</span>**kwargs<span class="br0">&#41;</span><br />
<br />
<span class="kw1">class</span> Index<span class="br0">&#40;</span>BaseController<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> index<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
&nbsp; &nbsp; <span class="kw1">def</span> view<span class="br0">&#40;</span><span class="kw2">self</span>, item<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; ...<br />
<br />
<span class="kw1">class</span> Application<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw2">map</span> = Mapper<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw2">map</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'index'</span>, <span class="st0">'/'</span>, controller=Index<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw2">map</span>.<span class="me1">connect</span><span class="br0">&#40;</span><span class="st0">'view'</span>, <span class="st0">'/view/{item}'</span>, controller=Index, &nbsp; &nbsp; action=<span class="st0">'view'</span><span class="br0">&#41;</span><br />
<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, **config<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">config</span> = config<br />
<br />
&nbsp; &nbsp; @<span class="co1">wsgify</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__call__</span><span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; results = <span class="kw2">self</span>.<span class="kw2">map</span>.<span class="me1">routematch</span><span class="br0">&#40;</span>environ=req.<span class="me1">environ</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> results:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> exc.<span class="me1">HTTPNotFound</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; match, route = results<br />
&nbsp; &nbsp; &nbsp; &nbsp; link = URLGenerator<span class="br0">&#40;</span><span class="kw2">self</span>.<span class="kw2">map</span>, req.<span class="me1">environ</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; req.<span class="me1">urlvars</span> = <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="br0">&#41;</span>, match<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; controller = match<span class="br0">&#91;</span><span class="st0">'controller'</span><span class="br0">&#93;</span><span class="br0">&#40;</span>req, link, **<span class="kw2">self</span>.<span class="me1">config</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> controller<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>That&#8217;s a lot of code blocks, but they all really say the same thing ;)  I think writing apps with almost-no-framework like this is pretty doable, so if you have something small you should give it a go.  I think it&#8217;s especially appropriate for applications that are an API (not a &quot;web site&quot;).</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/03/12/a-webob-app-example/feed/</wfw:commentRss>
		<slash:comments>30</slash:comments>
		</item>
		<item>
		<title>Toward a new self-definition for open source</title>
		<link>http://blog.ianbicking.org/2009/09/10/a-new-self-definition-for-foss/</link>
		<comments>http://blog.ianbicking.org/2009/09/10/a-new-self-definition-for-foss/#comments</comments>
		<pubDate>Fri, 11 Sep 2009 00:09:11 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Licensing]]></category>
		<category><![CDATA[Politics]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=125</guid>
		<description><![CDATA[

This is roughly the speech I gave as a keynote address at DjangoCon 2009 in Portland.
I&#8217;ve been programming Python web software for quite a while now.  I considered coming here and talked about WSGI, standards, cross-framework integration, etc., but I decided I wanted to come up here and talk to you as compatriots, as [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<blockquote><p>
This is roughly the speech I gave as a keynote address at <a class="reference external" href="http://www.djangocon.org/">DjangoCon 2009</a> in Portland.</p></blockquote>
<p>I&#8217;ve been programming Python web software for quite a while now.  I considered coming here and talked about WSGI, standards, cross-framework integration, etc., but I decided I wanted to come up here and talk to you as compatriots, as fellow open source programmers.</p>
<p>Over the past year or so I have been thinking a lot about politics.  Not electoral politics per se, or the geopolitical situation, but the question of the meaning of what we are doing.  Maybe it is some sort of programmer midlife crisis: why am I doing what I&#8217;m doing, and why does it matter?  And also I have been thinking a lot about open source &#8212; what this thing that we&#8217;re doing means in the larger context.  Are we just engineers?  Is there some sort of movement?  If so, what is that movement?  Especially as open source has become more popular, the sense of a movement seems to dwindle.  It felt like a movement 10 years ago, but not as much today.  Why should this happen?  Why now, in the midst of success does open source seem less politically relevant than it did 10 years ago?</p>
<p>I&#8217;m also speaking somewhat to Django specifically, as I think it is one of the communities with a bit more resistance to the idea of the politics of code.  The Django philosophy is more: the value of this code is the value of what you do with it.  I&#8217;m not here to criticize this perspective, but to think about how we can find meaning without relying on the traditional free software ideas.  To see if there&#8217;s something here that isn&#8217;t described yet.</p>
<p>I&#8217;d like to start with a quick history of free and open source software.  My own start was in highschool where I was taking a class in which we all used Emacs.  This was my first introduction to any real sort of programming environment, to Unix, to a text editor that was anything to talk about.  At the time Emacs would say at startup &quot;to learn more about the GNU project hit Control-H Control-P&quot; &#8212; because of course you need a keyboard shortcut to get to a philosophy statement about an editor.  So one day I hit Control-H Control-P.  I was expecting to see some sort of About Message, or if you remember the software of the times maybe something about Shareware, or even &quot;if you really like this software, consider giving to the Red Cross.&quot;  But instead I came upon the GNU Manifesto.</p>
<div class="section" id="gnu-manifesto">
<h2>GNU Manifesto</h2>
<p>I&#8217;d like to read a couple quotes from the <a class="reference external" href="http://www.gnu.org/gnu/manifesto.html">GNU Manifesto</a>.  There are more <a class="reference external" href="http://www.gnu.org/gnu/thegnuproject.html">modern descriptions of GNU</a>, but this is one of the first documents describing the project and its mission, written by Richard Stallman.  Let me quote the section &quot;Why I Must Write GNU&quot;:</p>
<blockquote>
<p>&quot;I consider that the golden rule requires that if I like a program I must share it with other people who like it. Software sellers want to divide the users and conquer them, making each user agree not to share with others. I refuse to break solidarity with other users in this way. [it continues...]</p>
<p>&quot;So that I can continue to use computers without dishonor, I have decided to put together a sufficient body of free software so that I will be able to get along without any software that is not free.&quot;</p>
<p>[later it goes on...]</p>
<p>&quot;The fundamental act of friendship among programmers is the sharing of programs; marketing arrangements now typically used essentially forbid programmers to treat others as friends. The purchaser of software must choose between friendship and obeying the law. Naturally, many decide that friendship is more important. But those who believe in law often do not feel at ease with either choice. They become cynical and think that programming is just a way of making money.&quot;</p>
</blockquote>
<p>When I read this statement I was immediate head-over-heels in love with this concept.  As a teenager, thinking about programming, thinking about the world, having a statement that was so intellectually aggressive was exciting.  It didn&#8217;t ask: &quot;how wrong is piracy really&quot;, or &quot;why are our kids doing this&quot;, but it asked &quot;is piracy a moral imperative&quot; &#8212; that&#8217;s the kind of aggressive question that feels revolutionary and passionate.</p>
<p>Let me go over one of the lines that I think exemplifies this:</p>
<blockquote><p>
&quot;I consider that the golden rule requires that if I like a program I must share it with other people who like it.&quot;</p></blockquote>
<p>It wasn&#8217;t saying: what are we not allowed to do, nor did it talk about some kind of societal injustice.  It didn&#8217;t talk about the meaning of actions or their long-term effects.  Instead it asked: what must we do, not as a society, not in service of some end, but what are we called upon to do as an <em>individual</em>, <em>right now</em>, in service of the people we call friends.  It didn&#8217;t allude to any sociological explanation, natural selection, economics; there is just the golden rule, the most basic tenant of moral thought.</p>
</div>
<div class="section" id="free-software-vs-open-source">
<h2>Free Software vs. Open Source</h2>
<p>When I first encountered free software, I suppose about 15 years ago, this was during one of the more difficult periods of its evolution.  It was past the initial excitement, the initial optimism that the project would take only a couple years to reach parity with closed-source Unix, it was before it was clear how the project would move forward.  Linux was young and seemed to be largely off the radar of Richard Stallman and other GNU advocates, and they were struggling to fill in final key pieces, things like a kernel, widgets, and they hadn&#8217;t even thought about entirely new things like browsers.</p>
<p>The message that came through from that period is not the message I wish came through.  The message I wish came through was that message from the GNU Manifesto, that spirit of a new sense of duty and ability.  When people talk about Richard Stallman and the Free Software Foundation and the GNU Project, they&#8217;ll often point to the GNU General Public License as the most important contribution &#8212; the GPL.  I&#8217;m sure you all know something about it.  Of course the core concept there is the idea of copyleft.  Not only will the software be open, but it&#8217;s takes the implied perspective that the principles of freedom are rights &#8212; that unfortunately the world is not wise enough to see that use, distribution, and modification are rights; but the GPL still asserts that these <em>are</em> your rights.  When you become one of us, when you participate in the freedoms this license grants you, when you use the GPL, there is encoded in the license a support for this sense of the natural right of free software.  We, GNU, can&#8217;t encode that for the world, but for the software that we write these rights are inalienable.</p>
<p>But as I said those were difficult times.  There was a great deal of pressure.  People were trying to understand what open source meant. People still struggle with questions: how would an economy function, how would a programmer get a job, if this is as successful as people hoped will we all just be out of jobs?  Other questions were: who will write the software that no one wants to write?  How can I, embedded in a situation where I can&#8217;t actually use only free software &#8212; remember at this time there was no way to use completely free software &#8212; how can I assert a duty to do something that is not possible?  How can I be useful unless I interface with all these proprietary things?  If I deal with companies which aren&#8217;t comfortable with open source software, then what?  After all, open source seemed only barely plausible at this time.  It was not an easy argument to make.</p>
<p>And all this was before the term &quot;open source&quot; really took hold as a distinct idea.  That itself is an interesting story.  There was a time during this marketing period when there arose a kind of terminology divide &#8212; free software vs. open source software.  The terminology divide was that the &quot;free&quot; in free software implied you couldn&#8217;t charge anything, that made people think about price, might even imply cheapness.  Open source directly refers to programming, uses the feel-good term &quot;open&quot;, and doesn&#8217;t sound too revolutionary.  But besides that there was also a substantial philosophical difference about the value of the software itself.</p>
<p>So there was a difference in how things were going to be pitched, but also a difference in what people thought the general value of this project was.  From GNU and Richard Stallman there was the notion that this was right because it was right; it was a moral imperative.  The virtue of what we build is in its freedom; if it is also technically superior then that&#8217;s great, but it is not how we should judge our success.  We were giving people self-determination: programmer self-determination, user self-determination&#8230; on the open source side the argument was that this is a good way to create software.  Programmers working together can do better work.  With many eyes all bugs are shallow.  All working together, we&#8217;ll work faster, you get the benefit of free contributions from all sorts of people.  People were clamouring to get all these proprietary companies with failing software products to open source their software; miracles will occur!  What you thought was useless will regain value!  You&#8217;ll reattain relevance!</p>
<p>The open source and free software philosophical divide: on one side practical concerns, on the other moral.  And this is what I want to talk about later: can we find a moral argument for these practical concerns?</p>
<p>The basic free/open disagreement continues in debates over licenses: the GPL vs. the BSD and other permissive licenses.  If you read the <a class="reference external" href="http://www.gnu.org/copyleft/gpl.html">GPL</a> it talks a great deal about philosophy; if you read the <a class="reference external" href="http://www.opensource.org/licenses/bsd-license.html">BSD license</a> it&#8217;s really just some disclaimers and basic instructions, and the one line: &quot;Redistribution and use in source and binary forms, with or without modification, are permitted.&quot;  It doesn&#8217;t say why you&#8217;ve received this software, or any philosophy about rights and freedoms, or even encourage you to use the same license on your own software.  An engineer&#8217;s license.</p>
<p>So these two licenses in many ways became a focus and definition of free and open source software.  If you look at the <a class="reference external" href="http://www.opensource.org/">Open Source Initiative</a>, which has served to define what &quot;open source&quot; means, it is basically just a <a class="reference external" href="http://www.opensource.org/licenses/alphabetical">list of approved licenses</a>.  If you use one of those licenses, the software is open source, if not then it is closed.</p>
<p>I think this is disappointing, because licenses are just law, and law is not very interesting.  A law tells you what you shouldn&#8217;t do, it doesn&#8217;t tell you what you should do.  When both sides are talking about freedom, the licenses just define freedom as the lack of certain restrictions.  Take away those restrictions and voila, you are free&#8230; as though we are all just bundles of freedom waiting to be released.</p>
</div>
<div class="section" id="self-definitions">
<h2>Self-Definitions</h2>
<p>With licenses we have a negative definition of our community.  Either license you choose, the license feels like a reaction against closed source software.  If you can imagine a world in which there was no copyright, where our platforms were all setup to distribute source code in modifiable forms, where everything was open and everything was free, then none of these licenses would matter.  No one would be compelled to create the GPL in such a world; we wouldn&#8217;t advocate for copyright just so we can secure people&#8217;s freedoms.  In that kind of world all this licensing disappears.  And this isn&#8217;t even so weird a world.  You can pretend there&#8217;s no copyright now.  Maybe you have to reverse-engineer some stuff.  There&#8217;s lots of places in the world where no one really gives a damn about copyright.  But those places don&#8217;t feel open source to me, they don&#8217;t feel that more free.  We aren&#8217;t made unfree just by legal restrictions; freedom is something we have to actively grasp.</p>
<p>I don&#8217;t think what we do is predicated on copyright.  Indeed, many projects are comfortable with an entirely confused copyright ownership.  This causes very few problems.  A focus on licensing makes us into a reaction against proprietary software, where we allow proprietary software and its makers to define what it means to be <em>us</em>.</p>
<p>This concerns me because it isn&#8217;t just about formal definitions and terminology.  When I say <em>what do I do</em>, I say I am an open source programmer.  That&#8217;s not just an attribute, like saying that my hair is brown.  Open source is a way in which I see myself, a way I think about my craft, my profession, and a way I justify the work I put out to the world: that it aligns with these values.  So it&#8217;s very important to me what these values are.  And it&#8217;s frustrating to see open source defined in reaction to closed source software, because personally I don&#8217;t care about closed source software that much.</p>
<p>I never really cared much about fighting Microsoft, and I certainly don&#8217;t care now.  I see myself as a builder; this is what always drew me towards programming.  The desire to build new things.  This is our privilege as programmers, that we always have the opportunity to build new things.  If we&#8217;re asked to do something again and again and again, you always have the power to do it in a more abstract way, to generalize it away, until you can start to ignore the requests and move on to another problem.  This is something unique thing to computer programming.  These are the kind of unique attributes that make us different as a profession and as a craft than just about anything I can think of.</p>
<p>So I&#8217;m frustrated.  Here we are stuck in this notion of a license as a self-definition.  I want to find a new self-definition, a new idea of what makes us us.</p>
</div>
<div class="section" id="what-makes-us-us">
<h2>What Makes Us Us</h2>
<p>So&#8230; what makes us us?</p>
<p>I was saying about Django, the community is not particularly enthusiastic about philosophy.  Or maybe I should say, Django&#8217;s philosophy is: the value of the code is the thing you do with it.  These abstract discussions about architecture, reuse, big plans&#8230; instead, Django as a community encourages you to keep your head in the code, think about what you want to do, and then do it.  Don&#8217;t shave yaks.</p>
<p>But I&#8217;m not here to tell you to get philosophical about freedom, or to berate you for a functional definition of value.  I&#8217;d like to look at this community for what it is, and ask: what is the value system here?  Maybe it isn&#8217;t described, but I also don&#8217;t think it is therefore absent.</p>
<p>So&#8230; when I say I identify as an open source programmer, what is it that I am identifying as?</p>
<p>I don&#8217;t believe licensing makes something truly open source.  There was this clamour in the past to get companies to open source their products.  This has stopped, because all the software that got open source sucked.  It&#8217;s just not very interesting to have a closed source program get open sourced.  It doesn&#8217;t help anyone, because the way closed source software is created in a very different way than open source software.  The result is a software base that just does not engage people in a way to make it a valid piece of software for further development.  At least not unless you have something peculiar going on&#8230; an economic force like you had behind Mozilla that could push things forward even in the midst of all the problems that project had.  One might even ask, is Mozilla still suffering from that proprietary background, when something like KHTML or WebKit which came from a truly open source background, and has been a more successful basis for collaboration and new work.</p>
<p>So whatever it is that makes something open source, it&#8217;s not just licensing.  Given a codebase, we can&#8217;t necessarily expect that someone going to care about it and love it and make it successful.  A lot of people have described what makes a successful open source codebase; I&#8217;d like to talk some about what the communities look like.</p>
<hr class="docutils" />
<p>Open source works as a fairly loose federation of people together.  Everyone involved is involved as an individual.  Companies seldom participate directly in open source.  Companies might use open source, they might sponsor people to work on open source projects, they might ask an employee to act as a liason.  But it&#8217;s not cool to submit a bug as a company.  You submit it as yourself.  If someone asks a question, you answer as yourself.  You don&#8217;t join a mailing list under the company&#8217;s name.  And even when you put a company name on a product, it&#8217;s hard to relate to the product as a <em>project</em> without some sense of authorship, of the underlying individual.</p>
<hr class="docutils" />
<p>There&#8217;s also very little money being moved about.  There&#8217;s not a lot of commercial contracts.  You might get software, you might get bug fixes, you might get reputation, but there&#8217;s seldom any formal way setup to introduce commerce into the community.  How many projects let you pay to escalate a bug?  Even if everyone involved might like that, it&#8217;s just not there.</p>
<hr class="docutils" />
<p>But I want to get back to individuals.  How things are created is not that someone determines a set of priorities, lays them out, then people work on implementation based on those priorities.  That of course is how things typically work at a company, as an employee.  But open source software and open source projects are created because an individual looks at the world and sees an opportunity to create something they think should exist.  Maybe it resolves a tension they&#8217;ve felt in their work, maybe it allows that person to respond to the priorities from above better, but the decision to implement lies primarily with the implementor.  When someone makes a decision to move a product from simply private code &#8212; regardless of the license &#8212; to being a real open source project, that decision is almost always driven by the programmer.</p>
<hr class="docutils" />
<p>Underneath most open source work there is a passion for the craft itself.  This is what leads to a certain kind of quality that is not the norm in closed source software.  It&#8217;s not necessarily less bugs or more features, but a pride in the expression itself.  A sense of aesthetic that applies to even the individual lines of software, not just to the functionality produced.  This kind of aesthetic defies scheduling and relies on personal motivation.</p>
<p>As open source programmers we are not first concerned with how a task fits into institutions, how a task can be directed by a hierarchy or an authority, or even how the task can be directed by economics.  The tasks that we take on are motivated by aesthetic, by personal excitement and drive.</p>
<hr class="docutils" />
<p>We are also in a profession where there is little stasis.  If you can create something once, you can create it a thousand times, through iteration or abstraction.  You can constantly make your own effort obsolete.  A good programmer is always trying to work themselves out of a job.</p>
<p>Djangocon didn&#8217;t exist a couple years ago.  Django didn&#8217;t exist only a few years ago.  And I don&#8217;t think there&#8217;s anyone here who thinks that, having found Django, they&#8217;ve reached some terminal point.  It&#8217;s hardly even a point to pause.  There&#8217;s a constant churn, a constant push forward that we&#8217;re all participating in.</p>
<p>As a result it&#8217;s demanded of us that we have a tight feedback cycle, that education is not a formal affair but a constant process in our own work.  There&#8217;s a constant churn, and a professional sense we&#8217;re kind of like fruit flies.  A generation of knowledge and practice is short enough that the evolution is rapid and visible.  You don&#8217;t have to be particularly old or even thoughtful to see the changes.  You can look back even on your own work and on communities to see changes over the course of a couple years, to see changes and shifts and a maturing of the work and the community.</p>
<hr class="docutils" />
<p>Another attribute of open source: our communities are ad hoc and temporary.  We do not overvalue these communities and institutions; we regularly migrate, split, recombine, and we constantly rewrite.  There is both an arrogance and a humility to this.  We are arrogant to think This Time Will Be Different.  But we are humble enough to know that last time wasn&#8217;t different either.  There will always be a next thing, another technique, another vision.</p>
<p>Because of the ad hoc nature of the communities, we don&#8217;t have long collective plans.  The ad hoc community may be the intersection of different <em>personal</em> long range plans, a time when different visions somehow coincide in a similar implementation.  Or perhaps it&#8217;s just serendipity, or leadership.  But we make each decision anew.  I believe this protects us from being misled by sunk costs.  The idea of a sunk cost is that when you make an investment, you&#8217;ve put in effort, that effort is gone.  Just because you&#8217;ve put in effort doesn&#8217;t mean you&#8217;ve received value, or that the path of investment remains valid.  But as humans we are highly reluctant to let go of a plan that we&#8217;ve invested in.  We have a hard time recognizing sunk costs.</p>
<p>I believe in our developer community we approach our work with sufficient humility that we can see our work as simply a sunk cost.  Our effort does not entitle us to any particular success, so we can choose new directions with more rationality than an institution.  Though it can also be argued that we are too quick to dismiss past investments; there is a youthfulness even to our oldest members.</p>
<hr class="docutils" />
<p>We do not have hierachies with decision makers above implementors.  Some people have veto power (a BDFL), but no one has <em>executive</em> power.  A decision only is valid paired with an implementation.  You cannot decide something based on information you <em>wish</em> was true; you cannot decide on something then blame the implementors for getting it wrong.  We are in this sense vertically integrated, decision and implementation are combined.  The result may be success or failure, commitment or abandonment, but the hierarchy is flat and the feedback loop is very tight.  And if an individual feels stymied, there is always another community to join or create.</p>
<p>Though this is only a start, it&#8217;s these attributes that I would prefer define us, not licenses.</p>
<p>I also would like that this could be a model for how other work should be done.</p>
</div>
<div class="section" id="why-us">
<h2>Why Us?</h2>
<p>Why would we, as programmers, be unique or worthy of emulation?  I mentioned before that we constantly work ourselves out of our job.  We also create the tools we use to do the work.  We define the structure of our communities.  We&#8217;re consistently finding novel ways to use the internet build those communities.  It&#8217;s not that we as a group are somehow uniquely wise, or some Greatest Generation, but we have become distinctly self-empowered.  There is a uniqueness to us.  It might be a coincidence of history, but it is there.</p>
<p>A question I might then ask: is there a political meaning to this?  This is the form our craft takes, but does that mean anything?  We work with computers, someone else might work with their hands, an artist considers color, a salesperson learns how to put on a good smile.</p>
<p>I haven&#8217;t quite figured this out yet, but I think there&#8217;s something in this.  Over the years I&#8217;ve found myself looking at politics in a increasingly technocratic lens; more so than as a liberal, conservative, or radical.  That is, instead of looking at the world and seeing what&#8217;s wrong about it, and explaining it in terms of a class struggle, a cultural conflict, in terms of advocacy or invented enemies or allies, I see a system that just works how it works.  It&#8217;s more like gears than like a war.  The gears turn and sometimes we don&#8217;t like what results, but it&#8217;s not malice.</p>
<p>But I also don&#8217;t think we are slaves to the technical functioning of the system.  None of us are inevitably caught up in some statistical outcome of markets, or condemned by money in politics or advertising.  At any time we can say Here Is What I Believe, and it is as powerful as any of those other things; we&#8217;re too quick to look at the people who aren&#8217;t asserting a belief, who aren&#8217;t asserting their own potential for self-empowerment and direction, and we ignore everyone who is aware and concerned and attempting self-determination.  We are at danger of ignoring the great potential around us.</p>
<p>It is in this sense that I wonder not just how we can spread the idea of freedom through licensing, which has inspired the free culture movement, but also how we can spread this idea and practice of individual action, of combining decision and implementation, and of constant ad hoc collaboration.</p>
<p>I&#8217;m not just thinking of politics directly, but of professional lives as well.  Right now we&#8217;re talking about healthcare.  It&#8217;s a very political issue, and yet healthcare is ultimately a profession, a job, an action.  How we work on that, collaboratively or not, is as political as any aspect of the system.</p>
<p>One anecdote that made me think about this, is a task I had that involved putting authentication in front of a mailing list.  The mailing list happened to be for wound, ostomy, and continence nurses, and in the process of the job I read a bunch of their emails from the archives.  As wound nurses they spent a lot of time asking about specific questions &#8212; maybe a wound that wouldn&#8217;t heal, they kept draining the puss and it discharge kept reappearing, and did anyone have ideas of the next technique to try?</p>
<p>Reading a few of these I could tell this was a profession where you needed a strong stomach.  But the whole interaction, the way they described problems, the way people came back with answers, it felt very familiar to me.  It was the same kind of discussions I could imagine having about Linux administration or debugging.  And the goals were similar.  No one was making money, there wasn&#8217;t really reputation on the line, it was just people who wanted to help their patients and who wanted to help each other.</p>
<p>So that mailing list was great, but it&#8217;s unfortunately not that common.  And if nurses were open to that kind of collaboration, doctors don&#8217;t seem nearly as ready.  And there&#8217;s a lot of professions where there&#8217;s not even that thoughtfulness.  I believe in any profession there&#8217;s the ability to do it well or not; there&#8217;s nothing so rote or well understood that there&#8217;s no room for improvement.  It doesn&#8217;t have to be fancy technology, it can just be a technique, a way of managing work; all things worth doing have some way of improving, by bringing in this same sense of collaboration and individual action and thoughtfulness, all things can be implemented better than they are now.  What I&#8217;m describing isn&#8217;t a fancy new website for professionals, but about people look at their own work differently; the technology is not the hard part.</p>
</div>
<div class="section" id="the-political">
<h2>The Political</h2>
<p>Changing how people look at their work I think is political.  It involves individual empowerment.  It can mean economic change.  I also think it deemphasizes competition.  When I think about Pylons, or Django, or TurboGears, or WSGI, there&#8217;s competition, but it&#8217;s also collegial.  There&#8217;s not really that much of a sense of survival.  We aren&#8217;t carving out territories, we&#8217;re just finding paths to some unknown end.  If something else wins out, well, we&#8217;re all just along for the ride.  In the end it is inevitable that something else other than what <em>any</em> of us are working on will win out over what any of us are doing.  Just like everyone eventually loses their job at least to death or retirement.  There&#8217;s no permanency.  But if we can be individually more productive, it doesn&#8217;t have to mean we&#8217;ve put someone else out.  It <em>could</em> mean we all, all of society, all of humanity, just do <em>more</em>.  Why do we have to set ourselves against the Chinese, or Europe against the U.S.?  Why do we have to set ourselves one economy against another?</p>
<p>Or consider government itself: we&#8217;re obsessed with our elected officials, but of course government is far larger than just the elected officials.  The U.S. Federal Government alone has 1.8 million employees.  We constantly threaten to institute accountability, meaning that we&#8217;ll poke and prod government workers from the outside and expect better outcomes.  That we expect anything to come of this is absurd, but somehow accountability has become an easy alternative to constructive suggestions for improvement.</p>
<p>But why shouldn&#8217;t we expect that government workers <em>want</em> to do better?  I believe in fact those people doing the work are especially well equiped to figure out <em>how</em> to do better.  But it&#8217;s not automatic.  They aren&#8217;t empowered in a system that is so exceptionally hierarchical.  Lately we&#8217;ve seen lots of efforts to ask the public how to do government work better, but we&#8217;ve seen nothing asking <em>government</em> how to do government work better.</p>
<p>These are the kinds of things I&#8217;d like to see us all think about more: open source has done incredible things, has inspired new ideas, about more than just software and engineering, but I think we have yet more things to give.</p>
<p>Thank you for your time.</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/09/10/a-new-self-definition-for-foss/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>WebOb decorator</title>
		<link>http://blog.ianbicking.org/2009/05/22/webob-decorator/</link>
		<comments>http://blog.ianbicking.org/2009/05/22/webob-decorator/#comments</comments>
		<pubDate>Sat, 23 May 2009 02:35:58 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=122</guid>
		<description><![CDATA[
Lately I&#8217;ve been writing a few applications (e.g., PickyWiki and a revisiting a request-tracking application VaingloriousEye), and I usually use no framework at all.  Pylons would be a natural choice, but given that I am comfortable with all the components, I find myself inclined to assemble the pieces myself.
In the process I keep writing [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Lately I&#8217;ve been writing a few applications (e.g., <a class="reference external" href="http://pickywiki.org">PickyWiki</a> and a revisiting a request-tracking application <a class="reference external" href="http://svn.pythonpaste.org/Paste/VaingloriousEye/trunk">VaingloriousEye</a>), and I usually use no framework at all.  <a class="reference external" href="http://pylonshq.com">Pylons</a> would be a natural choice, but given that I am comfortable with all the components, I find myself inclined to assemble the pieces myself.</p>
<p>In the process I keep writing bits of code to make WSGI applications from simple <a class="reference external" href="http://pythonpaste.org/webob/">WebOb</a> -based request/response cycles.  The simplest form looks like this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> webob <span class="kw1">import</span> Request, Response, exc<br />
<br />
<span class="kw1">def</span> wsgiwrap<span class="br0">&#40;</span>func<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> wsgi_app<span class="br0">&#40;</span>environ, start_response<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; req = Request<span class="br0">&#40;</span>environ<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resp = func<span class="br0">&#40;</span>req<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> exc.<span class="me1">HTTPException</span>, e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; resp = e<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> resp<span class="br0">&#40;</span>environ, start_response<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> wsgi_app<br />
<br />
@<span class="co1">wsgiwrap</span><br />
<span class="kw1">def</span> hello_world<span class="br0">&#40;</span>req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">return</span> Response<span class="br0">&#40;</span><span class="st0">'Hi %s!'</span> % <span class="br0">&#40;</span>req.<span class="me1">POST</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'name'</span>, <span class="st0">'You'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>But each time I&#8217;d write it, I change things slightly, implementing more or less features.  For instance, <a class="reference external" href="http://blog.ianbicking.org/2008/10/24/decorators-and-descriptors/">handling methods</a>, or coercing other responses, or handling middleware.</p>
<p>Having implemented several of these (and <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/contrib">reading other people&#8217;s implementations</a>) I decided I wanted WebOb to include a kind of reference implementation.  But I don&#8217;t like to include anything in WebOb unless I&#8217;m sure I can get it <em>right</em>, so I&#8217;d really like feedback.  (There&#8217;s been some <a class="reference external" href="http://groups.google.com/group/paste-users/browse_thread/thread/7346e75940413f46">less than positive feedback</a>, but I trudge on.)</p>
<p>My implementation is in a <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/branches/ianb-decorator-experiment">WebOb branch</a>, primarily in <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/branches/ianb-decorator-experiment/webob/dec.py">webob.dec</a> (along with some <a class="reference external" href="http://svn.pythonpaste.org/Paste/WebOb/branches/ianb-decorator-experiment/tests/test_dec.txt">doctests</a>).</p>
<p>The most prominent way this is different from the example I gave is that it doesn&#8217;t change the function signature, instead it adds an attribute <tt class="docutils literal"><span class="pre">.wsgi_app</span></tt> which is WSGI application associated with the function.  My goal with this is that the decorator isn&#8217;t intrusive.  Here&#8217;s the case where I&#8217;ve been bothered:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">class</span> MyClass<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; @<span class="co1">wsgiwrap</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> form<span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> Response<span class="br0">&#40;</span>form_html...<span class="br0">&#41;</span><br />
<br />
&nbsp; &nbsp; @<span class="co1">wsgiwrap</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> form_post<span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; handle submission<br />
&nbsp;</div>
<p>OK, that&#8217;s fine, then I add validation:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
@<span class="co1">wsgiwrap</span><br />
<span class="kw1">def</span> form_post<span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> req <span class="kw1">not</span> valid:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">form</span><br />
&nbsp; &nbsp; handle submission<br />
&nbsp;</div>
<p>This still works, because the decorator allows you to return <em>any</em> WSGI application, not just a WebOb Response object.  But that&#8217;s not helpful, because I need errors&#8230;</p>
<div class="dean_ch" style="white-space: wrap;"><br />
@<span class="co1">wsgiwrap</span><br />
<span class="kw1">def</span> form_post<span class="br0">&#40;</span><span class="kw2">self</span>, req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> req <span class="kw1">not</span> valid:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">form</span><span class="br0">&#40;</span>req, errors<span class="br0">&#41;</span><br />
&nbsp; &nbsp; handle submission<br />
&nbsp;</div>
<p>That is, I want to have an option argument to the <tt class="docutils literal"><span class="pre">form</span></tt> method that passes in errors.  But I can&#8217;t do this with the traditional <tt class="docutils literal"><span class="pre">wsgiwrap</span></tt> decorator, instead I have to refactor the code to have a third method that both <tt class="docutils literal"><span class="pre">form</span></tt> and <tt class="docutils literal"><span class="pre">form_post</span></tt> use.  Of course, there&#8217;s more than one way to address this issue, but this is the technique I like.</p>
<p>The one other notable feature is that you can also make middleware:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
@<span class="co1">wsgify.middleware</span><br />
<span class="kw1">def</span> cap_middleware<span class="br0">&#40;</span>req, app<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; resp = app<span class="br0">&#40;</span>req<span class="br0">&#41;</span><br />
&nbsp; &nbsp; resp.<span class="me1">body</span> = resp.<span class="me1">body</span>.<span class="me1">upper</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> resp<br />
<br />
capped_app = cap_middleware<span class="br0">&#40;</span>some_wsgi_app<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Otherwise, for some reason I&#8217;ve found myself putting an inordinate amount of time into <tt class="docutils literal"><span class="pre">__repr__</span></tt>.  Why I&#8217;ve done this I cannot say.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2009/05/22/webob-decorator/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Using pip Requirements</title>
		<link>http://blog.ianbicking.org/2008/12/16/using-pip-requirements/</link>
		<comments>http://blog.ianbicking.org/2008/12/16/using-pip-requirements/#comments</comments>
		<pubDate>Wed, 17 Dec 2008 01:30:21 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Packaging]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/12/16/using-pip-requirements/</guid>
		<description><![CDATA[
Following onto a set of recent posts (from James, me, then James again), Martijn Faassen wrote a description of Grok&#8217;s version management.  Our ideas are pretty close, but he&#8217;s using buildout, and I&#8217;ll describe out to do the same things with pip.
Here&#8217;s a kind of development workflow that I think works well:

A framework release [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Following onto a set of recent posts (from <a class="reference external" href="http://www.b-list.org/weblog/2008/dec/14/packaging/">James</a>, <a class="reference external" href="http://blog.ianbicking.org/2008/12/14/a-few-corrections-to-on-packaging/">me</a>, then <a class="reference external" href="http://www.b-list.org/weblog/2008/dec/15/pip/">James again</a>), Martijn Faassen <a class="reference external" href="http://faassen.n--tree.net/blog/view/weblog/2008/12/16/0">wrote a description of Grok&#8217;s version management</a>.  Our ideas are pretty close, but he&#8217;s using buildout, and I&#8217;ll describe out to do the same things with pip.</p>
<p>Here&#8217;s a kind of development workflow that I think works well:</p>
<ul class="simple">
<li>A framework release is prepared.  Ideally there&#8217;s a buildbot that has been running (as <a class="reference external" href="http://pylonshq.com:8010/">Pylons has</a>, for example), so the integration has been running for a while.</li>
<li>People make sure there are released versions of all the important components.  If there are known conflicts between pieces, libraries and the framework update their <tt class="docutils literal"><span class="pre">install_requires</span></tt> in their <tt class="docutils literal"><span class="pre">setup.py</span></tt> files to make sure people don&#8217;t use conflicting pieces together.</li>
<li>Once everything has been released, there is a known set of packages that work together.  Using a buildbot maybe future versions will also work together, but they won&#8217;t necessarily work together with applications built on the framework.  And breakage can also occur regardless of a buildbot.</li>
<li>Also, people may have versions of libraries already installed, but just because they&#8217;ve installed something doesn&#8217;t mean they really mean to stay with an old version.  While known conflicts have been noted, there&#8217;s going to be lots of unknown conflicts and future conflicts.</li>
<li>When starting development with a framework, the developer would like to start with some known-good set, which is a set that can be developed by the framework developers, or potentially by any person.  For instance, if you extend a public framework with an internal framework (or even a public sub-framework like <a class="reference external" href="http://pinaxproject.com/">Pinax</a>) then the known-good set will be developed by a different set of people.</li>
<li>As an application is developed, the developer will add on other libraries, or use some of their own libraries.  Development will probably occur at the trunk/tip of several libraries as they are developed together.</li>
<li>A developer might upgrade the entire framework, or just upgrade one piece (for instance, to get a bug fix they are interested in, or follow a branch that has functionality they care about).  The developer doesn&#8217;t necessarily have the same notion of &quot;stable&quot; and &quot;released&quot; as the core framework developers have.</li>
<li>At the time of deployment the developer wants to make sure all the pieces are deployed together as they&#8217;ve tested them, and how they know them to work.  At any time, another developer may want to clone the same set of libraries.</li>
<li>After initial deployment, the developer may want to upgrade a single component, if only to test that an upgrade works, or if it resolves a bug.  They may test out combinations only to throw them away, and they don&#8217;t want to bump versions of libraries in order to deploy new combinations.</li>
</ul>
<p>This is the kind of development pattern that requirement files are meant to assist with.  They can provide a known-good set of packages.  Or they can provide a starting point for an active line of development.  Or they can provide a historical record of how something was put together.</p>
<p>The easy way to start a requirement file for pip is just to put the packages you know you want to work with.  For instance, we&#8217;ll call this <tt class="docutils literal"><span class="pre">project-start.txt</span></tt>:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
Pylons<br />
-e svn+http://mycompany/svn/MyApp/trunk<span class="co1">#egg=MyApp</span><br />
-e svn+http://mycompany/svn/MyLibrary/trunk<span class="co1">#egg=MyLibrary</span><br />
&nbsp;</div>
<p>You can plug away for a while, and maybe you decide you want to freeze the file.  So you do:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ pip freeze -r project-start.<span class="me1">txt</span> project-frozen.<span class="me1">txt</span><br />
&nbsp;</div>
<p>By using <tt class="docutils literal"><span class="pre">-r</span> <span class="pre">project-start.txt</span></tt> you give <tt class="docutils literal"><span class="pre">pip</span> <span class="pre">freeze</span></tt> a template for it to start with.  From that, you&#8217;ll get <tt class="docutils literal"><span class="pre">project-frozen.txt</span></tt> that will look like:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
Pylons==<span class="nu0">0.9</span><span class="nu0">.7</span><br />
-e svn+http://mycompany/svn/MyApp/trunk@<span class="co1">1045#egg=MyApp</span><br />
-e svn+http://mycompany/svn/MyLibrary/trunk@<span class="co1">1058#egg=MyLibrary</span><br />
<br />
<span class="co1">## The following requirements were added by pip --freeze:</span><br />
Beaker==<span class="nu0">0.2</span><span class="nu0">.1</span><br />
WebHelpers==<span class="nu0">0.9</span><span class="nu0">.1</span><br />
nose==<span class="nu0">1.4</span><br />
<span class="co1"># Installing as editable to satisfy requirement INITools==0.2.1dev-r3488:</span><br />
-e svn+http://svn.<span class="me1">colorstudy</span>.<span class="me1">com</span>/INITools/trunk@<span class="co1">3488#egg=INITools-0.2.1dev_r3488</span><br />
&nbsp;</div>
<p>At that point you might decide that you don&#8217;t care about the nose version, or you might have installed something from trunk when you could have used the last release.  So you go and adjust some things.</p>
<p>Martijn also asks: how do you have framework developers maintain one file, and then also have developers maintain their own lists for their projects?</p>
<p>You could start with a file like this for the framework itself.  Pylons for instance could ship with something like this.  To install Pylons you could then do:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ pip -E MyProject install \\<br />
&gt; &nbsp; &nbsp;-r http://pylonshq.<span class="me1">com</span>/<span class="nu0">0.9</span><span class="nu0">.7</span>-requirements.<span class="me1">txt</span><br />
&nbsp;</div>
<p>You can also download that file yourself, add some comments, rename the file and add your project to it, and use that.  When you freeze the order of the packages and any comments will be preserved, so you can keep track of what changed.  Also it should be ameniable to source control, and diffs would be sensible.</p>
<p>You could also use indirection, creating a file like this for your project:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
-r http://pylonshq.<span class="me1">com</span>/<span class="nu0">0.9</span><span class="nu0">.7</span>-requirements.<span class="me1">txt</span><br />
-e svn+http://mycompany/svn/MyApp/trunk<span class="co1">#egg=MyApp</span><br />
-e svn+http://mycompany/svn/MyLibrary/trunk<span class="co1">#egg=MyLibrary</span><br />
&nbsp;</div>
<p>That is, requirements files can refer to each other.  So if you want to maintain your own requirements file alongside the development of an upstream requirements file, you could do that.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/12/16/using-pip-requirements/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Inverted Partials</title>
		<link>http://blog.ianbicking.org/2008/09/08/inverted-partials/</link>
		<comments>http://blog.ianbicking.org/2008/09/08/inverted-partials/#comments</comments>
		<pubDate>Tue, 09 Sep 2008 03:12:44 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/09/08/inverted-partials/</guid>
		<description><![CDATA[
I was talking with a coworker some time ago about his project, and he needed to update a piece of the page in-place when you go back to the page, and setting the page as uncacheable didn&#8217;t really work.  Which probably makes sense; I think at one time browsers did respect those cache controls, [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I was talking with a coworker some time ago about <a class="reference external" href="http://melkjug.com/">his project</a>, and he needed to update a piece of the page in-place when you go back to the page, and setting the page as uncacheable didn&#8217;t really work.  Which probably makes sense; I think at one time browsers <em>did</em> respect those cache controls, but as a result going back in history <em>through</em> a page could cause some intermediate page to be refreshed and needlessly slow down your progress.</p>
<p>Anyway, Rails uses <a class="reference external" href="http://wiki.rubyonrails.org/rails/pages/UnderstandingPartials">partials</a> to facilitate this kind of stuff in a general way.  Bigger chunks of your page are defined in their own template, and instead of rendering the full page you can ask just for a chunk of the page.  Then you do something like <tt class="docutils literal"><span class="pre">document.getElementById('some_block').innerHTML</span> <span class="pre">=</span> <span class="pre">req.responseText</span></tt>.  Mike Bayer just <a class="reference external" href="http://techspot.zzzeek.org/?p=29">described how to do this in Mako too</a>, using template functions.</p>
<p>When asked, another technique also occurred to me, using just HTML.  Just add a general way of fetching an element by ID.  At any time you say &quot;refresh the element with id X&quot;, and it asks the server for the current version of that element (using a query string variable <tt class="docutils literal"><span class="pre">document_id=X</span></tt>) and replaces the content of that element in the browser.</p>
<p>The client side looks like this (it would be much simpler if you used a Javascript library):</p>
<div class="dean_ch" style="white-space: wrap;"><br />
function refreshId<span class="br0">&#40;</span><span class="kw2">id</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; var el = document.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="kw2">id</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>! el<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; throw<span class="br0">&#40;</span><span class="st0">&quot;No element by id '&quot;</span> + <span class="kw2">id</span> + <span class="st0">&quot;'&quot;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; function handler<span class="br0">&#40;</span>data<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>this.<span class="me1">readyState</span> == <span class="nu0">4</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>this.<span class="me1">status</span> == <span class="nu0">200</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; el.<span class="me1">innerHTML</span> = this.<span class="me1">responseText</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw<span class="br0">&#40;</span><span class="st0">&quot;Bad response getting &quot;</span> + idURL + <span class="st0">&quot;: &quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; + this.<span class="me1">status</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; var req = <span class="kw3">new</span> XMLHttpRequest<span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; req.<span class="me1">onreadystatechange</span> = handler;<br />
&nbsp; &nbsp; var idURL = location.<span class="me1">href</span> + <span class="st0">''</span>;<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>idURL.<span class="me1">indexOf</span><span class="br0">&#40;</span><span class="st0">'?'</span><span class="br0">&#41;</span> == <span class="nu0">-1</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; idURL += <span class="st0">'?'</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; idURL += <span class="st0">'&amp;amp;#038;'</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; idURL += <span class="st0">'document_id='</span>+escape<span class="br0">&#40;</span><span class="kw2">id</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; req.<span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">&quot;GET&quot;</span>, idURL<span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; req.<span class="me1">send</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;<br />
<span class="br0">&#125;</span><br />
&nbsp;</div>
<p>Then you need the server-side component.  Here&#8217;s something written for <a class="reference external" href="http://pylonshq.com/">Pylons</a> (using <a class="reference external" href="http://codespeak.net/lxml/lxmlhtml.html">lxml.html</a>, and Pylons 0.9.7 which is configured to use <a class="reference external" href="http://pythonpaste.org/webob/">WebOb</a>):</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> pylons <span class="kw1">import</span> request, response<br />
<span class="kw1">from</span> lxml <span class="kw1">import</span> html<br />
<br />
<span class="kw1">def</span> get_id<span class="br0">&#40;</span>response, <span class="kw2">id</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>response.<span class="me1">content_type</span> == <span class="st0">'text/html'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">and</span> response.<span class="me1">status_int</span> == <span class="nu0">200</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; doc = html.<span class="me1">fromstring</span><span class="br0">&#40;</span>response.<span class="me1">body</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; el = doc.<span class="me1">get_element_by_id</span><span class="br0">&#40;</span><span class="kw2">id</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyError</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">pass</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.<span class="me1">body</span> = html.<span class="me1">tostring</span><span class="br0">&#40;</span>el<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> response<br />
<br />
<span class="kw1">class</span> BaseController<span class="br0">&#40;</span>WSGIController<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> __after__<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">id</span> = req.<span class="me1">GET</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'document_id'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">id</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; get_id<span class="br0">&#40;</span>response, <span class="kw2">id</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Though I&#8217;m not sure this is appropriate for middleware, you could do it as middleware too:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> webob <span class="kw1">import</span> Request<br />
<span class="kw1">class</span> DocumentIdMiddleware<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, app<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">app</span> = app<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__call__</span><span class="br0">&#40;</span><span class="kw2">self</span>, environ, start_response<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; req = Request<span class="br0">&#40;</span>environ<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">id</span> = req.<span class="me1">GET</span>.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'document_id'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> <span class="kw2">id</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">app</span><span class="br0">&#40;</span>environ, start_response<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; resp = req.<span class="me1">get_response</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">app</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; resp = get_id<span class="br0">&#40;</span>resp, <span class="kw2">id</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> resp<span class="br0">&#40;</span>environ, start_response<span class="br0">&#41;</span><br />
&nbsp;</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/09/08/inverted-partials/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>My Experience Writing a Build System</title>
		<link>http://blog.ianbicking.org/2008/06/19/my-experience-writing-a-build-system/</link>
		<comments>http://blog.ianbicking.org/2008/06/19/my-experience-writing-a-build-system/#comments</comments>
		<pubDate>Fri, 20 Jun 2008 04:41:54 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/06/19/my-experience-writing-a-build-system/</guid>
		<description><![CDATA[
Lately there&#8217;s been some interest in build processes among various people &#8212; Vellum was announced a while back, Ben has been looking for a tool and looking at Fabric, and Kevin announced Paver.  At the same time zc.buildout is starting to gain some users outside of the Zope world, and I noticed Minitage as [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Lately there&#8217;s been some interest in build processes among various people &#8212; <a class="reference external" href="http://www.zedshaw.com/projects/vellum/">Vellum</a> was announced a while back, <a class="reference external" href="http://groovie.org/2008/04/09/wheres-the-capistrano-knock-off-for-us-python-web-devs">Ben has been looking for a tool</a> and looking at <a class="reference external" href="https://savannah.nongnu.org/projects/fab/">Fabric</a>, and <a class="reference external" href="http://www.blueskyonmars.com/projects/paver/">Kevin announced Paver</a>.  At the same time <a class="reference external" href="http://pypi.python.org/pypi/zc.buildout">zc.buildout</a> is starting to gain some users outside of the Zope world, and I noticed <a class="reference external" href="http://www.minitage.org/doc/rst/">Minitage</a> as an abstraction on top of zc.buildout.</p>
<p>A while ago I started working on a build project for <a class="reference external" href="http://topp.openplans.org">Open Plans</a> called <a class="reference external" href="https://svn.openplans.org/svn/fassembler/trunk">fassembler</a>.  I think the result has been fairly successful and maintainable, and I thought I&#8217;d share some of my own reflections on that tool.</p>
<div class="section" id="update-what-we-were-trying-to-accomplish">
<h2><strong>Update:</strong> what we were trying to accomplish</h2>
<p>I didn&#8217;t make it clear in the post just what we were trying to do, and what this build system would accomplish.</p>
<p>Our site (<a class="reference external" href="http://openplans.org">openplans.org</a>) is made up of several separate servers with an HTML-rewriting proxy on the front end.  We have a Zope server running a custom application, Apache running WordPress MU, and some servers running Pylons or other Python web applications for portions of our site.  We needed a way to consistently reproduce this entire stack, all the pieces, plugged together so that the site would actually work.  Two equally important places where we had to reproduce the stack are for developer rigs and the production site.</p>
<p>Our code is primarily Python and we use a <em>lot</em> of libraries, developed both internally and externally.  Setting up the site is primarily a matter of installing the right libraries and configuration and setting up any databases (both a <a class="reference external" href="http://www.zope.org/Products/StandaloneZODB">ZODB</a> databases and several MySQL databases).  We use a few libraries written in C, but <a class="reference external" href="http://python.org/doc/current/lib/module-distutils.html">distutils</a> handles the compilation of those pretty transparently.</p>
<p>For this case we really don&#8217;t care about build tools that focus on compilation.  We don&#8217;t care about careful dependency tracking because we are compiling very little software.</p>
</div>
<div class="section" id="make-doesn-t-make-sense">
<h2>make doesn&#8217;t make sense</h2>
<p><strong>Update 2</strong>: If you think the make model makes lots of sense, read the preceding section &#8212; it makes sense for a different problem set than what we&#8217;re doing.</p>
<p>We initially had a system based on <a class="reference external" href="http://agendaless.com/Members/chrism/software/buildit">BuildIt</a>, which is kind of like <a class="reference external" href="http://en.wikipedia.org/wiki/Make_(software)">make</a> with Python as the control code.  It wasn&#8217;t really a good basis for our build tool, and I think it added a lot of confusion, compounded by the fact that we weren&#8217;t quite sure what we wanted our build to do.  Ultimately I think the make model of building doesn&#8217;t make sense.</p>
<p>The make model is based on the idea that you <strong>really</strong> want to save work.  So you detect changes and remake things only as necessary.  For compilation this might make sense, because you edit code and recompile a lot and it&#8217;s tedious to wait.  But we are building a website, and installing software, and none of that style of efficiency matters.  make-style detection of work to be done doesn&#8217;t even save any time.  But it does make the build more fragile (e.g., if you define a dependency incorrectly) and much harder to understand, and you constantly find yourself wiping the build and starting from scratch because you don&#8217;t trust the system.</p>
<p>The metaphor for the new build system was much simpler: do a list of things, top to bottom.  There&#8217;s no effort into detecting changes in the build, or changes in the settings, or anything else.</p>
</div>
<div class="section" id="do-things-carefully">
<h2>Do things carefully</h2>
<p>In the build system almost all actions go through the <a class="reference external" href="https://svn.openplans.org/svn/fassembler/trunk/fassembler/filemaker.py">filemaker</a> module.  This is <em>kind of</em> a file abstraction library.  But the goals are entirely different than convenience: the goal is transparency and safety.  In contrast Paver uses <a class="reference external" href="http://www.jorendorff.com/articles/python/path/">path.py</a> for convenience, but I&#8217;m not sure what the win would be if we used a model like that.</p>
<p><tt class="docutils literal"><span class="pre">filemaker</span></tt> itself is heavily tied to the framework that it&#8217;s written for, specifically user interaction and logging.  Most tasks just <em>do</em> things, and rely on filemaker to detect problems and ask the user questions.  For example, every time a file is written, it checks if the file exists, and if it has the same content.  If it exists with other content, it asks the user about what to do.  It doesn&#8217;t overwrites files without asking (at least by default).  I think this makes the tool more humane as the default behavior for a build is to be careful and transparent.  The build author has to go out of their way to make things difficult.</p>
<p>Many zc.buildout recipes will blithely overwrite all sorts of files which always made me very uncomfortable with the product.  It&#8217;s the <em>recipes</em> in zc.buildout which do this, not the buildout framework itself, but because buildout made overwriting the easy thing to do, and didn&#8217;t start with humane conventions or tools, this behavior is the norm.</p>
<p>What I think filemaker most accomplished was the ability to do file operations while also asserting the expected state of the system, and so makes build bugs noticeable earlier instead of getting a build process that finishes successfully but creates a buggy build, or having an exception show up far from where the error was originally introduced.</p>
<p>Also, because it won&#8217;t overwrite your work in progress this has saved the build from engendering deep feelings of hatred in cases when it might overwrite your work in progress.  It&#8217;s hard to detect this absence of hatred, but I know that I&#8217;ve felt it with other systems.</p>
</div>
<div class="section" id="update-a-corollary-ignore-no-errors">
<h2><strong>Update:</strong> a corollary: ignore no errors</h2>
<p>One question you might wonder about: why not a shell script?  We did prototype some things as shell scripts, but we&#8217;ve consistently moved to Python at some point, even things that seemed really trivial.  The problem with shell scripts is they have horribly bad behavior with respect to errors.  Ignoring errors is really really easy, noticing errors is really hard.</p>
<p>This is absolutely unacceptable for builds.  Builds must not ignore errors.  The build may mostly work despite an error.  It might be totally broken, but the error message is lost in all sorts of useless output.  The error message probably makes no sense.  The context is lost.  No suggestion is given to the user.</p>
<p>When builds work, that&#8217;s great.  Build <em>do not</em> always work.  They always fail sometimes, and some poor sucker (usually in some hot potato-like arrangement) has to figure out what went wrong.  You have to plan for these problems.</p>
<p>Everything in the build tries to be careful about errors.  All places where it is not, it is a bug.  The resolution isn&#8217;t to see something appear to work, but create a broken build, and say &quot;oh, you forgot to set X&quot;.  The resolution is to make sure when you forget to set X it gives you an error that tells you to set X.</p>
<p>This is one of the more important and more often ignored principles of a good build/deployment system.  Maybe it&#8217;s gotten better, but when I first used zc.buildout (<em>very</em> early in its development) the poor handling of errors was by far the biggest problem and it left me with a bad taste in my mouth.  easy_install and setuptools in general is also very flawed in this respect.</p>
</div>
<div class="section" id="log-interesting-things">
<h2>Log interesting things</h2>
<p>I tried to make a compromise between logging very verbosely, and being too quiet.  As a user, I want to see everything <em>interesting</em> and leave out everything <em>boring</em>.  Determining interesting and boring can be a bit difficult, but really just require some attention and tweaking.</p>
<p>To make it possible to visually parse the output of the tool I found both indentation and color to be very useful.  Indentation is used to represent subtasks, and color to make sections and warnings stand out.</p>
<p>The default verbosity setting is not to be completely quiet.  Silence is a Unix convention that just doesn&#8217;t work for build tools.  Silence gets you interactions like this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ build-something target-directory/<br />
<span class="br0">&#40;</span>much <span class="kw3">time</span> passes<span class="br0">&#41;</span><br />
Error: cannot write /home/ianb/builds/<span class="nu0">20080426</span>/target-directory/products/AuxInput/auxinput/config/configuration.<span class="kw3">xml</span><br />
&nbsp;</div>
<p>Why did it want to write that file?  Why can&#8217;t it write that file?  Is the build buggy?  Did I misconfigure it?  Does the directory exist?</p>
<p>The typical way of handling this is either to run the build again with logging setup or otherwise make it more verbose, or to get in the habit of always running it verbose.</p>
</div>
<div class="section" id="mixing-code-and-configuration">
<h2>Mixing code and configuration</h2>
<p>BuildIt, which we were using before, had the ability to put variables in settings, and you could read an option from another section with something like <tt class="docutils literal"><span class="pre">${section/option}</span></tt>.  It was limited to simple (but recursive) variable substitution, and had some clever but very confusing rules that created a kind of inheritance.</p>
<p>I liked the ability to do substitution, but wasn&#8217;t happy with the compromise BuildIt made.  I wasted a <em>lot</em> of time trying to figure out the context of substitutions.  So, I saw two directions.  One was to remove the cleverness and just do simple substitution.  This is the choice zc.buildout made.  The other was to go whole-hog.  With a bit of trepidation I decided to to go for it, and I made the choice to treat all configuration settings as <a class="reference external" href="http://pythonpaste.org/tempita/">Tempita</a> templates.  All configuration is generally accessed via <tt class="docutils literal"><span class="pre">config.setting_name</span></tt>, and that lazily interpolates the setting (it took me quite a while to figure out how to avoid infinite loops of substitution).  Because evaluation is done lazily settings can depend on each other and be overridden and have lots of code in defaults (e.g., a default that is calculated based on the value of another setting), and it works out okay.  Most settings just ended up having a smart default, and as a result very little tweaking of the configuration is necessary.</p>
<p>Somewhat ironically the result was a kind of atrophying of the settings, because no one actually <em>set</em> them, instead we just tweaked the defaults to get it right.  Now I&#8217;m not entirely sure what exactly the &quot;settings&quot; are setting, or who they should really belong to.  To the build?  To the tasks?  While this is conceptually confusing, in practice it isn&#8217;t so bad.  This mixing of code and configuration has been distinctly useful, and not <em>nearly</em> as problematic to debug as I worried it would be.   In some ways it was a way of building <tt class="docutils literal"><span class="pre">lambda</span></tt> into every string, and the lazy evaluation of those strings has been really important.  But it&#8217;s not clear if they are really settings.</p>
<p>Would normal string interpolation have been enough (e.g., with <a class="reference external" href="http://python.org/doc/current/lib/node40.html">string.Template</a>)?  I&#8217;m pretty sure it wouldn&#8217;t have been.  The ability to do a little math or use functions that read things from the environment has been very important.</p>
</div>
<div class="section" id="managing-python-libraries">
<h2>Managing Python libraries</h2>
<p>fassembler uses <a class="reference external" href="http://pypi.python.org/pypi/virtualenv">virtualenv</a> for building each piece of the stack.  Generally it creates several environments and installs things into them &#8212; it doesn&#8217;t run inside the environments itself.  This works fine.</p>
<p>zc.buildout in comparison does some fancy stuff to scripts where specific eggs are enabled when you run a script.  Each script has a list of <em>all</em> the eggs to enable.  You can&#8217;t install things or manage anything manually, even to test &#8212; you always have to go through buildout, and it will regenerate the scripts for you.  zc.buildout was implemented at the same time as workingenv (the predecessor to virtualenv), and I actually finished virtualenv with fassembler in mind, so I can&#8217;t blame zc.buildout for not using virtualenv.  That said, I don&#8217;t think the zc.buildout system makes any sense.  And it&#8217;s really complicated and has to access all sorts of not-really-public parts of easy_install to work.</p>
<p>Isolation is only the start.  easy_install makes sure each library&#8217;s claimed dependencies are satisfied.  You might then think easy_install would do all the work to make the stack work.  It is nowhere close to making the stack work.  <tt class="docutils literal"><span class="pre">setup.py</span></tt> files can/should contain the bare minimum that is known to be necessary to make a package work.  But they can&#8217;t predict future incompatibilities, and they can&#8217;t predict interactions.  And you don&#8217;t want all your packages changing versions arbitrarily.  If you work with a lot of libraries you <em>need</em> those libraries to be pinned, and only update them when you <em>want</em> to update them, not just because an update has been released.</p>
<p>So for each piece of the stack we have a set of &quot;requirements&quot;.  This is a flat files that indicates all the packages to install.  They can have explicit versions, far more restrictive than anything you should put in <tt class="docutils literal"><span class="pre">setup.py</span></tt>.  It also can check out from svn, including pinning to revisions.  This installation plan can go in svn, you can do diffs on it, you can branch and copy and do whatever.  Maybe at some point we could use it to keep cached copies of the libraries.  For now it mostly uses <tt class="docutils literal"><span class="pre">easy_install</span></tt> (and <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">develop</span></tt> for checkouts).</p>
<p>In parallel we have a command-line program for just installing packages using files like this, called <a class="reference external" href="https://svn.openplans.org/svn/PoachEggs/trunk">PoachEggs</a>.  I want to make this better, and have fassembler use it, but I mostly note it because it implements a feature that can &quot;freeze&quot; all your packages to a requirements file.  You take a working build and freeze its requirements, giving explicit (<tt class="docutils literal"><span class="pre">==</span></tt>) versions for packages, and pin all the svn checkouts to a revision, so that the frozen requirements file will install exactly the packages you know work.</p>
<p>An alternative to this is what the <a class="reference external" href="http://repoze.org/">Repoze</a> guys are doing, which is to create a custom index that only includes the versions of libraries that you want.  You then tell easy_install to use this instead of <a class="reference external" href="http://pypi.python.org/pypi">PyPI</a>.  It works with zc.buildout (and anything that uses easy_install), but I can&#8217;t get excited about it compared to a simple text file.  I also want svn checkouts instead of create tarballs of the checkout &#8212; I like an editable environment, because the build is just as much to support developers as to support deployment.</p>
</div>
<div class="section" id="the-structure">
<h2>The structure</h2>
<p>A big part of the development of fassembler was nailing down the structure of our site, and moving to use tools like <a class="reference external" href="http://supervisord.org/">supervisor</a> to manage our processes.  A lot of these expectations are built into the builds and fassembler itself.  This is part of what makes the build Work &#8212; the pieces all conform to a common structure with some basic standards.  But this isn&#8217;t the build tool itself, it&#8217;s just a set of conventions.</p>
<p>I don&#8217;t know quite what to make of this.  Extracting the conventions from the builds leads to a situation where you can more easily misconfigure things, and the installation process ends up being more documentation-based instead of code-based.  We do <em>not</em> want to rely on documentation, because documentation is generally because of a flaw in the build process that needs explaining.  It&#8217;s faster for everyone if the code is just right.  Maybe these conventions could be put into code, separate from the build.  The abstraction worries me, though &#8212; too much to keep track of?</p>
</div>
<div class="section" id="what-we-don-t-get-right">
<h2>What we don&#8217;t get right</h2>
<p>The biggest problem is that fassembler is our own system and no one else uses it.  If someone wants to use just a piece of our stack they either have to build it manually or they have to use our system which is meant to build all our pieces together with our conventions.  There&#8217;s some pressure to use zc.buildout to make pieces more accessible to other Zope users.  We&#8217;ve also found things that build with zc.buildout that we&#8217;d like to use (e.g., setups for <a class="reference external" href="http://varnish.projects.linpro.no/">varnish</a>).</p>
<p>We haven&#8217;t figured out how to separate the code for building <em>our</em> stuff from the build software itself.  There&#8217;s a bootstrapping problem: you need to get the build code to build a project, and so it can&#8217;t be part of the project you are building.  zc.buildout uses configuration files (that aren&#8217;t code, so they lack the bootstrap problem) and it uses <a class="reference external" href="http://pypi.python.org/pypi/zc.buildout#id1">recipes</a> (a kind of plugin) and has gone to quite a bit of effort to bootstrap everything.  virtualenv also supports a kind of <a class="reference external" href="http://pypi.python.org/pypi/virtualenv#bootstrap-example">bootstrap</a> which we use to do the initial setup of the environment, but it doesn&#8217;t support code organization in the style of zc.buildout.</p>
<p>Builds are also fairly tedious to write.  They aren&#8217;t horrible, but they feel much longer than they should be.  Part of their length, though, is that over time we put in more code to guard against environment differences or build errors, and more code to detect the environment.  But compared to zc.buildout&#8217;s configuration files, it doesn&#8217;t feel quite as nice, and if it&#8217;s not as nice sometimes people are lazy and do ad hoc setups.</p>
</div>
<div class="section" id="the-future">
<h2>The future</h2>
<p>We haven&#8217;t really decided, but as you might have noticed zc.buildout gets a lot of attention here.  There&#8217;s quite a few things I don&#8217;t like about it, but a lot of these have to do with the recipes available.  We don&#8217;t <em>have</em> to use the standard zc.buildout egg installation recipe.  In fact that would be first on the chopping block, replaced with something much simpler that assumes you are running inside a virtualenv environment, and probably something that uses requirement files.</p>
<p>Also, we could extract filemaker into a library and recipes could use that.  Possibly logging could be handled the same way (the <a class="reference external" href="http://python.org/doc/current/lib/module-logging.html">logging</a> module just isn&#8217;t designed for an interactive experience like a build tool).  Then if we used other people&#8217;s recipes we might feel grumpy, since they&#8217;d use neither filemaker or our logging, but it would still work.  And our recipes would be full of awesome.  The one thing I don&#8217;t think we could do is introduce the template-based configuration.  Or, if we did, it would be hard.</p>
<p>That said, there is a very different direction we could go, one inspired more by <a class="reference external" href="http://code.google.com/appengine/">App Engine</a>.  In that model we build files under a directory, and that directory is the build.  Wherever you build, you get the same files, period.  All paths would be relative.  All environmental detection would happen in code at runtime.  Things that aren&#8217;t &quot;files&quot; exactly would simply be standard scripts.  E.g., database setup would not be done by the build, but would be a script put in a standard location.</p>
<p>This second file-based model of building is very much different than the principles behind zc.buildout.  zc.buildout requires rebuilding when anything changes, and does so without apology.  It requires rebuilding to move the directories, or to move to different machines.  Using a file-based model requires a lot of push-back into the products themselves.  Applications have to be patched to accept smart relative paths.  They have to manage themselves a lot more, detect their environment, handle any conflicts or ambiguities, being graceful about stuff like databases, because the files have to be universal.  In an extreme case I could imagine going so far as to only keep a template for a configuration file, and write the real configuration file to a temporary location before starting a server (if the server cannot be patched to accept runtime location information).</p>
<p>So this is the choice ahead.  I&#8217;m not sure <em>when</em> we&#8217;ll make this choice (if ever!) &#8212; build systems are dull and somewhat annoying, but they are no more dull and annoying than dealing with a poor build system.  Actually, they are <em>definitely</em> less dull than working with a build system that isn&#8217;t good enough or powerful enough, or one that simply lacks the TLC necessary to keep builds working.  So no choice is a choice too, and maybe a bad choice.</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/06/19/my-experience-writing-a-build-system/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Governance</title>
		<link>http://blog.ianbicking.org/2008/05/05/governance/</link>
		<comments>http://blog.ianbicking.org/2008/05/05/governance/#comments</comments>
		<pubDate>Tue, 06 May 2008 04:08:30 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Politics]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/05/05/governance/</guid>
		<description><![CDATA[
It occurred to me&#8230; Django is something like a dictatorship&#8230; or maybe an oligarchy.  At first it seems like Pylons is the same&#8230; but no.  Pylons is clearly feudal.  I lord over Paste, WebOb, FormEncode.  Mike Bayer lords over Mako and SQLAlchemy.  Ben lords over Routes, Beaker, and Pylons.
I suppose [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>It occurred to me&#8230; Django is something like a dictatorship&#8230; or maybe an <a class="reference external" href="http://en.wikipedia.org/wiki/Oligarchy">oligarchy</a>.  At first it seems like Pylons is the same&#8230; but no.  Pylons is clearly <a class="reference external" href="http://en.wikipedia.org/wiki/Feudalism">feudal</a>.  I lord over Paste, WebOb, FormEncode.  Mike Bayer lords over Mako and SQLAlchemy.  Ben lords over Routes, Beaker, and Pylons.</p>
<p>I suppose in all cases there is a certain amount of democracy, because there are no <a class="reference external" href="http://en.wikipedia.org/wiki/Serf">serfs</a>, and any individual is free to travel to any kingdom they like.  Well, at least among the open source kingdoms.  Without citizenship, and with no exclusiveness of ownership, with even property having largely disappeared, I suppose it&#8217;s inevitable that traditional metaphors of control and governance don&#8217;t really make sense.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/05/05/governance/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>App Engine and Pylons</title>
		<link>http://blog.ianbicking.org/2008/04/13/app-engine-and-pylons/</link>
		<comments>http://blog.ianbicking.org/2008/04/13/app-engine-and-pylons/#comments</comments>
		<pubDate>Sun, 13 Apr 2008 17:32:06 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/04/13/app-engine-and-pylons/</guid>
		<description><![CDATA[
So I promised some more technical discussion of App Engine than my last two posts.  Here it is:
Google App Engine uses a somewhat CGI-like model.  That is, a script is run, and it uses stdin/stdout/environ to handle the requests.  To avoid the overhead of CGI a process can be reused by defining [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>So I promised some more technical discussion of App Engine than my <a class="reference external" href="http://blog.ianbicking.org/2008/04/09/app-engine-commodity-vs-proprietary/">last</a> <a class="reference external" href="http://blog.ianbicking.org/2008/04/09/app-engine-and-open-source/">two</a> posts.  Here it is:</p>
<p>Google App Engine uses a somewhat CGI-like model.  That is, a script is run, and it uses stdin/stdout/environ to handle the requests.  To avoid the overhead of CGI a process can be reused by defining <tt class="docutils literal"><span class="pre">__main__.main()</span></tt>.  But while a process <em>can</em> be reused, it might not be, and of course it might get run on an entirely separate server.  So in many ways it&#8217;s like the CGI model, with a small optimization so that, particularly under load, your requests can run with less latency.</p>
<p>This part is all well and good.  I&#8217;ve already come to terms with servers going up and down without warning.  But the environment itself has a number of other restrictions.  It seems that App Engine is providing security in the language itself.  The interpreter has been modified so that code is sandboxed, with no ability to write to the disk, open sockets, import C extensions, and see quite a few things in its environment.  It&#8217;s these things that are a bit harder to come to terms with.</p>
<p>While they claim it supports any Python framework, these restrictions don&#8217;t actually make it easy.  So for the last few days quite a few of us have been hacking various things to get stuff working.</p>
<p>The first thing people noticed is that <a class="reference external" href="http://www.makotemplates.org/">Mako</a> and <a class="reference external" href="http://genshi.edgewall.org/">Genshi</a> didn&#8217;t work, because they use the <a class="reference external" href="http://docs.python.org/lib/module-compiler.ast.html">ast</a> (via the <a class="reference external" href="http://python.org/doc/current/lib/module-parser.html">parser module</a>) to handle the templating, and that module has been restricted.  Apparently arbitrary bytecode is not safe in this environment, and so anything that can produce bytecode is considered dangerous.  From what I understand Philip Jenvy has been working on Mako and the trunk is currently working.  He&#8217;d already been doing work to get Mako working on Jython, which had similar issues.  Genshi is <a class="reference external" href="http://genshi.edgewall.org/wiki/AppEngine">also in progress</a> and fairly close to working, though with some missing features.  Genshi has the harder task as Mako was primarily reading the ast, while Genshi was writing it.</p>
<p>The first thing <em>I</em> noticed is that Setuptools doesn&#8217;t work.  I&#8217;m flattered that one of the only 3 libraries included with App Engine is <a class="reference external" href="http://pythonpaste.org/webob/">WebOb</a>, but of course I am more enamored of a rich set of reusable libraries.  Setuptools didn&#8217;t work because several modules and functions have been removed &#8212; this like <tt class="docutils literal"><span class="pre">os.open</span></tt>, <tt class="docutils literal"><span class="pre">os.uname</span></tt>, <tt class="docutils literal"><span class="pre">imp.acquire_lock</span></tt>, etc.  Some of these are kind of reasonable, while others are not.  The removal of many functions from <a class="reference external" href="http://python.org/doc/current/lib/module-imp.html">imp</a> doesn&#8217;t really make sense, for instance (I think the motivation was the difficulty of auditing the <em>implementation</em> of those functions, not that the functionality itself is dangerous).  And while some functions can&#8217;t be used in the environment, the fact you can&#8217;t <em>import</em> those functions is more problematic.  For instance, The Setuptools&#8217; <tt class="docutils literal"><span class="pre">pkg_resources</span></tt> module has support to unzip eggs when they are imported.  App Engine doesn&#8217;t support importing from zip files at all, and you certainly can&#8217;t unzip to a temporary location.  But withoutthe necessary modules and objects pkg_resources won&#8217;t even import.</p>
<p>To work around this I started a new project: <a class="reference external" href="http://code.google.com/p/appengine-monkey/">appengine-monkey</a>, which adds several monkeypatches and replacement dummy modules to the environment to simulate a more typical environment.  It&#8217;s just a small list so far (mostly in <a class="reference external" href="http://appengine-monkey.googlecode.com/svn/trunk/appengine_monkey.py">this module</a>), but I expect as people experiment with other libraries the list will increase.  For example, I would welcome implementations of things like <a class="reference external" href="http://python.org/doc/current/lib/module-httplib.html">httplib</a> on top of <a class="reference external" href="http://code.google.com/appengine/docs/urlfetch/">urlfetch</a> in this library.  (Implementing httplib and stubbing out parts of socket would probably make <a class="reference external" href="http://code.google.com/p/googleappengine/issues/detail?id=61">urllib run</a>.)</p>
<p>But the good news is that Pylons is pretty much working on App Engine, as is Setuptools and you can manage your libraries using <a class="reference external" href="http://pypi.python.org/pypi/virtualenv">virtualenv</a>.</p>
<p>The instructions are all located in the <a class="reference external" href="http://code.google.com/p/appengine-monkey/wiki/Pylons">appengine-monkey Pylons wiki page</a>.  Please leave comments if you have improvements or problems with that process.  I also welcome contributors and developers to the project itself &#8212; this is a project for expediting App Engine development, it is not a project I care to champion or control.  Or support to any large degree.</p>
<p>One ticket which is rather important is the apparent <a class="reference external" href="http://code.google.com/p/googleappengine/issues/detail?id=161">maximum number of files and blobs: 1000</a>.  Libraries involve lots of files, and the base Pylons install is only barely under this limit.  Now I just wish I could <a class="reference external" href="http://code.google.com/p/googleappengine/issues/detail?id=18">use lxml</a>, but that&#8217;s probably going to be a long time coming.</p>
<p><strong>Update</strong>: As of April 2009 these issues were fixed; it took a year, but at least it&#8217;s done.  The 1000 file limit has been relaxed (1000 code plus 1000 static) but still exists.  lxml remains unlikely.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/04/13/app-engine-and-pylons/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>App Engine and Open Source</title>
		<link>http://blog.ianbicking.org/2008/04/09/app-engine-and-open-source/</link>
		<comments>http://blog.ianbicking.org/2008/04/09/app-engine-and-open-source/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 19:13:36 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/2008/04/09/app-engine-and-open-source/</guid>
		<description><![CDATA[
This is about Google App Engine which probably everyone has read about already.
I&#8217;m quite excited about it.  Hosting has been the bane of the Python web world for a long time.  This provides a very compelling hosting situation for Python applications.
I&#8217;m not as interested in this from a competitive perspective as I am [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>This is about <a class="reference external" href="http://code.google.com/appengine/">Google App Engine</a> which probably everyone has read about already.</p>
<p>I&#8217;m quite excited about it.  Hosting has been the bane of the Python web world for a long time.  This provides a very compelling hosting situation for Python applications.</p>
<p>I&#8217;m not as interested in this from a competitive perspective as I am from a simple this-is-awesome perspective.  Regardless of how this positions Python relative to other languages, this is something Python needs.  But even looking beyond that, I think this is something the open source world needs.  Open source web development is in a funny place.  There&#8217;s a lot of reasons why web programming is a good domain for open source.  The barrier to entry for web development is extremely low.  Developers have choice in their tools, as browsers don&#8217;t really care what software you use so long as you serve up HTML.  This leads to experimentation and excitement and the kind of self-direction that is very motivating to developers.  It leads to the kind of personal excitement that underlies most open source development.</p>
<p>Despite this, open source web application development doesn&#8217;t seem sustainable.  There&#8217;s <em>some</em> applications, sure.  WordPress, Trac, MediaWiki, MoinMoin.  But most wiki software doesn&#8217;t have a vibrant community.  Many a bug tracker has fallen by the wayside.  Blog software projects have a horrible time building a viable community.  Other website software hardly gets anywhere at all.  A lot of the development that might <em>appear</em> to be application development really is more like a framework when you look closely (e.g., Plone, Drupal).</p>
<p>I think deployment concerns are a huge part of this.  And, <a class="reference external" href="http://blog.ianbicking.org/2008/01/12/what-php-deployment-gets-right/">given its better deployment story</a>, it&#8217;s no surprise PHP is the basis of most viable open source web applications.  Being interested in a project requires that you be able to <em>use</em> the product (and usually use it casually, as that&#8217;s the point of entry for many developers).  Right now most people can&#8217;t use open source web applications.</p>
<p>But people <em>can use</em> hosted applications, and that&#8217;s where all the effort has gone in the past few years.  I am comfortable saying that Trac is a better issue tracker than Google Code&#8217;s issue tracker.  But I&#8217;d probably recommend Google Code to someone starting a new project, because it&#8217;s so much less work.  Similarly I&#8217;d try to dissuade most people from installing their own blog software.  I still don&#8217;t know what to tell people about a CMS.</p>
<p>Many people are excited about how far up you might be able to scale something based on App Engine, but (like <a class="reference external" href="http://www.scripting.com/stories/2008/04/08/earlyNotesOnGoogleapps.html">Dave</a>) I&#8217;m excited about how far it could be scaled down.  For the majority of sites the free quota will be more than enough.  But that alone isn&#8217;t the point: there&#8217;s lots of free services people can use.  The difference here is that the free services can be modified and controlled by the anyone who signs up and installs an application.</p>
<p>From the perspective of open source it&#8217;s a bit awkward that the platform itself is proprietary.  <a class="reference external" href="http://www.tbray.org/ongoing/When/200x/2008/04/09/Google-Users-API">Questions about sharecropping are a valid concern</a>, but I&#8217;m optimistic about the ultimate outcome.  The SDK is under a permissive open source license, and the APIs are all reasonable enough that they could be reimplemented with open source backends (maybe without the same scalability, but that&#8217;s not the aspect I care about anyway).  Perhaps the BigTable APIs will serve as the <a class="reference external" href="http://radian.org/notebook/google-datastore">basis for future storage APIs</a>.</p>
<p>But even if other people make compatible implementations of these APIs, would it matter?  If Google offers free hosting, is someone else really going to be able to provide a better hosting option?  Or would these other implementations just be strawmen, a way to show that It Could Be Done?  If the libraries are just written to prove a point, I can&#8217;t see them gaining much traction.  But I think these could be viable as there are other constraints to the App Engine environment that people may want to escape at some point in their application development.</p>
<p>As to the details of App Engine?  Can you run Pylons or Paste on it?  Well, that&#8217;s a topic for another post.</p>
<p><strong>Update:</strong> I <a class="reference external" href="http://blog.ianbicking.org/2008/04/09/app-engine-commodity-vs-proprietary/">wrote up some more thoughts</a></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2008/04/09/app-engine-and-open-source/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.623 seconds -->
