<?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>KenKinder.com</title>
	<atom:link href="http://kenkinder.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://kenkinder.com</link>
	<description>Ken Kinder&#039;s personal website</description>
	<lastBuildDate>Mon, 01 Feb 2010 18:26:14 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Android, Google Maps, Navigation, and Open Source&#8230;</title>
		<link>http://kenkinder.com/2009/11/16/android-google-maps-navigation-and-open-source/</link>
		<comments>http://kenkinder.com/2009/11/16/android-google-maps-navigation-and-open-source/#comments</comments>
		<pubDate>Mon, 16 Nov 2009 18:03:18 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=246</guid>
		<description><![CDATA[UPDATE: The details of this article are now moot, as the latest Google Maps application on the Android Market includes navigation on the G1.
OF COURSE when I saw that someone on the Interwebz managed to get the new Google Maps with navigation running on a G1, I almost wet myself with excitement. Normally this app [...]]]></description>
			<content:encoded><![CDATA[<p style="padding-left: 30px;"><strong>UPDATE: The details of this article are now moot, as the latest Google Maps application on the Android Market includes navigation on the G1.</strong></p>
<p>OF COURSE when I saw that <a href="http://forum.xda-developers.com/showthread.php?t=582656&amp;page=8">someone on the Interwebz</a> managed to get the new Google Maps with navigation running on a G1, I almost wet myself with excitement. Normally this app only runs on the new Android 2.0 phones (namely, Droid from Verizon) and even rooted G1 are still only running Android 1.6. The <a href="http://forum.xda-developers.com/showpost.php?p=4920480&amp;postcount=75">instructions</a> call for basically replacing the entire build properties on your phone with the Droid ones.</p>
<p><span id="more-246"></span></p>
<p>I&#8217;m not going to write any explicit instructions, since those are already on the forums and easily accessible with a Google search. But here&#8217;s basically what I did, which temporarily enabled navigation. To build.prop, I made the following changes:</p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">kkinder@kkinder-laptop ~/Desktop&amp;gt; diff -u bp2 build.prop
<span style="color: #888822;">--- build.prop.org	<span style="">2009</span>-<span style="">11</span>-<span style="">16</span> <span style="">11</span>:<span style="">40</span>:<span style="">34.000000000</span> -0700</span>
<span style="color: #888822;">+++ build.prop	<span style="">2009</span>-<span style="">11</span>-<span style="">10</span> <span style="">19</span>:<span style="">13</span>:<span style="">18.000000000</span> -0700</span>
<span style="color: #440088;">@@ -<span style="">1</span>,<span style="">6</span> +<span style="">1</span>,<span style="">6</span> @@</span>
 # begin build properties
<span style="color: #991111;">-ro.build.version.sdk=4</span>
<span style="color: #991111;">-ro.build.version.release=1.6</span>
<span style="color: #00b000;">+ro.build.version.sdk=&lt;strong&gt;<span style="">5</span>&lt;/strong&gt;</span>
<span style="color: #00b000;">+ro.build.version.release=&lt;strong&gt;<span style="">2.0</span>&lt;/strong&gt;</span>
 ro.build.version.codename=REL
 ro.build.type=user
 ro.build.user=shade
<span style="color: #440088;">@@ -<span style="">15</span>,<span style="">7</span> +<span style="">15</span>,<span style="">7</span> @@</span>
 ro.com.android.wifi-watchlist=GoogleGuest
 ro.com.android.dateformat=MM-dd-yyyy
 ro.com.android.dataroaming=true
<span style="color: #991111;">-ro.com.google.clientidbase=android-tmobile</span>
<span style="color: #00b000;">+ro.com.google.clientidbase=&lt;strong&gt;android-verizon&lt;/strong&gt;</span>
 ro.setupwizard.mode=OPTIONAL
 ro.url.legal=http://www.google.com/intl/%s/mobile/android/android-dev-phone-legal.html
 ro.url.legal.android_privacy=http://www.google.com/intl/%s/mobile/android/android-dev-phone-privacy.html</pre></div></div>

<p>At this point, after using the unix <tt>find</tt> command in my phone&#8217;s terminal emulator to delete old maps data files and application files, I was able to reboot and install the maps app with all its new features &#8212; all its new features, except for navigation. So, I continued with the *real* instructions and applied changes to build.trout.prop</p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">--- build.trout.prop.orig	<span style="">2009</span>-<span style="">11</span>-<span style="">16</span> <span style="">11</span>:<span style="">40</span>:<span style="">56.000000000</span> -0700
<span style="color: #888822;">+++ build.trout.prop	<span style="">2009</span>-<span style="">11</span>-<span style="">10</span> <span style="">19</span>:<span style="">13</span>:<span style="">18.000000000</span> -0700</span>
<span style="color: #440088;">@@ -<span style="">1</span>,<span style="">25</span> +<span style="">1</span>,<span style="">25</span> @@</span>
 # begin build properties
 # autogenerated by buildinfo.sh
<span style="color: #991111;">-ro.build.id=DRC83</span>
<span style="color: #991111;">-ro.build.display.id=DRC83</span>
<span style="color: #991111;">-ro.build.version.incremental=14721</span>
<span style="color: #00b000;">+ro.build.id=ESD20</span>
<span style="color: #00b000;">+ro.build.display.id=ESD20</span>
<span style="color: #00b000;">+ro.build.version.incremental=17572</span>
 ro.build.date=Mon Sep <span style="">21</span> <span style="">16</span>:<span style="">16</span>:<span style="">12</span> PDT <span style="">2009</span>
 ro.build.date.utc=<span style="">1253574972</span>
<span style="color: #991111;">-ro.product.model=T-Mobile G1</span>
<span style="color: #991111;">-ro.product.brand=tmobile</span>
<span style="color: #00b000;">+ro.product.model=Droid</span>
<span style="color: #00b000;">+ro.product.brand=verizon</span>
 ro.product.name=kila
<span style="color: #991111;">-ro.product.device=dream</span>
<span style="color: #991111;">-ro.product.board=trout</span>
<span style="color: #00b000;">+ro.product.device=sholes</span>
<span style="color: #00b000;">+ro.product.board=sholes</span>
 ro.product.cpu.abi=armeabi
<span style="color: #991111;">-ro.product.manufacturer=HTC</span>
<span style="color: #00b000;">+ro.product.manufacturer=Motorola</span>
 ro.product.locale.language=en
 ro.product.locale.region=US
 ro.board.platform=msm7k
 # ro.build.product is obsolete; use ro.product.device
 ro.build.product=dream
 # Do not try to parse ro.build.description or .fingerprint
<span style="color: #991111;">-ro.build.description=kila-user <span style="">1.6</span> DRC83 <span style="">14721</span> ota-rel-keys,release-keys</span>
<span style="color: #991111;">-ro.build.fingerprint=tmobile/kila/dream/trout:<span style="">1.6</span>/DRC83/<span style="">14721</span>:user/ota-rel-keys,release-keys</span>
<span style="color: #00b000;">+ro.build.description=voles-user <span style="">2.0</span> ESD20 <span style="">17572</span> ota-rel-keys,release-keys</span>
<span style="color: #00b000;">+ro.build.fingerprint=verizon/voles/sholes/sholes:<span style="">2.0</span>/ESD20/<span style="">17572</span>:user/ota-rel-keys,release-keys</span>
 # end build properties
 #
 # system.prop for dream</pre></div></div>

<p>I don&#8217;t really like the idea of editing these files, because when the system lies about its version numbers, it could break other apps. But I made backups and did it anyway, with no dice on having a working navigation system. Some reading on a thread that grew to 50 posts within hours and I noticed some users reported that uninstalling and reinstalling Google Voice got navigation working on the (presumably unrelated) maps app, which it did.</p>
<p>But here&#8217;s the frustrating part: After driving around and enjoying your new navigation system, you go to restore your build*props files. If you revert version numbers, the app continues to work. However once you change your phone&#8217;s model information back (ie, you switch Verizon back to T-Mobile), your navigation disappears in the GUI. In other words, the map app is checking to make sure you&#8217;re running on Verizon&#8217;s network, and only allows you navigation then. That&#8217;s kind of slimey, but <strong>update:</strong> the updated Android 1.6 app includes navigation, so I guess my initial conspiracy theories are irrelevant.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2009/11/16/android-google-maps-navigation-and-open-source/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to fix NiftyCube IE 8 width problem</title>
		<link>http://kenkinder.com/2009/10/26/how-to-fix-niftycube-ie-8-width-problem/</link>
		<comments>http://kenkinder.com/2009/10/26/how-to-fix-niftycube-ie-8-width-problem/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 17:28:57 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Bugs]]></category>
		<category><![CDATA[diff]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[patch]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=241</guid>
		<description><![CDATA[At work we use this tool called NiftyCube to round corners of elements (it even works with divs that have gradients in them). The problem, however, is that on Internet Explorer 8, 100% width divs are shrunk to the contents of the div.

That happens because NiftyCube has code to correct rendering problems in previous version [...]]]></description>
			<content:encoded><![CDATA[<p>At work we use this tool called <a href="http://www.html.it/articoli/niftycube/index.html">NiftyCube</a> to round corners of elements (it even works with divs that have gradients in them). The problem, however, is that on Internet Explorer 8, 100% width divs are shrunk to the contents of the div.</p>
<p><span id="more-241"></span></p>
<p>That happens because NiftyCube has code to correct rendering problems in previous version of IE. Since IE 8 renders more elements correctly, NiftyCube&#8217;s hack actually makes things worse in IE 8. To fix the problem, disable their fix for IE 8. Apply this change to niftycube.js:</p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">Index: tuber/trunk/common/web/htdocs/assets/js/niftycube.js
===================================================================
<span style="color: #888822;">--- a/tuber/trunk/common/web/htdocs/assets/js/niftycube.js</span>
<span style="color: #888822;">+++ b/tuber/trunk/common/web/htdocs/assets/js/niftycube.js</span>
<span style="color: #440088;">@@ -<span style="">156</span>,<span style="">7</span> +<span style="">156</span>,<span style="">22</span> @@</span>
 <span style="">&#125;</span>
&nbsp;
<span style="color: #00b000;">+function getIeVersion<span style="">&#40;</span><span style="">&#41;</span> <span style="">&#123;</span></span>
<span style="color: #00b000;">+    var rv = -<span style="">1</span>;</span>
<span style="color: #00b000;">+    if <span style="">&#40;</span>navigator.appName == 'Microsoft Internet Explorer'<span style="">&#41;</span> <span style="">&#123;</span></span>
<span style="color: #00b000;">+        var ua = navigator.userAgent;</span>
<span style="color: #00b000;">+        var re = new RegExp<span style="">&#40;</span>&quot;MSIE <span style="">&#40;</span><span style="">&#91;</span><span style="">0</span>-<span style="">9</span><span style="">&#93;</span><span style="">&#123;</span><span style="">1</span>,<span style="">&#125;</span><span style="">&#91;</span>\.0-<span style="">9</span><span style="">&#93;</span><span style="">&#123;</span><span style="">0</span>,<span style="">&#125;</span><span style="">&#41;</span>&quot;<span style="">&#41;</span>;</span>
<span style="color: #00b000;">+        if <span style="">&#40;</span>re.exec<span style="">&#40;</span>ua<span style="">&#41;</span> != null<span style="">&#41;</span> <span style="">&#123;</span></span>
<span style="color: #00b000;">+            rv = parseFloat<span style="">&#40;</span>RegExp.$<span style="">1</span><span style="">&#41;</span>;</span>
<span style="color: #00b000;">+        <span style="">&#125;</span></span>
<span style="color: #00b000;">+    <span style="">&#125;</span></span>
<span style="color: #00b000;">+    return rv;</span>
<span style="color: #00b000;">+<span style="">&#125;</span></span>
<span style="color: #00b000;">+</span>
 function FixIE<span style="">&#40;</span>el<span style="">&#41;</span><span style="">&#123;</span>
 if<span style="">&#40;</span>el.currentStyle!=null &amp;&amp; el.currentStyle.hasLayout!=null &amp;&amp; el.currentStyle.hasLayout==false<span style="">&#41;</span>
<span style="color: #991111;">-    el.style.display=&quot;inline-block&quot;;</span>
<span style="color: #00b000;">+    var ver = getIeVersion<span style="">&#40;</span><span style="">&#41;</span>;</span>
<span style="color: #00b000;">+    if <span style="">&#40;</span>ver &lt; <span style="">8</span><span style="">&#41;</span> <span style="">&#123;</span></span>
<span style="color: #00b000;">+        el.style.display=&quot;inline-block&quot;;</span>
<span style="color: #00b000;">+    <span style="">&#125;</span></span>
 <span style="">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2009/10/26/how-to-fix-niftycube-ie-8-width-problem/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>CherryPy v. Pylons</title>
		<link>http://kenkinder.com/2009/10/18/cherrypy-v-pylons/</link>
		<comments>http://kenkinder.com/2009/10/18/cherrypy-v-pylons/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 16:12:27 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[CherryPy]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[mako]]></category>
		<category><![CDATA[Pylons]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=194</guid>
		<description><![CDATA[Over various pints of beer, emails, and late-night twitter tweets, I&#8217;ve alone and with others wondered about whether a smart, well-adjusted programmer would use Pylons or CherryPy for all his web programming needs (and whether such a programmer would take the time to convert from CherryPy to Pylons). Pylons is newish to me, but I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Over various pints of beer, emails, and late-night twitter tweets, I&#8217;ve alone and with others wondered about whether a smart, well-adjusted programmer would use <a href="http://pylonshq.com/">Pylons</a> or <a href="http://www.cherrypy.org/">CherryPy</a> for all his web programming needs (and whether such a programmer would take the time to convert from CherryPy to Pylons). Pylons is newish to me, but I&#8217;ve been using CherryPy (on and off) for years now. What troubles me about CherryPy is that despite all those years of experience, there are still parts of CherryPy I struggle with (and not just <a href="http://www.cherrypy.org/browser/trunk/cherrypy/lib/sessions.py?rev=2528#L389">this horrible while-true-except-pass loop</a>). Here are my partially collected thoughts. I&#8217;ll start with what bugs me enough about CherryPy for me to seek alternatives.</p>
<p><span id="more-194"></span></p>
<p>If you visit the URI <tt>/foo/bar/spam</tt>, CherryPy looks for a <tt>foo.bar</tt> controller with a <tt>spam</tt> action (sort of). There are other mostly irrelevant complexities (mount points for quasi-apps and such), but that&#8217;s the gist. You can write your own &#8220;dispatcher&#8221; in CherryPy to map URLs to executable code, or use ones such as the <a href="http://www.cherrypy.org/wiki/PageHandlers">RoutesDispatcher</a>, which uses <a href="http://routes.groovie.org/">Groovie Routes</a> to map URLs to code. But using your own component is always kind of a sour-tasting afterthought in CherryPy and you&#8217;re sometimes reminded of that, unpleasantly (for example, routes for static content do not work in RoutesDispatcher).</p>
<p>In version 3, CherryPy&#8217;s previously simple configuration system got kind of confusing. I started writing a lot of code like this:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">cherrypy.<span style="color: black;">config</span>.<span style="color: black;">update</span><span style="color: black;">&#40;</span>myConfig<span style="color: black;">&#41;</span>
app = cherrypy.<span style="color: black;">tree</span>.<span style="color: black;">mount</span><span style="color: black;">&#40;</span><span style="color: #008000;">None</span>, moreConfig<span style="color: black;">&#41;</span>
cherrypy.<span style="color: black;">config</span>.<span style="color: black;">update</span><span style="color: black;">&#40;</span>someFile<span style="color: black;">&#41;</span>
cherrypy.<span style="color: black;">quickstart</span><span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span></pre></div></div>

<p>CherryPy lets you pass in configuration options a number of ways: <em>In Python</em>: dicts passed to <tt>config.update</tt>, dicts passed to <tt>tree.mount</tt>, or dicts on your controller object. <em>In <a href="http://docs.python.org/library/configparser.html">ConfigParser</a> syntax</em>: as filenames passed to <tt>config.update</tt> or <tt>tree.mount</tt>. The problem is that I&#8217;m always left with trial-and-error in figuring out what options I have; configuration directives don&#8217;t work everywhere, and you&#8217;re given relatively little guidance finding out where. If the documentation were better, that might help, but it&#8217;s confusing no matter what.</p>
<p>Which brings me to my most significant grievance with CherryPy: Its documentation is mediocre and because it takes such a novel approach to so many things, it needs good documentation. Most of CherryPy&#8217;s documentation is on a loosely organized wiki that resembles someone&#8217;s lecture notes more than it resembles documentation. This makes finding specific pieces of information difficult; for example, the RoutesDispatcher from above is buried deep down on a page called &#8220;PageHandlers&#8221; and is otherwise mostly unmentioned. Sometimes the wiki looks helpful, such as on <a href="http://cherrypy.org/wiki/FileUpload">this file upload page</a>, but in practice the examples given are apparently built for an old version of the framework (&#8220;<tt>from cherrypy.lib.filter import basefilter</tt>&#8221; results in an ImportError).</p>
<p>You can always ask CherryPy&#8217;s mailing list, but be forewarned: it&#8217;s not very inhabited now that TurboGears moved to Pylons.</p>
<p><strong>Where is CherryPy superior?</strong></p>
<p>After all these gripes, you might think I&#8217;m fully convinced that move to Pylons is good. A simple &#8220;Hello World&#8221; comparison reveals why that&#8217;s not the case. In CherryPy:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> cherrypy
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> HelloWorld<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Hello World!&quot;</span>
    index.<span style="color: black;">exposed</span> = <span style="color: #008000;">True</span>
&nbsp;
cherrypy.<span style="color: black;">quickstart</span><span style="color: black;">&#40;</span>HelloWorld<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>In Pylons: &#8230; this is going to take some time. Pylons doesn&#8217;t let you create a Hello World app in one file. Or even one directory. You start by running this command (for convenience and comic effect, there are scroll bars):</p>
<pre lang="python" style="height: 200px; overflow: scroll;">
kkinder@kkinder-laptop ~> paster create MyHelloWorldProject -t pylons
Selected and implied templates:
  Pylons#pylons  Pylons application template

Variables:
  egg:      MyHelloWorldProject
  package:  myhelloworldproject
  project:  MyHelloWorldProject
Enter template_engine (mako/genshi/jinja2/etc: Template language) ['mako']:
Enter sqlalchemy (True/False: Include SQLAlchemy 0.5 configuration) [False]:
Creating template pylons
Creating directory ./MyHelloWorldProject
  Recursing into +package+
    Creating ./MyHelloWorldProject/myhelloworldproject/
    Copying templates/default_project/+package+/__init__.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/__init__.py
    Recursing into config
      Creating ./MyHelloWorldProject/myhelloworldproject/config/
      Copying templates/default_project/+package+/config/__init__.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/config/__init__.py
      Copying templates/default_project/+package+/config/deployment.ini_tmpl_tmpl to ./MyHelloWorldProject/myhelloworldproject/config/deployment.ini_tmpl
      Copying templates/default_project/+package+/config/environment.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/config/environment.py
      Copying templates/default_project/+package+/config/middleware.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/config/middleware.py
      Copying templates/default_project/+package+/config/routing.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/config/routing.py
    Recursing into controllers
      Creating ./MyHelloWorldProject/myhelloworldproject/controllers/
      Copying templates/default_project/+package+/controllers/__init__.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/controllers/__init__.py
      Copying templates/default_project/+package+/controllers/error.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/controllers/error.py
    Recursing into lib
      Creating ./MyHelloWorldProject/myhelloworldproject/lib/
      Copying templates/default_project/+package+/lib/__init__.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/lib/__init__.py
      Copying templates/default_project/+package+/lib/app_globals.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/lib/app_globals.py
      Copying templates/default_project/+package+/lib/base.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/lib/base.py
      Copying templates/default_project/+package+/lib/helpers.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/lib/helpers.py
    Recursing into model
      Creating ./MyHelloWorldProject/myhelloworldproject/model/
      Copying templates/default_project/+package+/model/__init__.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/model/__init__.py
    Recursing into public
      Creating ./MyHelloWorldProject/myhelloworldproject/public/
      Copying templates/default_project/+package+/public/bg.png to ./MyHelloWorldProject/myhelloworldproject/public/bg.png
      Copying templates/default_project/+package+/public/favicon.ico to ./MyHelloWorldProject/myhelloworldproject/public/favicon.ico
      Copying templates/default_project/+package+/public/index.html_tmpl to ./MyHelloWorldProject/myhelloworldproject/public/index.html
      Copying templates/default_project/+package+/public/pylons-logo.gif to ./MyHelloWorldProject/myhelloworldproject/public/pylons-logo.gif
    Recursing into templates
      Creating ./MyHelloWorldProject/myhelloworldproject/templates/
    Recursing into tests
      Creating ./MyHelloWorldProject/myhelloworldproject/tests/
      Copying templates/default_project/+package+/tests/__init__.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/tests/__init__.py
      Recursing into functional
        Creating ./MyHelloWorldProject/myhelloworldproject/tests/functional/
        Copying templates/default_project/+package+/tests/functional/__init__.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/tests/functional/__init__.py
      Copying templates/default_project/+package+/tests/test_models.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/tests/test_models.py
    Copying templates/default_project/+package+/websetup.py_tmpl to ./MyHelloWorldProject/myhelloworldproject/websetup.py
  Copying templates/default_project/MANIFEST.in_tmpl to ./MyHelloWorldProject/MANIFEST.in
  Copying templates/default_project/README.txt_tmpl to ./MyHelloWorldProject/README.txt
  Copying templates/default_project/development.ini_tmpl to ./MyHelloWorldProject/development.ini
  Recursing into docs
    Creating ./MyHelloWorldProject/docs/
    Copying templates/default_project/docs/index.txt_tmpl to ./MyHelloWorldProject/docs/index.txt
  Copying templates/default_project/ez_setup.py to ./MyHelloWorldProject/ez_setup.py
  Copying templates/default_project/setup.cfg_tmpl to ./MyHelloWorldProject/setup.cfg
  Copying templates/default_project/setup.py_tmpl to ./MyHelloWorldProject/setup.py
  Copying templates/default_project/test.ini_tmpl to ./MyHelloWorldProject/test.ini
Running /usr/bin/python setup.py egg_info
</pre>
<p>I of course went for the lighter option that doesn&#8217;t include <a href="http://www.sqlalchemy.org/">SQLAlchemy</a>. Okay, we&#8217;re almost there. Now I&#8217;m going to create a Hello controller:</p>
<pre>
kkinder@kkinder-laptop ~/MyHelloWorldProject> paster controller Hello
Creating /home/kkinder/MyHelloWorldProject/myhelloworldproject/controllers/Hello.py
Creating /home/kkinder/MyHelloWorldProject/myhelloworldproject/tests/functional/test_Hello.py
</pre>
<p>This is where Pylons READS MY MIND and does the work for me. Take a look at the new <tt>Hello.py</tt> controller it made for me:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> pylons <span style="color: #ff7700;font-weight:bold;">import</span> request, response, session, tmpl_context <span style="color: #ff7700;font-weight:bold;">as</span> c
<span style="color: #ff7700;font-weight:bold;">from</span> pylons.<span style="color: black;">controllers</span>.<span style="color: black;">util</span> <span style="color: #ff7700;font-weight:bold;">import</span> abort, redirect_to
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> myhelloworldproject.<span style="color: black;">lib</span>.<span style="color: black;">base</span> <span style="color: #ff7700;font-weight:bold;">import</span> BaseController, render
&nbsp;
log = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span>__name__<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> HelloController<span style="color: black;">&#40;</span>BaseController<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Return a rendered template</span>
        <span style="color: #808080; font-style: italic;">#return render('/Hello.mako')</span>
        <span style="color: #808080; font-style: italic;"># or, return a response</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">'Hello World'</span></pre></div></div>

<p>But I&#8217;m not done yet. Now I need to edit my routing.py file, check my development.ini for any settings, run &#8220;setup.py develop&#8221; and then use &#8220;paster serve&#8221; to finally test my app. By the time I&#8217;m done printing &#8220;Hello World&#8221;, I have 42 files in 11 directories:</p>
<pre style="height: 200px; overflow: scroll">
.
|-- MANIFEST.in
|-- MyHelloWorldProject.egg-info
|   |-- PKG-INFO
|   |-- SOURCES.txt
|   |-- dependency_links.txt
|   |-- entry_points.txt
|   |-- not-zip-safe
|   |-- paster_plugins.txt
|   |-- requires.txt
|   `-- top_level.txt
|-- README.txt
|-- development.ini
|-- docs
|   `-- index.txt
|-- ez_setup.py
|-- myhelloworldproject
|   |-- __init__.py
|   |-- __init__.pyc
|   |-- config
|   |   |-- __init__.py
|   |   |-- deployment.ini_tmpl
|   |   |-- environment.py
|   |   |-- middleware.py
|   |   `-- routing.py
|   |-- controllers
|   |   |-- Hello.py
|   |   |-- __init__.py
|   |   `-- error.py
|   |-- lib
|   |   |-- __init__.py
|   |   |-- __init__.pyc
|   |   |-- app_globals.py
|   |   |-- base.py
|   |   |-- base.pyc
|   |   `-- helpers.py
|   |-- model
|   |   `-- __init__.py
|   |-- public
|   |   |-- bg.png
|   |   |-- favicon.ico
|   |   |-- index.html
|   |   `-- pylons-logo.gif
|   |-- templates
|   |-- tests
|   |   |-- __init__.py
|   |   |-- functional
|   |   |   |-- __init__.py
|   |   |   `-- test_Hello.py
|   |   `-- test_models.py
|   `-- websetup.py
|-- setup.cfg
|-- setup.py
`-- test.ini

11 directories, 42 files
</pre>
<p>The Django/Pylons/TurboGears frameworks all follow a teeth gnashing design pattern that came out of Java and was made ugly in Ruby: Code generation. This is just my opinion, but in a language as dynamic and meta-programmative as Python, code generation is obsolete <em>at best</em>. What happens when the basic layout for a project changes a bit in the next version of Pylons? Do I &#8220;diff&#8221; the paste template and compare it to the old version to see what changed? And half of the configuration is in Pylon&#8217;s WSGI-obsessed middleware.py file, which is itself both a product of code generation and subsequent edits by the developer:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;Pylons middleware initialization&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">from</span> beaker.<span style="color: black;">middleware</span> <span style="color: #ff7700;font-weight:bold;">import</span> CacheMiddleware, SessionMiddleware
<span style="color: #ff7700;font-weight:bold;">from</span> paste.<span style="color: black;">cascade</span> <span style="color: #ff7700;font-weight:bold;">import</span> Cascade
<span style="color: #ff7700;font-weight:bold;">from</span> paste.<span style="color: black;">registry</span> <span style="color: #ff7700;font-weight:bold;">import</span> RegistryManager
<span style="color: #ff7700;font-weight:bold;">from</span> paste.<span style="color: black;">urlparser</span> <span style="color: #ff7700;font-weight:bold;">import</span> StaticURLParser
<span style="color: #ff7700;font-weight:bold;">from</span> paste.<span style="color: black;">deploy</span>.<span style="color: black;">converters</span> <span style="color: #ff7700;font-weight:bold;">import</span> asbool
<span style="color: #ff7700;font-weight:bold;">from</span> pylons <span style="color: #ff7700;font-weight:bold;">import</span> config
<span style="color: #ff7700;font-weight:bold;">from</span> pylons.<span style="color: black;">middleware</span> <span style="color: #ff7700;font-weight:bold;">import</span> ErrorHandler, StatusCodeRedirect
<span style="color: #ff7700;font-weight:bold;">from</span> pylons.<span style="color: black;">wsgiapp</span> <span style="color: #ff7700;font-weight:bold;">import</span> PylonsApp
<span style="color: #ff7700;font-weight:bold;">from</span> routes.<span style="color: black;">middleware</span> <span style="color: #ff7700;font-weight:bold;">import</span> RoutesMiddleware
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> myhelloworldproject.<span style="color: black;">config</span>.<span style="color: black;">environment</span> <span style="color: #ff7700;font-weight:bold;">import</span> load_environment
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> make_app<span style="color: black;">&#40;</span>global_conf, full_stack=<span style="color: #008000;">True</span>, static_files=<span style="color: #008000;">True</span>, <span style="color: #66cc66;">**</span>app_conf<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Create a Pylons WSGI application and return it
&nbsp;
    ``global_conf``
        The inherited configuration for this application. Normally from
        the [DEFAULT] section of the Paste ini file.
&nbsp;
    ``full_stack``
        Whether this application provides a full WSGI stack (by default,
        meaning it handles its own exceptions and errors). Disable
        full_stack when this application is &quot;managed&quot; by another WSGI
        middleware.
&nbsp;
    ``static_files``
        Whether this application serves its own static files; disable
        when another web server is responsible for serving them.
&nbsp;
    ``app_conf``
        The application's local configuration. Normally specified in
        the [app:&lt;name&gt;] section of the Paste ini file (where &lt;name&gt;
        defaults to main).
&nbsp;
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># Configure the Pylons environment</span>
    load_environment<span style="color: black;">&#40;</span>global_conf, app_conf<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># The Pylons WSGI app</span>
    app = PylonsApp<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Routing/Session/Cache Middleware</span>
    app = RoutesMiddleware<span style="color: black;">&#40;</span>app, config<span style="color: black;">&#91;</span><span style="color: #483d8b;">'routes.map'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    app = SessionMiddleware<span style="color: black;">&#40;</span>app, config<span style="color: black;">&#41;</span>
    app = CacheMiddleware<span style="color: black;">&#40;</span>app, config<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> asbool<span style="color: black;">&#40;</span>full_stack<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Handle Python exceptions</span>
        app = ErrorHandler<span style="color: black;">&#40;</span>app, global_conf, <span style="color: #66cc66;">**</span>config<span style="color: black;">&#91;</span><span style="color: #483d8b;">'pylons.errorware'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #808080; font-style: italic;"># Display error documents for 401, 403, 404 status codes (and</span>
        <span style="color: #808080; font-style: italic;"># 500 when debug is disabled)</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> asbool<span style="color: black;">&#40;</span>config<span style="color: black;">&#91;</span><span style="color: #483d8b;">'debug'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:
            app = StatusCodeRedirect<span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            app = StatusCodeRedirect<span style="color: black;">&#40;</span>app, <span style="color: black;">&#91;</span><span style="color: #ff4500;">400</span>, <span style="color: #ff4500;">401</span>, <span style="color: #ff4500;">403</span>, <span style="color: #ff4500;">404</span>, <span style="color: #ff4500;">500</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># Establish the Registry for this application</span>
    app = RegistryManager<span style="color: black;">&#40;</span>app<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> asbool<span style="color: black;">&#40;</span>static_files<span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># Serve static files</span>
        static_app = StaticURLParser<span style="color: black;">&#40;</span>config<span style="color: black;">&#91;</span><span style="color: #483d8b;">'pylons.paths'</span><span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'static_files'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
        app = Cascade<span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>static_app, app<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> app</pre></div></div>

<p>Beyond its sanity in <em>not</em> generating piles of code, CherryPy has other advantages. Its testing framework is very easy to use, but and also <a href="http://www.cherrypy.org/wiki/Testing">documented with almost no examples</a>. Pylons, in contrast, tells you where to put the tests but doesn&#8217;t make it quite as easy to run them.</p>
<p>On a day to day basis, writing code in CherryPy is seldom a chore; it isn&#8217;t exciting or cutting edge, but it&#8217;s simple and usually CherryPy does a good job of staying out of your way. I&#8217;m never left wondering in CherryPy whether there is a specific &#8220;CherryPy way to do it,&#8221; while in Pylons, my framework even has an opinion on what Javascript library I choose (it likes script.aculo.us, although it doesn&#8217;t bang you over the head with it). CherryPy is usually simpler: take a look at <a href="http://static.repoze.org/whodocs/">repoze.who/what</a> or <a href="http://authkit.org/">AuthKit</a> in the Pylons world and compare a very simple <a href="http://tools.cherrypy.org/wiki/AuthenticationAndAccessRestrictions">CherryPy auth example</a>.</p>
<p>But there are places where Pylons is amazing&#8230;</p>
<p><strong>One more thing: What&#8217;s missing from CherryPy?</strong></p>
<p>Pylons error handling is the one killer feature it has that CherryPy just lacks. Skip to line 598 of the &#8220;Hello, World&#8221; pylons project and try throwing an error:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">    <span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span></pre></div></div>

<p>Then use the controller. In CherryPy, I would get a Python traceback wrapped in a &lt;pre&gt; tag. In Pylons, I get an ajax debugger with expression evaluation and variable inspection:</p>
<p><a href="http://kenkinder.com/wp-content/uploads/2009/08/screenshot1.png"><img src="http://kenkinder.com/wp-content/uploads/2009/08/screenshot1.png" alt="Pylons Screenshot" title="Pylons Screenshot" width="850" height="288" class="alignnone size-full wp-image-225" /></a><br/></p>
<p>I can inspect variables and evaluate expressions at each point in the traceback:</p>
<p><a href="http://kenkinder.com/wp-content/uploads/2009/08/screenshot2.png"><img src="http://kenkinder.com/wp-content/uploads/2009/08/screenshot2.png" alt="Pylons Screenshot" title="Pylons Screenshot" width="877" height="830" class="alignnone size-full wp-image-226" /></a></p>
<p>Along with view environment info, complete source code of running file and template, and more.</p>
<p><strong>Wrapping it up</strong></p>
<p>I normally would have a strong aversion to &#8220;glue&#8221; frameworks that try (usually badly) to integrate unrelated toolsets. Having said that, when I sit down and build my own framework in CherryPy, I want to use SQLAlchemy, Groovie Routes, and <a href="http://www.makotemplates.org/">Mako templates</a>. (Pylons&#8217; &#8220;webhelpers&#8221; are nice too.)</p>
<p>Pylons offers all those those tools in a bundle. Also, its mailing list is far more active. While CherryPy manages a post or two a day, Pylons has a high quality post every hour or more. I&#8217;m not saying I&#8217;m giving up on CherryPy, but if I started a project today, I would seriously consider Pylons as a more friendly alternative, even if it relies on code generation.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2009/10/18/cherrypy-v-pylons/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Patch for meld to show multiple comparisons</title>
		<link>http://kenkinder.com/2009/09/16/patch-for-meld-to-show-multiple-comparisons/</link>
		<comments>http://kenkinder.com/2009/09/16/patch-for-meld-to-show-multiple-comparisons/#comments</comments>
		<pubDate>Thu, 17 Sep 2009 00:26:38 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[diff]]></category>
		<category><![CDATA[meld]]></category>
		<category><![CDATA[patch]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=230</guid>
		<description><![CDATA[I really like meld as a visual diff tool, but I wanted to have have it show multiple comparisons at once from the commandline. In the GUI, you can create multiple tabs for multiple comparisons, but there is (was) no way to do it directly from the command line. So, I wrote a patch that [...]]]></description>
			<content:encoded><![CDATA[<p>I really like <a href="http://meld.sourceforge.net/">meld</a> as a visual diff tool, but I wanted to have have it show multiple comparisons at once from the commandline. In the GUI, you can create multiple tabs for multiple comparisons, but there is (was) no way to do it directly from the command line. So, I wrote a patch that lets you use it like this:</p>
<pre>meld spam.orig spam.mine - eggs.orig eggs.mine - pants.orig pants.mine</pre>
<p>The usage is the same as it was before, but now you can specify multiple comparisons, separated by &#8220;-&#8221;. We&#8217;ll see if the patch is accepted; I <a href="http://article.gmane.org/gmane.comp.gnome.meld.general/990">posted</a> it to the mailing list. In the meantime, you can <a title="patch for meld to support multiple files" href="http://kenkinder.com/wp-content/uploads/2009/09/meld-multiple-diffs-patch.patch">download it here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2009/09/16/patch-for-meld-to-show-multiple-comparisons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My first YouTube video&#8230;</title>
		<link>http://kenkinder.com/2009/06/12/my-first-youtube-video/</link>
		<comments>http://kenkinder.com/2009/06/12/my-first-youtube-video/#comments</comments>
		<pubDate>Fri, 12 Jun 2009 17:39:47 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=191</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/l2Fu4ZVYnd8&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/l2Fu4ZVYnd8&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2009/06/12/my-first-youtube-video/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL (MySQLdb) sessions on CherryPy</title>
		<link>http://kenkinder.com/2008/12/29/mysql-mysqldb-sessions-on-cherrypy/</link>
		<comments>http://kenkinder.com/2008/12/29/mysql-mysqldb-sessions-on-cherrypy/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 23:44:40 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[CherryPy]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQLdb]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=163</guid>
		<description><![CDATA[No such module existed, so I wrote one. Using it is pretty simple:


&#34;&#34;&#34;
Example code using mysqlsession.py
&#34;&#34;&#34;
from mysqlsession import MySQLSession
import cherrypy
import logging
&#160;
logging.basicConfig&#40;level=logging.DEBUG&#41;
&#160;
sessionInfo = &#123;
    'tools.sessions.on': True,
    'tools.sessions.storage_type': &#34;Mysql&#34;,
    'tools.sessions.connect_arguments': &#123;'db': 'sessions'&#125;,
    'tools.sessions.table_name': 'session'
&#125;
&#160;
cherrypy.config.update&#40;sessionInfo&#41;
&#160;
class HelloWorld:
    def index&#40;self&#41;:
      [...]]]></description>
			<content:encoded><![CDATA[<p>No such module existed, so I wrote one. Using it is pretty simple:</p>
<p><span id="more-163"></span></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
Example code using mysqlsession.py
&quot;&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">from</span> mysqlsession <span style="color: #ff7700;font-weight:bold;">import</span> MySQLSession
<span style="color: #ff7700;font-weight:bold;">import</span> cherrypy
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
&nbsp;
<span style="color: #dc143c;">logging</span>.<span style="color: black;">basicConfig</span><span style="color: black;">&#40;</span>level=<span style="color: #dc143c;">logging</span>.<span style="color: black;">DEBUG</span><span style="color: black;">&#41;</span>
&nbsp;
sessionInfo = <span style="color: black;">&#123;</span>
    <span style="color: #483d8b;">'tools.sessions.on'</span>: <span style="color: #008000;">True</span>,
    <span style="color: #483d8b;">'tools.sessions.storage_type'</span>: <span style="color: #483d8b;">&quot;Mysql&quot;</span>,
    <span style="color: #483d8b;">'tools.sessions.connect_arguments'</span>: <span style="color: black;">&#123;</span><span style="color: #483d8b;">'db'</span>: <span style="color: #483d8b;">'sessions'</span><span style="color: black;">&#125;</span>,
    <span style="color: #483d8b;">'tools.sessions.table_name'</span>: <span style="color: #483d8b;">'session'</span>
<span style="color: black;">&#125;</span>
&nbsp;
cherrypy.<span style="color: black;">config</span>.<span style="color: black;">update</span><span style="color: black;">&#40;</span>sessionInfo<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> HelloWorld:
    <span style="color: #ff7700;font-weight:bold;">def</span> index<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        v = cherrypy.<span style="color: black;">session</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'v'</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        cherrypy.<span style="color: black;">session</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'v'</span><span style="color: black;">&#93;</span> = v+<span style="color: #ff4500;">1</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Hello world! %s&quot;</span> <span style="color: #66cc66;">%</span> v
&nbsp;
    index.<span style="color: black;">exposed</span> = <span style="color: #008000;">True</span>
&nbsp;
cherrypy.<span style="color: black;">quickstart</span><span style="color: black;">&#40;</span>HelloWorld<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Download the module: <a href="/wp-content/uploads/2008/12/mysqlsession.py.zip">mysqlsession.py</a></p>
<p>I would publish it formally, but I&#8217;m going to see if I can just have it added to the CherryPy project.</p>
<p>UPDATE: I took out the table locking and used InnoDB select-for-update locking.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2008/12/29/mysql-mysqldb-sessions-on-cherrypy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making httplib log debug information</title>
		<link>http://kenkinder.com/2008/12/27/making-httplib-log-debug-information/</link>
		<comments>http://kenkinder.com/2008/12/27/making-httplib-log-debug-information/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 09:16:31 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[httplib]]></category>
		<category><![CDATA[logging]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=151</guid>
		<description><![CDATA[As opposed to having it print to stdout. Here&#8217;s how&#8230;


--- httplib.py.orig	2008-12-16 19:14:07.000000000 -0600
+++ httplib.py	2008-12-16 19:26:20.000000000 -0600
@@ -69,6 +69,7 @@
 import errno
 import mimetools
 import socket
+import logging
 from urlparse import urlsplit
&#160;
 try:
@@ -342,7 +343,7 @@
         # Initialize with Simple-Response defaults
         [...]]]></description>
			<content:encoded><![CDATA[<p>As opposed to having it print to stdout. Here&#8217;s how&#8230;</p>
<p><span id="more-151"></span></p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">--- httplib.py.orig	<span style="">2008</span>-<span style="">12</span>-<span style="">16</span> <span style="">19</span>:<span style="">14</span>:<span style="">07.000000000</span> -0600
<span style="color: #888822;">+++ httplib.py	<span style="">2008</span>-<span style="">12</span>-<span style="">16</span> <span style="">19</span>:<span style="">26</span>:<span style="">20.000000000</span> -0600</span>
<span style="color: #440088;">@@ -<span style="">69</span>,<span style="">6</span> +<span style="">69</span>,<span style="">7</span> @@</span>
 import errno
 import mimetools
 import socket
<span style="color: #00b000;">+import logging</span>
 from urlparse import urlsplit
&nbsp;
 try:
<span style="color: #440088;">@@ -<span style="">342</span>,<span style="">7</span> +<span style="">343</span>,<span style="">7</span> @@</span>
         # Initialize with Simple-Response defaults
         line = self.fp.readline<span style="">&#40;</span><span style="">&#41;</span>
         if self.debuglevel &gt; <span style="">0</span>:
<span style="color: #991111;">-            print &quot;reply:&quot;, repr<span style="">&#40;</span>line<span style="">&#41;</span></span>
<span style="color: #00b000;">+            logging.info<span style="">&#40;</span>&quot;reply: %r&quot; % <span style="">&#40;</span>line,<span style="">&#41;</span><span style="">&#41;</span></span>
         if not line:
             # Presumably, the server closed the connection before
             # sending a valid response.
<span style="color: #440088;">@@ -<span style="">391</span>,<span style="">7</span> +<span style="">392</span>,<span style="">7</span> @@</span>
                 if not skip:
                     break
                 if self.debuglevel &gt; <span style="">0</span>:
<span style="color: #991111;">-                    print &quot;header:&quot;, skip</span>
<span style="color: #00b000;">+                    logging.info<span style="">&#40;</span>'header: %r' % <span style="">&#40;</span>skip,<span style="">&#41;</span><span style="">&#41;</span></span>
&nbsp;
         self.status = status
         self.reason = reason.strip<span style="">&#40;</span><span style="">&#41;</span>
<span style="color: #440088;">@@ -<span style="">414</span>,<span style="">7</span> +<span style="">415</span>,<span style="">7</span> @@</span>
         self.msg = HTTPMessage<span style="">&#40;</span>self.fp, <span style="">0</span><span style="">&#41;</span>
         if self.debuglevel &gt; <span style="">0</span>:
             for hdr in self.msg.headers:
<span style="color: #991111;">-                print &quot;header:&quot;, hdr,</span>
<span style="color: #00b000;">+                logging.info<span style="">&#40;</span>'header: %r' % <span style="">&#40;</span>hdr,<span style="">&#41;</span><span style="">&#41;</span></span>
&nbsp;
         # don't let the msg keep an fp
         self.msg.fp = None
<span style="color: #440088;">@@ -<span style="">665</span>,<span style="">11</span> +<span style="">666</span>,<span style="">11</span> @@</span>
             try:
                 self.sock = socket.socket<span style="">&#40;</span>af, socktype, proto<span style="">&#41;</span>
                 if self.debuglevel &gt; <span style="">0</span>:
<span style="color: #991111;">-                    print &quot;connect: <span style="">&#40;</span>%s, %s<span style="">&#41;</span>&quot; % <span style="">&#40;</span>self.host, self.port<span style="">&#41;</span></span>
<span style="color: #00b000;">+                    logging.info<span style="">&#40;</span>&quot;connect: <span style="">&#40;</span>%s, %s<span style="">&#41;</span>&quot; % <span style="">&#40;</span>self.host, self.port<span style="">&#41;</span><span style="">&#41;</span></span>
                 self.sock.connect<span style="">&#40;</span>sa<span style="">&#41;</span>
             except socket.error, msg:
                 if self.debuglevel &gt; <span style="">0</span>:
<span style="color: #991111;">-                    print 'connect fail:', <span style="">&#40;</span>self.host, self.port<span style="">&#41;</span></span>
<span style="color: #00b000;">+                    logging.info<span style="">&#40;</span>'connect fail:', <span style="">&#40;</span>self.host, self.port<span style="">&#41;</span><span style="">&#41;</span></span>
                 if self.sock:
                     self.sock.close<span style="">&#40;</span><span style="">&#41;</span>
                 self.sock = None
<span style="color: #440088;">@@ -<span style="">702</span>,<span style="">7</span> +<span style="">703</span>,<span style="">7</span> @@</span>
         # NOTE: we DO propagate the error, though, because we cannot simply
         #       ignore the error... the caller will know if they can retry.
         if self.debuglevel &gt; <span style="">0</span>:
<span style="color: #991111;">-            print &quot;send:&quot;, repr<span style="">&#40;</span>str<span style="">&#41;</span></span>
<span style="color: #00b000;">+            logging.info<span style="">&#40;</span>&quot;send: %s&quot; % <span style="">&#40;</span>str,<span style="">&#41;</span><span style="">&#41;</span></span>
         try:
             self.sock.sendall<span style="">&#40;</span>str<span style="">&#41;</span>
         except socket.error, v:</pre></div></div>

<p><a href='http://kenkinder.com/wp-content/uploads/2008/12/httplib-logging-patch.diff'>httplib-logging-patch</a></p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2008/12/27/making-httplib-log-debug-information/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Worst lock acquisition code ever.</title>
		<link>http://kenkinder.com/2008/11/24/worst-lock-acquisition-code-ever/</link>
		<comments>http://kenkinder.com/2008/11/24/worst-lock-acquisition-code-ever/#comments</comments>
		<pubDate>Tue, 25 Nov 2008 05:27:01 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Bugs]]></category>
		<category><![CDATA[CherryPy]]></category>

		<guid isPermaLink="false">/?p=82</guid>
		<description><![CDATA[Courtesy of CherryPy:

while True:
    try:
        lockfd = os.open&#40;path, os.O_CREAT&#124;os.O_WRONLY&#124;os.O_EXCL&#41;
    except OSError:
        time.sleep&#40;0.1&#41;
    else:
        os.close&#40;lockfd&#41;
        break
self.locked = True

Really people, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cherrypy.org/browser/tags/cherrypy-3.1.1/cherrypy/lib/sessions.py">Courtesy of CherryPy</a>:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        lockfd = <span style="color: #dc143c;">os</span>.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>path, <span style="color: #dc143c;">os</span>.<span style="color: black;">O_CREAT</span>|os.<span style="color: black;">O_WRONLY</span>|os.<span style="color: black;">O_EXCL</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">OSError</span>:
        <span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0.1</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #dc143c;">os</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span>lockfd<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">break</span>
<span style="color: #008000;">self</span>.<span style="color: black;">locked</span> = <span style="color: #008000;">True</span></pre></div></div>

<p>Really people, really? We silently loop until an error goes away? <a href="http://groups.google.com/group/cherrypy-devel/browse_thread/thread/5c02051b151bc916?pli=1">Really</a>? </p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2008/11/24/worst-lock-acquisition-code-ever/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>The Wordy Shipmates</title>
		<link>http://kenkinder.com/2008/11/24/the-wordy-shipmates/</link>
		<comments>http://kenkinder.com/2008/11/24/the-wordy-shipmates/#comments</comments>
		<pubDate>Tue, 25 Nov 2008 05:12:33 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Books]]></category>

		<guid isPermaLink="false">/?p=79</guid>
		<description><![CDATA[In the unplanned spirit of Thanksgiving, I recently finished Sarah Vowell&#8217;s The Wordy Shipmates. Written as a cross between a history book and a mÃ©moire on the Massachusetts Bay, it&#8217;s so-named as a commentary on the Pilgrams&#8217; verbose writing style. Vowell has a bookish snarkiness that makes the book worthwhile. Read it.
]]></description>
			<content:encoded><![CDATA[<p>In the unplanned spirit of Thanksgiving, I recently finished Sarah Vowell&#8217;s <a href="http://www.amazon.com/Wordy-Shipmates-Sarah-Vowell/dp/1594489998">The Wordy Shipmates</a>. Written as a cross between a history book and a mÃ©moire on the Massachusetts Bay, it&#8217;s so-named as a commentary on the Pilgrams&#8217; verbose writing style. Vowell has a bookish snarkiness that makes the book worthwhile. Read it.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2008/11/24/the-wordy-shipmates/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Decorating your methods</title>
		<link>http://kenkinder.com/2007/03/03/decorating-your-methods/</link>
		<comments>http://kenkinder.com/2007/03/03/decorating-your-methods/#comments</comments>
		<pubDate>Sat, 03 Mar 2007 22:29:57 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">/?p=94</guid>
		<description><![CDATA[You can read about Python Decorators in the PEP like I had to, or you can just skip to the good stuff.
Python decorators are a way of modifying a function, of quickly wrapping it. They&#8217;re sort of like aspect-oriented programming, in that they let you define logic that cross-cuts methods all over your program. Here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>You can read about Python Decorators in the <a href="http://www.python.org/dev/peps/pep-0318/">PEP</a> like I had to, or you can just skip to the good stuff.</p>
<p>Python decorators are a way of modifying a function, of quickly wrapping it. They&#8217;re sort of like aspect-oriented programming, in that they let you define logic that cross-cuts methods all over your program. Here&#8217;s an example that takes a method that returns a list, and converts that list to a CSV file.</p>
<p><span id="more-94"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">csv</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">StringIO</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> list2csv<span style="color: black;">&#40;</span>func<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> wrapper<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        listValue = func<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
        fd = <span style="color: #dc143c;">StringIO</span>.<span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        writer = <span style="color: #dc143c;">csv</span>.<span style="color: black;">writer</span><span style="color: black;">&#40;</span>fd<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> row <span style="color: #ff7700;font-weight:bold;">in</span> listValue:
            writer.<span style="color: black;">writerow</span><span style="color: black;">&#40;</span>row<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> fd.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> wrapper
&nbsp;
@list2csv
<span style="color: #ff7700;font-weight:bold;">def</span> getList<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'First Name'</span>, <span style="color: #483d8b;">'Last Name'</span>,  <span style="color: #483d8b;">'Profession'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Ken'</span>,        <span style="color: #483d8b;">'Kinder'</span>,     <span style="color: #483d8b;">'Software Engineer'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'John'</span>,       <span style="color: #483d8b;">'Stewart'</span>,    <span style="color: #483d8b;">'Funny man'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Guido'</span>,      <span style="color: #483d8b;">'Van Russum'</span>, <span style="color: #483d8b;">'Smart guy'</span><span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> getList<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Results in&#8230;</p>
<pre>First Name,Last Name,Profession
Ken,Kinder,Software Engineer
John,Stewart,Funny man
Guido,Van Russum,Smart guy</pre>
<p>Now, you may have seen a few decorators that take keyword arguments, and look like this:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="python" style="font-family:monospace;">@list2csv<span style="color: black;">&#40;</span>dialect=<span style="color: #dc143c;">csv</span>.<span style="color: black;">exel</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> getList<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'First Name'</span>, <span style="color: #483d8b;">'Last Name'</span>,  <span style="color: #483d8b;">'Profession'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Ken'</span>,        <span style="color: #483d8b;">'Kinder'</span>,     <span style="color: #483d8b;">'Software Engineer'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'John'</span>,       <span style="color: #483d8b;">'Stewart'</span>,    <span style="color: #483d8b;">'Funny man'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Guido'</span>,      <span style="color: #483d8b;">'Van Russum'</span>, <span style="color: #483d8b;">'Smart guy'</span><span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>If you&#8217;re like me, you&#8217;re tempted to just add a keyword argument, dialect, to the list2csv method. But what&#8217;s important to keep in mind is that the text after the @ in your decoration <em>is evaluated to being</em> the decorator. In other words, <tt>@list2csv</tt> <em>is not</em> a shortcut to <tt>@list2csv()</tt>. If list2csv is called, it should return a decorator itself. Here&#8217;s how:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">csv</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">StringIO</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Tabs<span style="color: black;">&#40;</span><span style="color: #dc143c;">csv</span>.<span style="color: black;">excel</span><span style="color: black;">&#41;</span>:
    delimiter = <span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\t</span>'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> list2csv<span style="color: black;">&#40;</span>func=<span style="color: #008000;">None</span>, dialect=<span style="color: #483d8b;">'excel'</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> func <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #008000;">None</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> _: list2csv<span style="color: black;">&#40;</span>_, dialect<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> wrapper<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>:
        listValue = func<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kwargs<span style="color: black;">&#41;</span>
        fd = <span style="color: #dc143c;">StringIO</span>.<span style="color: #dc143c;">StringIO</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        writer = <span style="color: #dc143c;">csv</span>.<span style="color: black;">writer</span><span style="color: black;">&#40;</span>fd, dialect<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> row <span style="color: #ff7700;font-weight:bold;">in</span> listValue:
            writer.<span style="color: black;">writerow</span><span style="color: black;">&#40;</span>row<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> fd.<span style="color: black;">getvalue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> wrapper
&nbsp;
@list2csv<span style="color: black;">&#40;</span>dialect=Tabs<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> getList<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span>
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'First Name'</span>, <span style="color: #483d8b;">'Last Name'</span>,  <span style="color: #483d8b;">'Profession'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Ken'</span>,        <span style="color: #483d8b;">'Kinder'</span>,     <span style="color: #483d8b;">'Software Engineer'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'John'</span>,       <span style="color: #483d8b;">'Stewart'</span>,    <span style="color: #483d8b;">'Funny man'</span><span style="color: black;">&#41;</span>,
        <span style="color: black;">&#40;</span><span style="color: #483d8b;">'Guido'</span>,      <span style="color: #483d8b;">'Van Russum'</span>, <span style="color: #483d8b;">'Smart guy'</span><span style="color: black;">&#41;</span>
        <span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> getList<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>This is a trick that lets you pass keyword arguments to the decorator. Notice lines 8 and 9, then 20. When this method is the called with a function, it behaves as normal, otherwise it returns a lambda to itself, with the arguments already specified.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2007/03/03/decorating-your-methods/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
