<?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; Python</title>
	<atom:link href="http://blog.ianbicking.org/category/python/feed/" 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>Silver Lining: More People!</title>
		<link>http://blog.ianbicking.org/2010/04/21/silver-lining-more-people/</link>
		<comments>http://blog.ianbicking.org/2010/04/21/silver-lining-more-people/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 03:20:00 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Silver Lining]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=224</guid>
		<description><![CDATA[
OK&#8230; so I said before Silver Lining is for collaborators not users. And that&#8217;s still true&#8230; it&#8217;s not a polished experience where you can confidently ignore the innards of the tool.  But it does stuff, and it works, and you can use it.  So&#8230; I encourage some more of you to do so.
Now [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>OK&#8230; so I said before Silver Lining is for collaborators not users. And that&#8217;s still true&#8230; it&#8217;s not a polished experience where you can confidently ignore the innards of the tool.  But it does stuff, and it works, and you can use it.  So&#8230; I encourage some more of you to do so.</p>
<p>Now would be a perfectly good time, for instance, to port an application you use to the system.  Almost all Python applications should be portable.  The requirements are fairly simple:</p>
<ol class="arabic simple">
<li>The application needs a WSGI interface.</li>
<li>It needs to be Python 2.6 compatible.</li>
<li>Any libraries that aren&#8217;t pure-Python need to be available as deb packages in some form.</li>
<li>Any persistence needs to be provided as a <a class="reference external" href="http://cloudsilverlining.org/services.html">service</a>; if the appropriate service isn&#8217;t already available you may need to write some code.</li>
</ol>
<p>Also PHP applications should work (though you may encounter more rough edges), with these constraints:</p>
<ol class="arabic simple">
<li>No <tt class="docutils literal"><span class="pre">.htaccess</span></tt> files, so you have to implement any URL rewriting in PHP (e.g., <a class="reference external" href="http://bitbucket.org/ianb/silverlining/src/tip/docs/examples/wordpress/runner.php">for WordPress</a>).</li>
<li>Source code is not writable, so self-installers that write files won&#8217;t work.  (Self-installing plugins might be workable, but that hasn&#8217;t been worked out yet.)</li>
<li>And the same constraints for services.</li>
</ol>
<p>So&#8230; take an application, give it a try, and tell me what you encounter.</p>
<p>Also I&#8217;d love to get feedback and ideas from people with more sysadmin background, or who know Ubuntu/Debian tricks.  For instance, I&#8217;d like to handle some of the questions packages ask about on installation (right now they are all left as defaults, not always the right answer).  I imagine there&#8217;s some non-interactive way to handle those questions but I haven&#8217;t been able to find it.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/04/21/silver-lining-more-people/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<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>More Sentinels</title>
		<link>http://blog.ianbicking.org/2010/04/02/more-sentinels/</link>
		<comments>http://blog.ianbicking.org/2010/04/02/more-sentinels/#comments</comments>
		<pubDate>Fri, 02 Apr 2010 18:26:24 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=208</guid>
		<description><![CDATA[
I&#8217;ve been casually perusing Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp.  One of the things I am noticing is that Lisp traditionally has a terrible lack of sentinels: special objects denoting some kind of meaning.  Specifically in Common Lisp the empty list and false and nil are all the same [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I&#8217;ve been casually perusing <a class="reference external" href="http://norvig.com/paip.html">Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp</a>.  One of the things I am noticing is that Lisp traditionally has a terrible lack of sentinels: special objects denoting some kind of meaning.  Specifically in Common Lisp the empty list and false and nil are all the same thing.  As a result there&#8217;s all these cases where you want to distinguish false from empty, especially when false represents a failure of some sort.  In these AI examples, usually a failure to find something, while in many cases the empty list could mean &quot;the thing is already found, no need to look&quot;.  But there&#8217;s also lots of other examples when this causes problems.</p>
<p>More modern languages usually distinguish between these objects. Python for instance has <tt class="docutils literal"><span class="pre">[]</span></tt>, <tt class="docutils literal"><span class="pre">False</span></tt> and <tt class="docutils literal"><span class="pre">None</span></tt>.  They might all test as &quot;falsish&quot;, but if you care to tell the difference it is easy to do; especially common is a test for <tt class="docutils literal"><span class="pre">x</span> <span class="pre">is</span> <span class="pre">None</span></tt>.  Modern Lisps also stopped folding together all these notions (Scheme for example has <tt class="docutils literal"><span class="pre">#f</span></tt> for false as a completely distinct object, though null and the empty list are still the same).  XML-RPC is an example of a language missing null&#8230; and though JSON is almost the same data model, it is a great deal superior for having null.  In comparison no one seems to care much one way or the other about making a strong distinction between True/False and 1/0.</p>
<p>These are all examples of sentinels: special objects that represent some state.  None doesn&#8217;t <em>mean</em> anything in particular, but it means lots of things specifically.  Maybe it means &quot;not found&quot; in one place, or &quot;give me anything I don&#8217;t care&quot; in another.  But sometimes you need more than one of these in the same place, or None isn&#8217;t entirely clear.</p>
<p>One thing I noticed while reading some Perl 6 examples is that they&#8217;ve added a number of new sentinels.  One is <tt class="docutils literal"><span class="pre">*</span></tt>.  So you could write something like <tt class="docutils literal"><span class="pre">item(*)</span></tt> to mean &quot;give me any item, your choice&quot;. While the Perl tendency to use punctuation is legend, words work too.</p>
<p>I wonder if we need a few more sentinel conventions?  If so what?</p>
<p>Of course any object can become a sentinel if you use it like that, None isn&#8217;t <em>more</em> unique than any other object.  (None <em>is</em> conveniently available everywhere.)</p>
<p><tt class="docutils literal"><span class="pre">Any</span></tt> seems useful, ala Perl&#8217;s <tt class="docutils literal"><span class="pre">*</span></tt>.  But&#8230; there&#8217;s already an <a class="reference external" href="http://docs.python.org/library/functions.html#any">any</a> available everywhere as well.  It happens to be a function, but it&#8217;s also a unique named object&#8230; would it be entirely too weird to do <tt class="docutils literal"><span class="pre">obj</span> <span class="pre">is</span> <span class="pre">any</span></tt>?  And there&#8217;s very few cases where the actual function <tt class="docutils literal"><span class="pre">any</span></tt> would be an appropriate input, making it a good sentinel.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/04/02/more-sentinels/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>The Web Server Benchmarking We Need</title>
		<link>http://blog.ianbicking.org/2010/03/16/web-server-benchmarking-we-need/</link>
		<comments>http://blog.ianbicking.org/2010/03/16/web-server-benchmarking-we-need/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 23:23:27 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Silver Lining]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=198</guid>
		<description><![CDATA[
Another WSGI web server benchmark was published.  It&#8217;s a decent benchmark, despite some criticisms.  But it benchmarks what everyone benchmarks: serving up a trivial app really really quickly.  This is not very useful to me.  Also, performance is not to me the most important differentiation of servers.
In Silver Lining we&#8217;re using [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>Another <a class="reference external" href="http://nichol.as/benchmark-of-python-web-servers">WSGI web server benchmark</a> was published.  It&#8217;s a decent benchmark, despite some criticisms.  But it benchmarks what everyone benchmarks: serving up a trivial app really really quickly.  This is not very useful to me.  Also, performance is not to me the most important differentiation of servers.</p>
<p>In <a class="reference external" href="http://cloudsilverlining.org">Silver Lining</a> we&#8217;re using <a class="reference external" href="http://code.google.com/p/modwsgi/">mod_wsgi</a>.  Silver Lining isn&#8217;t tied to mod_wsgi (applications can&#8217;t really tell), and we may revisit that decision (mostly because of memory concerns), but it is a deliberate choice.  mod_wsgi is one of the few multiprocess WSGI servers, and it manages its children (the same way Apache manages all its children).  So if a child stops responding, it gets taken out of the pool and killed (brutal efficiency!  Or at least brutal terminology).  Child processes are also recycled, guarding against memory leaks or other peculiarities.  Sometimes these kinds of things are dismissed for covering up bugs, but (a) production is a lousy time to learn about bugs, (b) it&#8217;s like a third tier of garbage collection, and (c) the bugs you are avoiding are often bugs you can&#8217;t fix anyway (for instance, if your mysql driver leaks memory, is that the application developer&#8217;s fault?)</p>
<p>I wish there was competition among servers not to see who can tweak their performance for entirely unrealistic situations, but to see who can implement the most fail-safe server.  We&#8217;re missing good benchmarks.  Unfortunately benchmarks are a pain in the butt to write and manage.</p>
<p>But I hope someone writes a benchmark like that.  Here&#8217;s some things I&#8217;d like to see benchmarked:</p>
<ul class="simple">
<li>A &quot;realistic&quot; CPU-bound application.  <tt class="docutils literal"><span class="pre">for</span> <span class="pre">i</span> <span class="pre">in</span> <span class="pre">xrange(10000000):</span> <span class="pre">pass</span></tt> is a reasonable start.</li>
<li>An application that generates big responses, e.g., <tt class="docutils literal"><span class="pre">&quot;x&quot;*100000</span></tt>.</li>
<li>An I/O bound application.  E.g., one that reads a big file.</li>
<li>A simply slow application (<tt class="docutils literal"><span class="pre">time.sleep(1)</span></tt>).</li>
<li>Applications that wedge.  <tt class="docutils literal"><span class="pre">while</span> <span class="pre">1:</span> <span class="pre">pass</span></tt> perhaps?  Or <tt class="docutils literal"><span class="pre">lock</span> <span class="pre">=</span> <span class="pre">threading.Lock();</span> <span class="pre">lock.acquire();</span> <span class="pre">lock.acquire()</span></tt>.  Wedging in C and wedging in Python are different, so a bunch of different kinds of wedging.</li>
<li>Applications that segfault.  ctypes is specially designed for this.</li>
<li>Applications that leak memory like a sieve, e.g., <tt class="docutils literal"><span class="pre">global_var.extend(['x']*10000)</span></tt>.</li>
<li>Large uploads.</li>
<li>Slow uploads, like a client that takes 30 seconds to upload 1Mb.</li>
<li>Also slow downloads.</li>
<li>In each case it is interesting what happens when something bad happens to just a portion of requests.  E.g., if 1% of requests wedge hard.  A good container will serve the other 99% of requests properly.  A bad container will have its worker pool exhausted and completely stop.</li>
<li>Mixing and matching these could be interesting.  For instance Dave Beazley <a class="reference external" href="http://www.dabeaz.com/blog/2010/02/revisiting-thread-priorities-and-new.html">found some bad GIL results mixing I/O and CPU-bound code</a>.</li>
<li>Add ideas in the comments and I&#8217;ll copy them into this list.</li>
</ul>
<p>The hardest part of writing this is not the applications (they are simple).  One annoyance is wiring up the applications, but handily Nicholas covers that well in <a class="reference external" href="http://nichol.as/benchmark-of-python-web-servers">his benchmark</a>.  You also have to make sure to clean up, as many servers will not exit cleanly from some of the tests.  Another nuisance is that some of these require funny clients.  These aren&#8217;t too hard to write, but you can&#8217;t just use <tt class="docutils literal"><span class="pre">ab</span></tt>.  Then you have to report.</p>
<p>Anyway: I would <strong>love it</strong> if someone did this, and packaged it as repeatable/runnable code/scripts.  I&#8217;ll help some, but I can&#8217;t lead.  I&#8217;d both really like to see the results, and in my ideal world people writing servers would start using these benchmarks to make their servers more robust.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/03/16/web-server-benchmarking-we-need/feed/</wfw:commentRss>
		<slash:comments>21</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>Joining Mozilla</title>
		<link>http://blog.ianbicking.org/2010/03/10/joining-mozilla/</link>
		<comments>http://blog.ianbicking.org/2010/03/10/joining-mozilla/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 23:46:40 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Mozilla]]></category>
		<category><![CDATA[Non-technical]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=185</guid>
		<description><![CDATA[
As of last week, I am now an employee of Mozilla!  Thanks to everyone who helped me out during my job search.
I&#8217;ll be working both with the Mozilla Web Development (webdev) team, and Mozilla Labs.
The first thing I&#8217;ll be working on is deployment.  In part because I&#8217;ve been thinking about deployment lately, in [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>As of last week, I am now an employee of Mozilla!  Thanks to everyone who helped me out during my job search.</p>
<p>I&#8217;ll be working both with the Mozilla <a class="reference external" href="http://blog.mozilla.com/webdev/">Web Development (webdev)</a> team, and <a class="reference external" href="https://mozillalabs.com/">Mozilla Labs</a>.</p>
<p>The first thing I&#8217;ll be working on is deployment.  In part because I&#8217;ve been <a class="reference external" href="http://blog.ianbicking.org/category/silverlining/">thinking about deployment lately</a>, in part because streamlining deployment is just generally enabling of other work (and a personal itch to be scratched), and because I think there is the possibility to fit this work into Mozilla&#8217;s <a class="reference external" href="http://www.mozilla.org/causes/">general mission</a>, specifically <em>Empowering people to do new and unanticipated things on the web</em>.  I think the way I&#8217;m approaching deployment has real potential to combine the discipline and benefits of good development practices with an accessible process that is more <em>democratic</em> and less <em>professionalized</em>.  This is some of what <a class="reference external" href="http://blog.ianbicking.org/2008/01/12/what-php-deployment-gets-right/">PHP has provided</a> over the years (and I think it&#8217;s been a genuinely positive influence on the web as a result); I&#8217;d like to see the same kind of easy entry using other platforms.  I&#8217;m hoping <a class="reference external" href="http://cloudsilverlining.org">Silver Lining</a> will fit both Mozilla&#8217;s application deployment needs, as well as serving a general purpose.</p>
<p>Once I <em>finish</em> deployment and can move on (oh fuck what am I getting myself into) I&#8217;ll also be working with the <a class="reference external" href="http://blog.mozilla.com/webdev">web development group</a> who has adopted Python for many of their new projects (e.g., <a class="reference external" href="http://github.com/jbalogh/zamboni">Zamboni</a>, a rewrite of the <a class="reference external" href="https://addons.mozilla.org/">addons.mozilla.org</a> site), and with Mozilla Labs on <a class="reference external" href="http://mozillalabs.com/weave/">Weave</a> or some of their other projects.</p>
<p>In addition my own <a class="reference external" href="http://ianbicking.appspot.com/projects">Python open source work</a> is in line with Mozilla&#8217;s mission and I will be able to continue spending time on those projects, as well as entirely new projects.</p>
<p>I&#8217;m pretty excited about this &#8212; it feels like there&#8217;s a really good match with Mozilla and what I&#8217;m good at, and what I care about, and <em>how</em> I care about it.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/03/10/joining-mozilla/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>toppcloud renamed to Silver Lining</title>
		<link>http://blog.ianbicking.org/2010/03/03/toppcloud-renamed-to-silver-lining/</link>
		<comments>http://blog.ianbicking.org/2010/03/03/toppcloud-renamed-to-silver-lining/#comments</comments>
		<pubDate>Thu, 04 Mar 2010 02:18:30 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Packaging]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Silver Lining]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=168</guid>
		<description><![CDATA[
After some pondering at PyCon, I decided on a new name for toppcloud: Silver Lining.  I&#8217;ll credit a mysterious commenter &#34;david&#34; with the name idea.  The command line is simply silver &#8212; silver update has a nice ring to it.
There&#8217;s a new site: cloudsilverlining.org; not notably different than the old site, just a [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>After some pondering at PyCon, I decided on a new name for toppcloud: <strong>Silver Lining</strong>.  I&#8217;ll credit a mysterious commenter &quot;david&quot; with the name idea.  The command line is simply <tt class="docutils literal"><span class="pre">silver</span></tt> &#8212; <tt class="docutils literal"><span class="pre">silver</span> <span class="pre">update</span></tt> has a nice ring to it.</p>
<p>There&#8217;s a new site: <a class="reference external" href="http://cloudsilverlining.org">cloudsilverlining.org</a>; not notably different than the old site, just a new name.  The product is self-hosting now, using a <a class="reference external" href="http://bitbucket.org/ianb/silverlining/">simple app</a> that runs after every commit to regenerate the docs, and with a small extension to Silver Lining itself (to make it easier to host static files).  Now that it has a real name I also gave it a <a class="reference external" href="http://groups.google.com/group/silverlining-dev">real mailing list</a>.</p>
<p>Silver Lining also has its <a class="reference external" href="http://bitbucket.org/ianb/silverlining/src/tip/tests/functional/runtest.py">first test</a>.  Not an impressive test, but a test.  I&#8217;m hoping with a <a class="reference external" href="http://mail-archives.apache.org/mod_mbox/incubator-libcloud/201003.mbox/browser">VM-based libcloud backend</a> that a full integration test can run in a reasonable amount of time.  <em>Some</em> unit tests would be possible, but so far most of the bugs have been interaction bugs so I think integration tests will have to pull most of the weight.  (A continuous integration rig will be very useful; I am not sure if Silver Lining can self-host that, though it&#8217;d be nice/clever if it could.)</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/03/03/toppcloud-renamed-to-silver-lining/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Throw out your frameworks! (forms included)</title>
		<link>http://blog.ianbicking.org/2010/03/01/throw-out-your-frameworks-forms-included/</link>
		<comments>http://blog.ianbicking.org/2010/03/01/throw-out-your-frameworks-forms-included/#comments</comments>
		<pubDate>Mon, 01 Mar 2010 06:29:04 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[HTML]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=164</guid>
		<description><![CDATA[
No, I should say forms particularly.
I have lots of things to blog about, but nothing makes me want to blog like code.  Ideas are hard, code is easy.  So when I saw Jacob&#8217;s writeup about dynamic Django form generation I felt a desire to respond.  I didn&#8217;t see the form panel at [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>No, I should say <em>forms particularly</em>.</p>
<p>I have lots of things to blog about, but nothing makes me want to blog like <em>code</em>.  Ideas are hard, code is easy.  So when I saw <a class="reference external" href="http://jacobian.org/writing/dynamic-form-generation/">Jacob&#8217;s writeup about dynamic Django form generation</a> I felt a desire to respond.  I didn&#8217;t see the form panel at PyCon (I intended to but I hardly saw <em>any</em> talks at PyCon, and yet still didn&#8217;t even see a good number of the people I wanted to see), but as the author of an <a class="reference external" href="http://formencode.org/htmlfill.html">ungenerator</a> and as a general <a class="reference external" href="http://blog.ianbicking.org/on-form-libraries.html">form library skeptic</a> I have a somewhat different perspective on the topic.</p>
<p>The example created for the panel might display that perspective.  You should go read <a class="reference external" href="http://jacobian.org/writing/dynamic-form-generation/">Jacob&#8217;s description</a>; but basically it&#8217;s a simple registration form with a dynamic set of questions to ask.</p>
<p>I have created a <a class="reference external" href="http://svn.colorstudy.com/home/ianb/formencode_answer.py">complete example</a>, because I wanted to be sure I wasn&#8217;t skipping anything, but I&#8217;ll present a trimmed-down version.</p>
<p>First, the basic control logic:</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> formencode <span class="kw1">import</span> htmlfill<br />
<br />
@<span class="co1">wsgify</span><br />
<span class="kw1">def</span> questioner<span class="br0">&#40;</span>req<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; questions = get_questions<span class="br0">&#40;</span>req<span class="br0">&#41;</span> <span class="co1"># This is provided as part of the example</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> req.<span class="me1">method</span> == <span class="st0">'POST'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; errors = validate<span class="br0">&#40;</span>req, questions<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> errors:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ... <span class="me1">save</span> response ...<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> exc.<span class="me1">HTTPFound</span><span class="br0">&#40;</span>location=<span class="st0">'/thanks'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; errors = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; <span class="co1">## Here's the &quot;form generation&quot;:</span><br />
&nbsp; &nbsp; page = page_template.<span class="me1">substitute</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; action=req.<span class="me1">url</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; questions=questions<span class="br0">&#41;</span><br />
&nbsp; &nbsp; page = htmlfill.<span class="me1">render</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; page,<br />
&nbsp; &nbsp; &nbsp; &nbsp; defaults=req.<span class="me1">POST</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; errors=errors<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> Response<span class="br0">&#40;</span>page<span class="br0">&#41;</span><br />
<br />
<span class="kw1">def</span> validate<span class="br0">&#40;</span>req, questions<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="co1"># All manual, but do it however you want:</span><br />
&nbsp; &nbsp; errors = <span class="br0">&#123;</span><span class="br0">&#125;</span><br />
&nbsp; &nbsp; form = req.<span class="me1">POST</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>form.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'password'</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">and</span> form<span class="br0">&#91;</span><span class="st0">'password'</span><span class="br0">&#93;</span> != form.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">'password_confirm'</span><span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; errors<span class="br0">&#91;</span><span class="st0">'password_confirm'</span><span class="br0">&#93;</span> = <span class="st0">'Passwords do not match'</span><br />
&nbsp; &nbsp; fields = questions + <span class="br0">&#91;</span><span class="st0">'username'</span>, <span class="st0">'password'</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw1">for</span> field <span class="kw1">in</span> fields:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> form.<span class="me1">get</span><span class="br0">&#40;</span>field<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; errors<span class="br0">&#91;</span>field<span class="br0">&#93;</span> = <span class="st0">'Please enter a value'</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> errors<br />
&nbsp;</div>
<p>I&#8217;ve just manually handled validation here.  I don&#8217;t feel like doing it with FormEncode.  Manual validation isn&#8217;t that big a deal; FormEncode would just produce the same <tt class="docutils literal"><span class="pre">errors</span></tt> dictionary anyway.  In this case (as in many form validation cases) you can&#8217;t do better than hand-written validation code: it&#8217;s shorter, more self-contained, and easier to tweak.</p>
<p>After validation the template is rendered:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
page = page_template.<span class="me1">substitute</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; action=req.<span class="me1">url</span>,<br />
&nbsp; &nbsp; questions=questions<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>I&#8217;m using <a class="reference external" href="http://pythonpaste.org/tempita/">Tempita</a>, but it really doesn&#8217;t matter.  The template looks like this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
&lt;form action=<span class="st0">&quot;{{action}}&quot;</span> method=<span class="st0">&quot;POST&quot;</span>&gt;<br />
New Username: &lt;input <span class="kw2">type</span>=<span class="st0">&quot;text&quot;</span> name=<span class="st0">&quot;username&quot;</span>&gt;&lt;br /&gt;<br />
Password: &lt;input <span class="kw2">type</span>=<span class="st0">&quot;password&quot;</span> name=<span class="st0">&quot;password&quot;</span>&gt;&lt;br /&gt;<br />
Repeat Password:<br />
&nbsp; &lt;input <span class="kw2">type</span>=<span class="st0">&quot;password&quot;</span> name=<span class="st0">&quot;password_confirm&quot;</span>&gt;&lt;br /&gt;<br />
<span class="br0">&#123;</span><span class="br0">&#123;</span><span class="kw1">for</span> question <span class="kw1">in</span> questions<span class="br0">&#125;</span><span class="br0">&#125;</span><br />
&nbsp; <span class="br0">&#123;</span><span class="br0">&#123;</span>question<span class="br0">&#125;</span><span class="br0">&#125;</span>: &lt;input <span class="kw2">type</span>=<span class="st0">&quot;text&quot;</span> name=<span class="st0">&quot;{{question}}&quot;</span>&gt;&lt;br /&gt;<br />
<span class="br0">&#123;</span><span class="br0">&#123;</span>endfor<span class="br0">&#125;</span><span class="br0">&#125;</span><br />
&lt;input <span class="kw2">type</span>=<span class="st0">&quot;submit&quot;</span>&gt;<br />
&lt;/form&gt;<br />
&nbsp;</div>
<p>Note that the only &quot;logic&quot; here is to render the form to include fields for all the questions.  Obviously this produces an ugly form, but it&#8217;s <em>very obvious</em> how you make this form pretty, and how to tweak it in any way you might want.  Also if you have deeper dynamicism (e.g., <tt class="docutils literal"><span class="pre">get_questions</span></tt> start returning the type of response required, or weird validation, or whatever) it&#8217;s <em>very obvious</em> where that change would go: display logic goes in the form, validation logic goes in that validate function.</p>
<p>This just gives you the raw form.  You wouldn&#8217;t need a template at all if it wasn&#8217;t for the dynamicism.  Everything else is added when the form is &quot;filled&quot;:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
page = htmlfill.<span class="me1">render</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; page,<br />
&nbsp; &nbsp; defaults=req.<span class="me1">POST</span>,<br />
&nbsp; &nbsp; errors=errors<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>How exactly you want to calculate <tt class="docutils literal"><span class="pre">defaults</span></tt> is up to the application; you might want query string variables to be able to pre-fill the form (use <tt class="docutils literal"><span class="pre">req.params</span></tt>), you might want the form bare to start (like here with <tt class="docutils literal"><span class="pre">req.POST</span></tt>), you can easily implement wizards by stuffing <tt class="docutils literal"><span class="pre">req.POST</span></tt> into the session to repeat a form, you might read the defaults out of a user object to make this an edit form.  And errors are just handled automatically, inserted into the HTML with appropriate CSS classes.</p>
<p>A great aspect of this <em>pattern</em> if you use it (I&#8217;m not even sure it deserves the moniker <em>library</em>): when <a class="reference external" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#forms">HTML 5 Forms</a> finally come around and we can all stop doing this stupid server-side overthought nonsense, <strong>you</strong> won&#8217;t have overthought your forms.  Your mind will be free and ready to accept that the world has actually become simpler, not more complicated, and that there is knowledge worth forgetting (forms are so freakin&#8217; stupid!)  If at all possible, dodging complexity is far better than cleverly responding to complexity.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/03/01/throw-out-your-frameworks-forms-included/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
		<item>
		<title>Why toppcloud (Silver Lining) will not be agnostic</title>
		<link>http://blog.ianbicking.org/2010/02/10/why-toppcloud-not-agnostic/</link>
		<comments>http://blog.ianbicking.org/2010/02/10/why-toppcloud-not-agnostic/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 06:41:45 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Silver Lining]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=158</guid>
		<description><![CDATA[
I haven&#8217;t received a great deal of specific feedback on toppcloud (update: renamed Silver Lining), only a few people (Ben Bangert, Jorge Vargas) seem to have really dived deeply into it.  But &#8212; and this is not unexpected &#8212; I have already gotten several requests about making it more agnostic with respect to&#8230; stuff. [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I haven&#8217;t received a great deal of <em>specific</em> feedback on toppcloud (<strong>update</strong>: renamed Silver Lining), only a few people (Ben Bangert, Jorge Vargas) seem to have really dived deeply into it.  But &#8212; and this is not unexpected &#8212; I have already gotten several requests about making it more agnostic with respect to&#8230; stuff.  Maybe that it not (at least forever) require Ubuntu.  Or maybe that it should support different process models (e.g., threaded and multiple processes).  Or other versions of Python.</p>
<p>The more I think about it, and the more I work with the tool, the more confident I am that toppcloud should not be agnostic on these issues.  This is not so much about an &quot;opinionated&quot; tool; toppcloud is not actually very opinionated.  It&#8217;s about a well-understood system.</p>
<p>For instance, Ben noticed a problem recently with <a class="reference external" href="http://code.google.com/p/modwsgi/issues/detail?id=177">weird import errors</a>.  I don&#8217;t know <em>quite</em> why mod_wsgi has this particular problem (when other WSGI servers that I&#8217;ve used haven&#8217;t), but the fix isn&#8217;t that hard.  So Ben <a class="reference external" href="http://bitbucket.org/ianb/toppcloud/changeset/27a470352a5e/">committed a fix</a> and the problem went away.</p>
<p>Personally I think this is a bug with mod_wsgi.  Maybe it&#8217;s also a Python bug.  But it doesn&#8217;t really matter.  When a bug exists it &quot;belongs&quot; to everyone who encounters it.</p>
<p>toppcloud is not intended to be a transparent system.  When it&#8217;s working correctly, you should be able to ignore most of the system and concentrate on the relatively simple abstractions given to your application.  So if the configuration reveals this particular bug in Python/mod_wsgi, then the bug is essentially a toppcloud bug, and toppcloud should (and <em>can</em>) fix it.</p>
<p>A more flexible system can ignore such problems as being &quot;somewhere else&quot; in the system.  Or, if you don&#8217;t define these problems as someone else&#8217;s problem, then a more flexible system is essentially always broken somewhere; there is always some untested combination, some new component, or some old component that might get pushed into the mix.  Fixes for one person&#8217;s problem may introduce a new problem in someone else&#8217;s stack.  Some fixes aren&#8217;t even clear.  toppcloud has Varnish in place, so it&#8217;s quite clear where a <a class="reference external" href="http://bitbucket.org/ianb/toppcloud/changeset/614d5366be67/">fix related to Django and Varnish configuration goes</a>.  If these were each components developed by different people at different times (like with buildout recipes) then fixing something like this could get complicated.</p>
<p>So I feel very resolved: toppcloud will hardcode everything it possibly can.  Python 2.6 and only 2.6!  (Until 2.7, but then <strong>only 2.7</strong>!).  Only Varnish/Apache/mod_wsgi.  I haven&#8217;t figured out threads/processes exactly, but once I do, there will be only one way!  And if I get it wrong, then everyone (<strong>everyone</strong>) will have to switch when it is corrected!  Because I&#8217;d much rather have a system that is inflexible than one that doesn&#8217;t work.  With a clear and solid design I think it is feasible to get this to work, and that is no small feat.</p>
<p>Relatedly, <a class="reference external" href="http://blog.ianbicking.org/2010/02/09/leaving-topp/comment-page-1/#comment-151194">I think I&#8217;m going to change the name of toppcloud</a>, so ideas are welcome!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/02/10/why-toppcloud-not-agnostic/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
		</item>
		<item>
		<title>toppcloud (Silver Lining) and Django</title>
		<link>http://blog.ianbicking.org/2010/02/05/toppcloud-and-django/</link>
		<comments>http://blog.ianbicking.org/2010/02/05/toppcloud-and-django/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 08:50:58 +0000</pubDate>
		<dc:creator>Ian Bicking</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Silver Lining]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://blog.ianbicking.org/?p=143</guid>
		<description><![CDATA[
I wrote up instructions on using toppcloud (update: renamed Silver Lining) with Django.  They are up on the site (where they will be updated in the future), but I&#8217;ll drop them here too&#8230;

Creating a Layout
First thing you have to do (after installing toppcloud of course) is create an environment for your new application.  [...]]]></description>
			<content:encoded><![CDATA[<div class="document">
<p>I wrote up instructions on using <a class="reference external" href="http://blog.ianbicking.org/2010/01/29/new-way-to-deploy-web-apps/">toppcloud</a> (<strong>update</strong>: renamed Silver Lining) with Django.  They are <a class="reference external" href="http://toppcloud.colorstudy.com/django-quickstart.html">up on the site</a> (where they will be updated in the future), but I&#8217;ll drop them here too&#8230;</p>
<div class="section" id="creating-a-layout">
<h2>Creating a Layout</h2>
<p>First thing you have to do (after installing toppcloud of course) is create an environment for your new application.  Do that like:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ toppcloud init sampleapp<br />
&nbsp;</div>
<p>This creates a directory <tt class="docutils literal"><span class="pre">sampleapp/</span></tt> with a basic layout.  The first thing we&#8217;ll do is set up version control for our project. For the sake of documentation, imagine you go to <a class="reference external" href="http://bitbucket.org">bitbucket</a> and create two new repositories, one called <tt class="docutils literal"><span class="pre">sampleapp</span></tt> and another called <tt class="docutils literal"><span class="pre">sampleapp-lib</span></tt> (and for the examples we&#8217;ll use the username <tt class="docutils literal"><span class="pre">USER</span></tt>).</p>
<p>We&#8217;ll go into our new environment and use these:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ <span class="kw3">cd</span> sampleapp<br />
$ hg clone http://bitbucket.<span class="me1">org</span>/USER/sampleapp src/sampleapp<br />
$ rm -r lib/python/<br />
$ hg clone http://bitbucket.<span class="me1">org</span>/USER/sampleapp-lib lib/python<br />
$ mkdir lib/python/bin/<br />
$ echo <span class="st0">&quot;syntax: glob<br />
bin/python*<br />
bin/activate<br />
bin/activate_this.py<br />
bin/pip<br />
bin/easy_install*<br />
&quot;</span> &gt; lib/python/.<span class="me1">hgignore</span><br />
$ mv bin/* lib/python/bin/<br />
$ rmdir bin/<br />
$ ln -s lib/python/bin bin<br />
&nbsp;</div>
<p>Now there is a basic layout setup, with all your libraries going into the <tt class="docutils literal"><span class="pre">sampleapp-lib</span></tt> repository, and your main application in the <tt class="docutils literal"><span class="pre">sampleapp</span></tt> repository.</p>
<p>Next we&#8217;ll install Django:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ source bin/activate<br />
$ pip install Django<br />
&nbsp;</div>
<p>Then we&#8217;ll set up a standard Django site:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ <span class="kw3">cd</span> src/sampleapp<br />
$ django-admin.<span class="me1">py</span> sampleapp<br />
&nbsp;</div>
<p>Also we&#8217;d like to be able to import this file.  It&#8217;d be nice if there was a <tt class="docutils literal"><span class="pre">setup.py</span></tt> file, and we could run <tt class="docutils literal"><span class="pre">pip</span> <span class="pre">-e</span> <span class="pre">src/sampleapp</span></tt>, but <tt class="docutils literal"><span class="pre">django-admin.py</span></tt> doesn&#8217;t create that itself.  Instead we&#8217;ll get that on the import path more manually with a <tt class="docutils literal"><span class="pre">.pth</span></tt> file:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ echo <span class="st0">&quot;../../src/sampleapp&quot;</span> &gt; lib/python/sampleapp.<span class="me1">pth</span><br />
&nbsp;</div>
<p>Also there&#8217;s the tricky <tt class="docutils literal"><span class="pre">$DJANGO_SETTINGS_MODULE</span></tt> that you might have had problems with before.  We&#8217;ll use the file <tt class="docutils literal"><span class="pre">lib/python/toppcustomize.py</span></tt> (which is imported everytime Python is started) to make sure that is always set:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ echo <span class="st0">&quot;import os<br />
os.environ['DJANGO_SETTINGS_MODULE'] = 'sampleapp.settings'<br />
&quot;</span> &gt; lib/python/toppcustomize.<span class="me1">py</span><br />
&nbsp;</div>
<p>Also we have a file <tt class="docutils literal"><span class="pre">src/sampleapp/sampleapp/manage.py</span></tt>, and that file doesn&#8217;t work <em>quite</em> how we&#8217;d like.  Instead we&#8217;ll put a file into <tt class="docutils literal"><span class="pre">bin/manage.py</span></tt> that does the same thing:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ rm sampleapp/manage.<span class="me1">py</span><br />
$ <span class="kw3">cd</span> ../..<br />
$ echo <span class="st0">'#!/usr/bin/env python<br />
from django.core.management import execute_manager<br />
from sampleapp import settings<br />
if __name__ == &quot;__main__&quot;:<br />
&nbsp; &nbsp; execute_manager(settings)<br />
'</span> &gt; bin/manage.<span class="me1">py</span><br />
$ chmod +x bin/manage.<span class="me1">py</span><br />
&nbsp;</div>
<p>Now, if you were just using plain Django you&#8217;d do something like run <tt class="docutils literal"><span class="pre">python</span> <span class="pre">manage.py</span> <span class="pre">runserver</span></tt>.  But we&#8217;ll be using <tt class="docutils literal"><span class="pre">toppcloud</span> <span class="pre">serve</span></tt> instead, which means we have to set up the two other files toppcloud needs: <tt class="docutils literal"><span class="pre">app.ini</span></tt> and the runner.  Here&#8217;s a simple <tt class="docutils literal"><span class="pre">app.ini</span></tt>:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ echo <span class="st0">'[production]<br />
app_name = sampleapp<br />
version = 1<br />
runner = src/sampleapp/toppcloud-runner.py<br />
'</span> &gt; src/sampleapp/toppcloud-app.<span class="me1">ini</span><br />
$ rm app.<span class="me1">ini</span><br />
$ ln -s src/sampleapp/toppcloud-app.<span class="me1">ini</span> app.<span class="me1">ini</span><br />
&nbsp;</div>
<p>The file <em>must</em> be in the &quot;root&quot; of your application, and named <tt class="docutils literal"><span class="pre">app.ini</span></tt>, but it&#8217;s good to keep it in version control, so we set it up with a symlink.</p>
<p>It also refers to a &quot;runner&quot;, which is the Python file that loads up the WSGI application.  This looks about the same for any Django application, and we&#8217;ll put it in <tt class="docutils literal"><span class="pre">src/sampleapp/toppcloud-runner.py</span></tt>:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ echo <span class="st0">'import django.core.handlers.wsgi<br />
application = django.core.handlers.wsgi.WSGIHandler()<br />
'</span> &gt; src/sampleapp/toppcloud-runner.<span class="me1">py</span><br />
&nbsp;</div>
<p>Now if you want to run the application, you can:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ toppcloud serve .<br />
&nbsp;</div>
<p>This will load it up on <tt class="docutils literal"><span class="pre">http://localhost:8080</span></tt>, and serve up a boring page.  To do something interesting we&#8217;ll want to use a database.</p>
</div>
<div class="section" id="setting-up-a-database">
<h2>Setting Up A Database</h2>
<p>At the moment the only good database to use is PostgreSQL with the PostGIS extensions.  Add this line to <tt class="docutils literal"><span class="pre">app.ini</span></tt>:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
service.<span class="me1">postgis</span> =<br />
&nbsp;</div>
<p>This makes the database &quot;available&quot; to the application.  For development you still have to set it up yourself.  You should create a database <tt class="docutils literal"><span class="pre">sampleapp</span></tt> on your computer.</p>
<p>Next, we&#8217;ll need to change <tt class="docutils literal"><span class="pre">settings.py</span></tt> to use the new database configuration.  Here&#8217;s the lines that you&#8217;ll see:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
DATABASE_ENGINE = <span class="st0">''</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.</span><br />
DATABASE_NAME = <span class="st0">''</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Or path to database file if using sqlite3.</span><br />
DATABASE_USER = <span class="st0">''</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Not used with sqlite3.</span><br />
DATABASE_PASSWORD = <span class="st0">''</span> &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Not used with sqlite3.</span><br />
DATABASE_HOST = <span class="st0">''</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Set to empty string for localhost. Not used with sqlite3.</span><br />
DATABASE_PORT = <span class="st0">''</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Set to empty string for default. Not used with sqlite3.</span><br />
&nbsp;</div>
<p>First add this to the top of the file:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">import</span> <span class="kw3">os</span><br />
&nbsp;</div>
<p>Then you&#8217;ll change those lines to:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
DATABASE_ENGINE = <span class="st0">'postgresql_psycopg2'</span><br />
DATABASE_NAME = <span class="kw3">os</span>.<span class="me1">environ</span><span class="br0">&#91;</span><span class="st0">'CONFIG_PG_DBNAME'</span><span class="br0">&#93;</span><br />
DATABASE_USER = <span class="kw3">os</span>.<span class="me1">environ</span><span class="br0">&#91;</span><span class="st0">'CONFIG_PG_USER'</span><span class="br0">&#93;</span><br />
DATABASE_PASSWORD = <span class="kw3">os</span>.<span class="me1">environ</span><span class="br0">&#91;</span><span class="st0">'CONFIG_PG_PASSWORD'</span><span class="br0">&#93;</span><br />
DATABASE_HOST = <span class="kw3">os</span>.<span class="me1">environ</span><span class="br0">&#91;</span><span class="st0">'CONFIG_PG_HOST'</span><span class="br0">&#93;</span><br />
DATABASE_PORT = <span class="st0">''</span><br />
&nbsp;</div>
<p>Now we can create all the default tables:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ manage.<span class="me1">py</span> syncdb<br />
Creating table auth_permission<br />
Creating table auth_group<br />
Creating table auth_user<br />
Creating table auth_message<br />
Creating table django_content_type<br />
Creating table django_session<br />
Creating table django_site<br />
...<br />
&nbsp;</div>
<p>Now we have an empty project that doesn&#8217;t do anything.  Let&#8217;s make it do a little something (this is all really based on <a class="reference external" href="http://docs.djangoproject.com/en/dev/intro/tutorial01/">the Django tutorial</a>).</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ manage.<span class="me1">py</span> startapp polls<br />
&nbsp;</div>
<p>Django magically knows to put the code in <tt class="docutils literal"><span class="pre">src/sampleapp/sampleapp/polls/</span></tt> &#8212; we&#8217;ll setup the model in <tt class="docutils literal"><span class="pre">src/sampleapp/sampleapp/polls/models.py</span></tt>:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> django.<span class="me1">db</span> <span class="kw1">import</span> models<br />
<br />
<span class="kw1">class</span> Poll<span class="br0">&#40;</span>models.<span class="me1">Model</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; question = models.<span class="me1">CharField</span><span class="br0">&#40;</span>max_length=<span class="nu0">200</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; pub_date = models.<span class="me1">DateTimeField</span><span class="br0">&#40;</span><span class="st0">'date published'</span><span class="br0">&#41;</span><br />
<br />
<span class="kw1">class</span> Choice<span class="br0">&#40;</span>models.<span class="me1">Model</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; poll = models.<span class="me1">ForeignKey</span><span class="br0">&#40;</span>Poll<span class="br0">&#41;</span><br />
&nbsp; &nbsp; choice = models.<span class="me1">CharField</span><span class="br0">&#40;</span>max_length=<span class="nu0">200</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; votes = models.<span class="me1">IntegerField</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>And activate the application by adding <tt class="docutils literal"><span class="pre">'sampleapp.polls'</span></tt> to <tt class="docutils literal"><span class="pre">INSTALLED_APPS</span></tt> in <tt class="docutils literal"><span class="pre">src/sampleapp/sampleapp/settings.py</span></tt>.  Also add <tt class="docutils literal"><span class="pre">'django.contrib.admin'</span></tt> to get the admin app in place.  Run <tt class="docutils literal"><span class="pre">manage.py</span> <span class="pre">syncdb</span></tt> to get the tables in place.</p>
<p>You can try <tt class="docutils literal"><span class="pre">toppcloud</span> <span class="pre">serve</span> <span class="pre">.</span></tt> and go to <tt class="docutils literal"><span class="pre">/admin/</span></tt> to login and see your tables.  You might notice all the CSS is broken.</p>
<p>toppcloud serves static files out of the <tt class="docutils literal"><span class="pre">static/</span></tt> directory.  You don&#8217;t actually put <tt class="docutils literal"><span class="pre">static</span></tt> in the URLs, these files are available at the top-level (unless you create a <tt class="docutils literal"><span class="pre">static/static/</span></tt> directory). The best way to put files in there is generally symbolic links.</p>
<p>For Django admin, do this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
$ <span class="kw3">cd</span> static<br />
$ ln -s ../lib/python/django/contrib/admin/media admin-media<br />
&nbsp;</div>
<p>Now edit <tt class="docutils literal"><span class="pre">src/sampleapp/sampleapp/settings.py</span></tt> and change <tt class="docutils literal"><span class="pre">ADMIN_MEDIA_PREFIX</span></tt> to <tt class="docutils literal"><span class="pre">'/admin-media'</span></tt>.</p>
<p>(Probably some other links should be added.)</p>
<p>One <em>last</em> little thing you might want to do; replace this line in<br />
settings:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
SECRET_KEY = <span class="st0">'ASF#&amp;#64;$&amp;#64;#JFAS#&amp;#64;'</span><br />
&nbsp;</div>
<p>With this:</p>
<div class="dean_ch" style="white-space: wrap;"><br />
<span class="kw1">from</span> tcsupport.<span class="me1">secret</span> <span class="kw1">import</span> get_secret<br />
SECRET_KEY = get_secret<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Then you don&#8217;t have to worry about checking a secret into version control.</p>
<p>You still don&#8217;t really have an application, but the rest is mere &quot;programming&quot; so have at it!</p>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.ianbicking.org/2010/02/05/toppcloud-and-django/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 1.109 seconds -->
<!-- Cached page served by WP-Cache -->
