<?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 &#187; Python</title>
	<atom:link href="http://kenkinder.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://kenkinder.com</link>
	<description>Ken Kinder&#039;s personal website</description>
	<lastBuildDate>Mon, 14 Jun 2010 22:27:25 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>WingIDE Colorpicker</title>
		<link>http://kenkinder.com/2010/03/28/wingide-colorpicker/</link>
		<comments>http://kenkinder.com/2010/03/28/wingide-colorpicker/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 06:14:23 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[pygtk]]></category>
		<category><![CDATA[WingIDE]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=298</guid>
		<description><![CDATA[Dun dun dun! This is a plugin for WingIDE. When editing code, I got tired of constantly googling &#8220;color picker&#8221; when I needed to make a hex color for my CSS. 


&#34;&#34;&#34;
Adds a color chooser to WingIDE.
&#160;
Copyright (c) 2010, Ken Kinder All rights reserved.
&#160;
Permission is hereby granted, free of charge, to any person obtaining
a copy [...]]]></description>
			<content:encoded><![CDATA[<p>Dun dun dun! This is a plugin for <a href="http://www.wingide.com/">WingIDE</a>. When editing code, I got tired of constantly googling &#8220;color picker&#8221; when I needed to make a hex color for my CSS. </p>
<p><span id="more-298"></span></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;
Adds a color chooser to WingIDE.
&nbsp;
Copyright (c) 2010, Ken Kinder All rights reserved.
&nbsp;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
&quot;Software&quot;), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
&nbsp;
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
&nbsp;
THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> guiutils <span style="color: #ff7700;font-weight:bold;">import</span> wgtk <span style="color: #ff7700;font-weight:bold;">as</span> gtk
<span style="color: #ff7700;font-weight:bold;">import</span> wingapi
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> _getclipboard<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    editor = wingapi.<span style="color: black;">gApplication</span>.<span style="color: black;">GetActiveEditor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    doc = editor.<span style="color: black;">GetDocument</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    start, end = editor.<span style="color: black;">GetSelection</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> doc.<span style="color: black;">GetCharRange</span><span style="color: black;">&#40;</span>start, end<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> _setclipboard<span style="color: black;">&#40;</span>txt<span style="color: black;">&#41;</span>:
    editor = wingapi.<span style="color: black;">gApplication</span>.<span style="color: black;">GetActiveEditor</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    doc = editor.<span style="color: black;">GetDocument</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    start, end = editor.<span style="color: black;">GetSelection</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    doc.<span style="color: black;">BeginUndoAction</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        doc.<span style="color: black;">DeleteChars</span><span style="color: black;">&#40;</span>start, end-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
        doc.<span style="color: black;">InsertChars</span><span style="color: black;">&#40;</span>start, txt<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">finally</span>:
        doc.<span style="color: black;">EndUndoAction</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> colorpicker<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    w = gtk.<span style="color: black;">ColorSelectionDialog</span><span style="color: black;">&#40;</span>title=<span style="color: #483d8b;">&quot;Color Picker&quot;</span><span style="color: black;">&#41;</span>
    w.<span style="color: black;">colorsel</span>.<span style="color: black;">set_has_palette</span><span style="color: black;">&#40;</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> _getclipboard<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        w.<span style="color: black;">colorsel</span>.<span style="color: black;">set_current_color</span><span style="color: black;">&#40;</span>gtk.<span style="color: black;">gdk</span>.<span style="color: black;">color_parse</span><span style="color: black;">&#40;</span>_getclipboard<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    response = w.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> response == gtk.<span style="color: black;">RESPONSE_OK</span>:
        r = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'%02X'</span> <span style="color: #66cc66;">%</span> w.<span style="color: black;">colorsel</span>.<span style="color: black;">get_current_color</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">red</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
        g = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'%02X'</span> <span style="color: #66cc66;">%</span> w.<span style="color: black;">colorsel</span>.<span style="color: black;">get_current_color</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">green</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
        b = <span style="color: black;">&#40;</span><span style="color: #483d8b;">'%02X'</span> <span style="color: #66cc66;">%</span> w.<span style="color: black;">colorsel</span>.<span style="color: black;">get_current_color</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">blue</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
        _setclipboard<span style="color: black;">&#40;</span><span style="color: #483d8b;">'#%s%s%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>r, g, b<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    w.<span style="color: black;">hide</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    w.<span style="color: black;">destroy</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Dump this code in a file in your <tt>~/.wingide3/scripts</tt> directory, run reload-scripts, and you have a <tt>colorpicker</tt> command. It will show a gtk color picker and insert that color in your code in <tt>#rrggbb</tt> format. If you have a color selected in your buffer at the time you invoke the command, it will be parsed, be the default in the editor, and replaced when you&#8217;re done.</p>
<p>It doesn&#8217;t add any menu items. You just have to use the command directly or add your on shortcuts.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2010/03/28/wingide-colorpicker/feed/</wfw:commentRss>
		<slash:comments>0</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>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>
	</channel>
</rss>
