<?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, 14 Jun 2010 22:27:25 +0000</lastBuildDate>
	
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>How to split a string csv-style in Python</title>
		<link>http://kenkinder.com/2010/06/14/how-to-split-a-string-csv-style-in-python/</link>
		<comments>http://kenkinder.com/2010/06/14/how-to-split-a-string-csv-style-in-python/#comments</comments>
		<pubDate>Mon, 14 Jun 2010 22:26:22 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[csv]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=323</guid>
		<description><![CDATA[So, this is easy:

&#62;&#62;&#62; 'foo,bar'.split&#40;','&#41;
&#91;'foo', 'bar'&#93;

But here&#8217;s the problem:

&#62;&#62;&#62; &#34;foo,bar,'spam,eggs'&#34;.split&#40;','&#41;
&#91;'foo', 'bar', &#34;'spam&#34;, &#34;eggs'&#34;&#93;

Sometimes you want a csv-style split without the hassle of actually using Python&#8217;s otherwise excellent full-blown csv parser module.
So I wrote something that lets you do this:

&#62;&#62;&#62; from csvsplit import csvsplit
&#62;&#62;&#62; csvsplit&#40;'foo,bar,&#34;spam,eggs&#34;'&#41;
&#91;'foo', 'bar', 'spam,eggs'&#93;
&#62;&#62;&#62; csvsplit&#40;'foo,bar,&#34;spam,eggs&#34;', delimiter='\t'&#41;
&#91;'foo,bar,&#34;spam,eggs&#34;'&#93;
&#62;&#62;&#62; csvsplit&#40;'foo\tbar\t&#34;spam\t\teggs&#34;', delimiter='\t'&#41;
&#91;'foo', 'bar', 'spam\t\teggs'&#93;

Download it here. Enjoy!
]]></description>
			<content:encoded><![CDATA[<p>So, this is easy:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">'foo,bar'</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">','</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span>, <span style="color: #483d8b;">'bar'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>But here&#8217;s the problem:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;foo,bar,'spam,eggs'&quot;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">','</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span>, <span style="color: #483d8b;">'bar'</span>, <span style="color: #483d8b;">&quot;'spam&quot;</span>, <span style="color: #483d8b;">&quot;eggs'&quot;</span><span style="color: black;">&#93;</span></pre></div></div>

<p>Sometimes you want a csv-style split without the hassle of actually using Python&#8217;s otherwise excellent full-blown <a href="http://docs.python.org/library/csv.html">csv parser module</a>.</p>
<p>So I wrote something that lets you do this:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> csvsplit <span style="color: #ff7700;font-weight:bold;">import</span> csvsplit
<span style="color: #66cc66;">&gt;&gt;&gt;</span> csvsplit<span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo,bar,&quot;spam,eggs&quot;'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span>, <span style="color: #483d8b;">'bar'</span>, <span style="color: #483d8b;">'spam,eggs'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> csvsplit<span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo,bar,&quot;spam,eggs&quot;'</span>, delimiter=<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\t</span>'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo,bar,&quot;spam,eggs&quot;'</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> csvsplit<span style="color: black;">&#40;</span><span style="color: #483d8b;">'foo<span style="color: #000099; font-weight: bold;">\t</span>bar<span style="color: #000099; font-weight: bold;">\t</span>&quot;spam<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>eggs&quot;'</span>, delimiter=<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\t</span>'</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'foo'</span>, <span style="color: #483d8b;">'bar'</span>, <span style="color: #483d8b;">'spam<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>eggs'</span><span style="color: black;">&#93;</span></pre></div></div>

<p><a href="http://kenkinder.com/wp-content/uploads/2010/06/csvsplit.zip">Download it here</a>. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2010/06/14/how-to-split-a-string-csv-style-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thoughts on Steve Jobs&#8217; Thoughts on Flash</title>
		<link>http://kenkinder.com/2010/04/29/thoughts-on-steve-jobs-thoughts-on-flash/</link>
		<comments>http://kenkinder.com/2010/04/29/thoughts-on-steve-jobs-thoughts-on-flash/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 00:55:56 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[iPhone]]></category>
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=314</guid>
		<description><![CDATA[It&#8217;s cute how Mac and Windows users hate Flash. They don&#8217;t know how good they have it. The Linux implementation of Flash is worse. It&#8217;s like a blink-tag plugin for your browser that crashes everything it touches and pegs your CPU to 100% only to deliver choppy, unsynchronized video. It just really blows. A lot. [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s cute how Mac and Windows users hate Flash. They don&#8217;t know how good they have it. The Linux implementation of Flash is worse. It&#8217;s like a blink-tag plugin for your browser that crashes everything it touches and pegs your CPU to 100% only to deliver choppy, unsynchronized video. It just really blows. A lot. I hate Flash. A lot. It&#8217;s not just that I think it&#8217;s bad technology, it&#8217;s weirdly personal. And yet, as much as I hate Flash, I was a little annoyed by Steve Jobs&#8217; <a href="http://www.apple.com/hotnews/thoughts-on-flash/">pithy defense of Apple keeping Flash off the iPhone</a>. Here&#8217;s why:</p>
<p><span id="more-314"></span></p>
<p>I&#8217;ll start, as a lonely developer with no real following, by saying that I agree with Steve Jobs about Flash. I wouldn&#8217;t <em>package</em> it on the iPhone either and I haven&#8217;t installed it on my Nexus One, nor do I plan to. But having said that, there&#8217;s still a certain elitism and entitlement that Jobs needs to be called out on, and I hope I&#8217;m not alone in thinking this. Jobs starts by mentioning that Flash is proprietary, and while Apple releases proprietary things too (you think?), they, according to Jobs, prefer open standards:</p>
<blockquote><p>Apple even creates open standards for the web. For example, Apple began  with a small open source project and created WebKit, a complete  open-source HTML5 rendering engine that is the heart of the Safari web  browser used in all our products. WebKit has been widely adopted. Google  uses it for Android’s browser, Palm uses it, Nokia uses it, and RIM  (Blackberry) has announced they will use it too. Almost every smartphone  web browser other than Microsoft’s uses WebKit. By making its WebKit  technology open, Apple has set the standard for mobile web browsers.</p></blockquote>
<p>Except, here&#8217;s the thing. Apple did not create WebKit. They based it on <a href="http://en.wikipedia.org/wiki/KHTML">KHTML</a> which is LGPL. They were <em>required by law</em> to keep it Open Source. More importantly, Jobs praises the HTML5 standard as the future for bringing video to the web. I look forward to that day myself, but I&#8217;m troubled that the biggest threat to HTML5 isn&#8217;t Adobe, but Apple. Steve writes,</p>
<blockquote><p>To achieve long battery life when playing video, mobile devices must  decode the video in hardware; decoding it in software uses too much  power. Many of the chips used in modern mobile devices contain a decoder  called H.264 – an industry standard that is used in every Blu-ray DVD  player and has been adopted by Apple, Google (YouTube), Vimeo, Netflix  and many other companies.</p></blockquote>
<p>That&#8217;s great and all but H.264 is a closed codec and Apple&#8217;s the <em>only</em> browser house that has committed to <em>only</em> implement H.264, not the standardsy alternative, Ogg Theora. That is to say, not only is Apple supporting the closed codec, but they&#8217;ve refused to support an open one, even though doing so would cost them almost nothing in terms of development time. Apple is a member of the MPEG group, which collects royalties on H.264, so that might explain their motivation. Google, by contrast, acquired VP8 to help bridge the divide.</p>
<p>Regarding developers, Steve continues,</p>
<blockquote><p>We know from painful experience that letting a third party layer of software come between the platform and the developer ultimately results in sub-standard apps and hinders the enhancement and progress of the platform. If developers grow dependent on third party development libraries and tools, they can only take advantage of platform enhancements if and when the third party chooses to adopt the new features. We cannot be at the mercy of a third party deciding if and when they will make our enhancements available to our developers.</p></blockquote>
<p>It&#8217;s certainly true that natively developed apps are usually better. Most cross-platform technologies are themselves meta-platforms that are, at best, inconsistent with the rest of the environment (Java&#8217;s GUI toolkit comes to mind). But barring third party developers from using cross-platform tools because those tools might not implement all of Apple&#8217;s new features is nonsensical. Even using Apple&#8217;s own SDK, developers might take their time in updating their applications, or they may not use Apple&#8217;s new APIs <em>at all</em>. Will Apple ban all apps that aren&#8217;t using enough new API calls?</p>
<p>Apple isn&#8217;t defending its right to innovate, but rather, it&#8217;s quashing everyone else&#8217;s right to innovate on the iPhone platform. There will be fewer non-native apps on the Apple Store, but that just means there will be fewer apps <em>period</em>. Hardly a win for users.</p>
<p>Finally, Steve writes,</p>
<blockquote><p>Flash was designed for PCs using mice, not for touch screens using  fingers. For example, many Flash websites rely on “rollovers”, which pop  up menus or other elements when the mouse arrow hovers over a specific  spot. Apple’s revolutionary multi-touch interface doesn’t use a mouse,  and there is no concept of a rollover. Most Flash websites will need to  be rewritten to support touch-based devices. If developers need to  rewrite their Flash websites, why not use modern technologies like  HTML5, CSS and JavaScript?</p></blockquote>
<p>So are web sites that use <em>onmouseover</em> not allowed on the iPhone?</p>
<p>Flash is a bad piece of software. It&#8217;s proprietary, slow, buggy, and just plain bad. But users have a right to install it if they want. I&#8217;m most troubled by sentences like this:</p>
<blockquote><p>We don’t want to reduce the reliability and security of <strong>our</strong> iPhones,  iPods and iPads by adding Flash.</p></blockquote>
<p>But they aren&#8217;t <em>your</em> iPhones, iPods, and iPads. They&#8217;re bought, not leased, and they belong to the users who paid for them. And if you own a device, you should have the right to decide what software it runs without having to &#8220;jailbreak&#8221; it.</p>
<p>That&#8217;s why I bought a Nexus One. If I want to install apps that aren&#8217;t available on the Android Market, I can do that with one touch. If I want to install a third party ROM, I&#8217;m simply warned that doing so will void my warranty (Google made no attempts to prevent you from doing this). I feel like I own the device. And I do. iPhone users should enjoy the same privilege of controlling their computing own destinies.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2010/04/29/thoughts-on-steve-jobs-thoughts-on-flash/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>In search of the perfect HTC Dream/G1 Android ROM</title>
		<link>http://kenkinder.com/2010/04/17/in-search-of-the-perfect-htc-dreamg1-android-rom/</link>
		<comments>http://kenkinder.com/2010/04/17/in-search-of-the-perfect-htc-dreamg1-android-rom/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 17:02:59 +0000</pubDate>
		<dc:creator>Ken Kinder</dc:creator>
				<category><![CDATA[Gadgets]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://kenkinder.com/?p=307</guid>
		<description><![CDATA[I&#8217;m in search of the perfect ROM for my phone. A ROM not for hackers, but also not for people who don&#8217;t know what a ROM is. A ROM that doesn&#8217;t expand on the stock ROM besides adding what should have been there anyway, like root and tethering. Users like me don&#8217;t need third party [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m in search of the perfect ROM for my phone. A ROM not for hackers, but also not for people who don&#8217;t know what a ROM is. A ROM that doesn&#8217;t expand on the stock ROM besides adding what should have been there anyway, like root and tethering. Users like me don&#8217;t need third party multi-touch modules, support for extra filesystems, or ipv6 before the stock ROM has those features. But we do prefer to own our phones with root, instead of &#8220;borrowing&#8221; phones from the manufacturer. (If you don&#8217;t have root, you don&#8217;t really own the device.)</p>
<p>Most of the ROMs on <a href="http://forum.xda-developers.com">xda-developers</a> are one-off builds from hackers who are experimenting. I don&#8217;t want to experiment &#8212; I&#8217;m looking for less Slackware, more Ubuntu on my phone. Over a year ago, I installed <a href="http://www.cyanogenmod.com/">CyanogenMod</a>, as it seemed like the most consumer-friendly ROM out there. For one, instead of a poorly formatted posting on xda-developers, it has an actual website. It also boasts an automatic updater, lots of nice features like tethering and a caller blacklist, and even a stable-v-unstable build schedule.</p>
<p>Unfortunately, CyanogenMod has become increasingly unstable for me. That&#8217;s probably due to a combination of things, including Cyanogen&#8217;s unfortunate proclivity to bloat-up the stock firmware with features and experimental kernel improvements. Another cause for the problem is likely attributable to Google&#8217;s position of only <a href="http://gizmodo.com/5367420/google-threatens-cyanogen-android-hacker-with-cease+and+desist">half open sourcing</a> Android.</p>
<p>What I&#8217;m looking for is something like the stock ROM, with root, tethering, auto-update, and not much else. I don&#8217;t think it&#8217;s out there. Maybe I should figure out how hard it is to do it myself.</p>
]]></content:encoded>
			<wfw:commentRss>http://kenkinder.com/2010/04/17/in-search-of-the-perfect-htc-dreamg1-android-rom/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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>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>6</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>
	</channel>
</rss>
