<?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>Mike&#039;s Blabberings &#187; python</title>
	<atom:link href="http://www.mike-griffith.com/blog/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mike-griffith.com/blog</link>
	<description>on software, testing, and the web.</description>
	<lastBuildDate>Tue, 29 Jun 2010 14:37:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Python decorators, SRP, and testability</title>
		<link>http://www.mike-griffith.com/blog/2010/06/python-decorators-srp-and-testability/</link>
		<comments>http://www.mike-griffith.com/blog/2010/06/python-decorators-srp-and-testability/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 06:30:02 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=504</guid>
		<description><![CDATA[On the SRP:
For those unfamiliar with the Single Responsibility Principle (SRP), it states that there should never be more than one reason for a class to change.
That is to say: do one thing, do it well.
Decorators (not to be confused with the decorator pattern) can add behaviors or side-effects to a method, and this can [...]]]></description>
			<content:encoded><![CDATA[<p><strong>On the SRP:</strong><br />
For those unfamiliar with the <a href="http://www.butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod" target="_blank">Single Responsibility Principle</a> (SRP), it states that <em>there should never be more than one reason for a class to change</em>.</p>
<p>That is to say: do one thing, do it well.</p>
<p><a href="http://www.python.org/dev/peps/pep-0318/" target="_blank">Decorators</a> (not to be confused with the <a href="http://en.wikipedia.org/wiki/Decorator_pattern" target="_blank">decorator pattern</a>) can add behaviors or side-effects to a method, and this can be dangerous.  It seems harmless, because by adding a decorator, you&#8217;re likely taking boilerplate code and shuffling it elsewhere.  However, they often encourage badness because of how easy it is to add these behaviors.</p>
<p><strong>On testing decorated methods:</strong></p>
<p>Adding an @decorator to a python object unarguably makes the undecorated code difficult to test in isolation.  Decorators are applied at compile-time, and cannot be mocked or made to not-execute without some pain.</p>
<p>There are certainly a few common tricks that can help test a decorated method with minimal side-effects, but they require changes to the decorator itself.  There&#8217;s just plain and simple no way to un-decorate a method for isolated testing.</p>
<p><strong>Let&#8217;s look at a few common examples:</strong></p>
<p><strong><em>@expose</em></strong>: register a URL for a view function in a web framework</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> BlogPostController<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    @expose<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/blog/{post_id}&quot;</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>, request, post_id=<span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; show a blog post &quot;&quot;&quot;</span>
        post = adapter.<span style="color: black;">get_post</span><span style="color: black;">&#40;</span>post_id<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> render<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;show_entry.html&quot;</span>, <span style="color: #008000;">dict</span><span style="color: black;">&#40;</span>post=post<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Without the `@expose`, your `show_entry` knows how to get a given post and render it in the proper template.  With the decorator, it also now knows which URL corresponds to that.  You now have multiple reasons for this block of code to change, including pointing to a different URL or using a different template.  It&#8217;s preferred to have a separate module for managing which urls point to which views.</p>
<p>Harm factor: low.  Ick factor: medium &#8211; high.</p>
<p><strong><em>@cache</em></strong>: try to get the result from memcache, otherwise, execute the function and stick it in cache for next time</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> PostAdapter<span style="color: black;">&#40;</span>DataAdapter<span style="color: black;">&#41;</span>:
    @cache
    <span style="color: #ff7700;font-weight:bold;">def</span> get_post<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, post_id<span style="color: black;">&#41;</span>
        <span style="color: #483d8b;">&quot;&quot;&quot; grab a blog post from the database &quot;&quot;&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">query</span><span style="color: black;">&#40;</span>Post<span style="color: black;">&#41;</span>.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #008000;">id</span>=post_id<span style="color: black;">&#41;</span>.<span style="color: black;">one</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># SQLAlchemy folks need to talk to Mr Demeter...</span></pre></div></div>

<p>OK this seems cool right?  You only hit the database when you have to, otherwise we get it even quicker by looking it up in the cache.</p>
<p>What happens if you want to disable caching?  A separate cache abstraction layer would reduce volatility in your data adapter.</p>
<p>And what does the unit test look like?</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> TestGettingAPost<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> setup<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">query</span> = Mock<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;">#don't hit the production database!</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">post_adapter</span> = PostAdapter<span style="color: black;">&#40;</span>query=<span style="color: #008000;">self</span>.<span style="color: black;">query</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> test_getting_a_post<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;">assert</span> <span style="color: #008000;">self</span>.<span style="color: black;">post_adapter</span>.<span style="color: black;">get_post</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">123</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Damn, there&#8217;s no way to mock out the @cache decorator so it doesn&#8217;t run.  Try to, I dare you.  You&#8217;re likely going to actually get post 123 from your production memcache.  Crappy.  The only thing you can do is make the @cache grab the cache implementation from the PostAdapter instance (and mock that out in you test), or find some other sneaky way of disabling caching for test runs.  But the @cache decorator isn&#8217;t all self-contained and fun anymore.</p>
<p>Harm factor: medium &#8211; high.</p>
<p><strong><em>@validate</em></strong>: Make sure the request matches the specified schema, otherwise hand-off to error handler</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> EditPostController<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> _save_error<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request, errors<span style="color: black;">&#41;</span>:
        <span style="color: #483d8b;">&quot;&quot;&quot; @validate decorator kicked flow here, redisplay edit page with errors &quot;&quot;&quot;</span>
        ...
    @validate<span style="color: black;">&#40;</span>schema, error_handler=_save_error<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> save<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, request<span style="color: black;">&#41;</span>
        post = <span style="color: #008000;">self</span>.<span style="color: black;">schema</span>.<span style="color: black;">to_python</span><span style="color: black;">&#40;</span>request.<span style="color: black;">params</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">post_adapter</span>.<span style="color: black;">save_post</span><span style="color: black;">&#40;</span>post<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> redirect<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;/blog/{0}&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>post_id<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Without this @validate, there would be a lot of boilerplate code inside the `save` method.  With it, any unit test for the save method will be likely linked to your schema.  You&#8217;d have to make an actual valid request in order to test this method.  That&#8217;s outside of any tests for your schema directly. That means double-coverage but 2 tests to update when requirements shift.</p>
<p>Harm factor: low-medium</p>
<p><strong>Conclusions (or tl;dr):</strong></p>
<p>As easy as it is to become infatuated with Python decorators, they definitely encourage you to violate the SRP.  This can create a myriad of problems:</p>
<ul>
<li>Difficultly in isolating system under test</li>
<li>Added complexity to enable testing</li>
<li>Redundant redundant unit tests</li>
<li>Making a code module more volatile than it ought to</li>
</ul>
<p>They still have some valid use cases and can lead to cleaner code, however,  as Master Yoda once said, &#8220;when you look at the dark side, careful you must be&#8230;&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2010/06/python-decorators-srp-and-testability/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Batch convert images to sepia tone with python</title>
		<link>http://www.mike-griffith.com/blog/2010/01/batch-convert-images-to-sepia-tone-with-python/</link>
		<comments>http://www.mike-griffith.com/blog/2010/01/batch-convert-images-to-sepia-tone-with-python/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 03:49:20 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[photography]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[tips & tricks]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=329</guid>
		<description><![CDATA[The Python Imaging Library (PIL) offers easy photo manipulation from python scripts.  There&#8217;s some handy sample code on effbot.org that demonstrates how to alter an image&#8217;s palette to generate a sepia tone effect.  It first desaturates the image, then applies a new palette based on a linear ramp.
I&#8217;ve cleanup up that sample code [...]]]></description>
			<content:encoded><![CDATA[<p>The Python Imaging Library (PIL) offers easy photo manipulation from python scripts.  There&#8217;s some handy <a href="http://effbot.org/zone/pil-sepia.htm" target="_blank">sample code on effbot.org</a> that demonstrates how to alter an image&#8217;s palette to generate a sepia tone effect.  It first desaturates the image, then applies a new palette based on a linear ramp.</p>
<p>I&#8217;ve cleanup up that sample code and tucked it into a script.  You can pass a list of files to the script, and it will apply a sepia effect to each, making sure to backup the originals.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
<span style="color: #483d8b;">&quot;&quot;&quot;
Apply sepia filter in batch to images
&nbsp;
Usage:
    python batch_sepia.py [--no-backup] file1 [file2] ...
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> Image <span style="color: #ff7700;font-weight:bold;">as</span> PIL_Image
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">shutil</span>, <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">optparse</span> <span style="color: #ff7700;font-weight:bold;">import</span> OptionParser
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> open_image<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; grab a PIL image from the given location
    &quot;&quot;&quot;</span>
    image = PIL_Image.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>
    image.<span style="color: black;">load</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> image
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> save_image<span style="color: black;">&#40;</span>image, filename, quality=<span style="color: #ff4500;">95</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; save the PIL image to disk
    &quot;&quot;&quot;</span>
    image.<span style="color: black;">save</span><span style="color: black;">&#40;</span>filename, <span style="color: #483d8b;">&quot;JPEG&quot;</span>, quality=quality<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> make_linear_ramp<span style="color: black;">&#40;</span>white<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; generate a palette in a format acceptable for `putpalette`, which
        expects [r,g,b,r,g,b,...]
    &quot;&quot;&quot;</span>
    ramp = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    r, g, b = white
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">255</span><span style="color: black;">&#41;</span>:
        ramp.<span style="color: black;">extend</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>r<span style="color: #66cc66;">*</span>i/<span style="color: #ff4500;">255</span>, g<span style="color: #66cc66;">*</span>i/<span style="color: #ff4500;">255</span>, b<span style="color: #66cc66;">*</span>i/<span style="color: #ff4500;">255</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> ramp
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> apply_sepia_filter<span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; Apply a sepia-tone filter to the given PIL Image
        Based on code at: http://effbot.org/zone/pil-sepia.htm
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># make sepia ramp (tweak color as necessary)</span>
    sepia = make_linear_ramp<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">255</span>, <span style="color: #ff4500;">240</span>, <span style="color: #ff4500;">192</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># convert to grayscale</span>
    orig_mode = image.<span style="color: black;">mode</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> orig_mode <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">&quot;L&quot;</span>:
        image = image.<span style="color: black;">convert</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;L&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># optional: apply contrast enhancement here, e.g.</span>
    <span style="color: #808080; font-style: italic;">#image = ImageOps.autocontrast(image)</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># apply sepia palette</span>
    image.<span style="color: black;">putpalette</span><span style="color: black;">&#40;</span>sepia<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># convert back to its original mode</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> orig_mode <span style="color: #66cc66;">!</span>= <span style="color: #483d8b;">&quot;L&quot;</span>:
        image = image.<span style="color: black;">convert</span><span style="color: black;">&#40;</span>orig_mode<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">return</span> image
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> convert_image<span style="color: black;">&#40;</span>filename, make_backup<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; convert an image at the given path to sepia tone.
        @param filename
        @param make_backup - if True, will copy original file to file.bak
    &quot;&quot;&quot;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">exists</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Skipping %s'</span> <span style="color: #66cc66;">%</span> filename
        <span style="color: #ff7700;font-weight:bold;">return</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Processing %s...'</span> <span style="color: #66cc66;">%</span> filename
    <span style="color: #ff7700;font-weight:bold;">if</span> make_backup:
        <span style="color: #dc143c;">shutil</span>.<span style="color: black;">copyfile</span><span style="color: black;">&#40;</span>filename, <span style="color: #483d8b;">'%s.bak'</span> <span style="color: #66cc66;">%</span> filename<span style="color: black;">&#41;</span>
    save_image<span style="color: black;">&#40;</span>apply_sepia_filter<span style="color: black;">&#40;</span>open_image<span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>, filename<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">'Done.'</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> convert_images<span style="color: black;">&#40;</span>files, make_backup=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot; convert the list of filenames to sepia tone.
        @param filename
        @param make_backup - if True, will copy original file to file.bak
    &quot;&quot;&quot;</span>
    <span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> f: convert_image<span style="color: black;">&#40;</span>f, make_backup<span style="color: black;">&#41;</span>, files<span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #dc143c;">parser</span> = OptionParser<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">parser</span>.<span style="color: black;">add_option</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;-x&quot;</span>, <span style="color: #483d8b;">&quot;--no-backup&quot;</span>, dest=<span style="color: #483d8b;">&quot;no_backup&quot;</span>, default=<span style="color: #008000;">False</span>,
            action=<span style="color: #483d8b;">&quot;store_true&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: black;">&#40;</span>options, files<span style="color: black;">&#41;</span> = <span style="color: #dc143c;">parser</span>.<span style="color: black;">parse_args</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    convert_images<span style="color: black;">&#40;</span>files, make_backup=<span style="color: #ff7700;font-weight:bold;">not</span> options.<span style="color: black;">no_backup</span><span style="color: black;">&#41;</span></pre></div></div>

<p>You can execute this from the command line as:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python batch_sepia.py image1.jpg image2.jpg image3.jpg</pre></div></div>

<p>If you want to recursively apply the filter to a bunch of images, you might consider mixing this with some find/xargs-fu:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">find</span> <span style="color: #007800;">$HOME</span><span style="color: #000000; font-weight: bold;">/</span>pictures <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.jpg&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">xargs</span> python batch_sepia.py</pre></div></div>

<p>Once you&#8217;ve got your photos in order, head over to <a href="http://www.photoworks.com" target="_blank">photoworks.com</a> to get them printed!&lt;/shameless-plug&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2010/01/batch-convert-images-to-sepia-tone-with-python/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>VIM Tip of the Day: leave python comments indented, don&#8217;t put cursor at beginning of the line</title>
		<link>http://www.mike-griffith.com/blog/2009/05/vim-tip-of-the-day-leave-python-comments-indented-dont-put-cursor-at-beginning-of-the-line/</link>
		<comments>http://www.mike-griffith.com/blog/2009/05/vim-tip-of-the-day-leave-python-comments-indented-dont-put-cursor-at-beginning-of-the-line/#comments</comments>
		<pubDate>Fri, 15 May 2009 17:18:32 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tips & tricks]]></category>
		<category><![CDATA[vim]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=305</guid>
		<description><![CDATA[If you&#8217;re ever been annoyed by VIM throwing your cursor to the left margin when you type &#8220;#&#8221; in a python file, there&#8217;s a simple remedy.  It&#8217;s the fault of &#8220;smartindent&#8221; in VIM, which in reality isn&#8217;t all that smart.  If you want to leave smartindent on but fix the weird hash behavior, [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;re ever been annoyed by VIM throwing your cursor to the left margin when you type &#8220;#&#8221; in a python file, there&#8217;s a simple remedy.  It&#8217;s the fault of &#8220;smartindent&#8221; in VIM, which in reality isn&#8217;t all that smart.  If you want to leave smartindent on but fix the weird hash behavior, throw the following in your $HOME/.vimrc.</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">:inoremap # X&lt;C-H&gt;#</pre></div></div>

<p>See <a href="http://vim.wikia.com/wiki/Restoring_indent_after_typing_hash">http://vim.wikia.com/wiki/Restoring_indent_after_typing_hash</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/05/vim-tip-of-the-day-leave-python-comments-indented-dont-put-cursor-at-beginning-of-the-line/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Notes from PyCon 2009</title>
		<link>http://www.mike-griffith.com/blog/2009/03/notes-from-pycon-2009/</link>
		<comments>http://www.mike-griffith.com/blog/2009/03/notes-from-pycon-2009/#comments</comments>
		<pubDate>Sun, 29 Mar 2009 21:24:56 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[pycon]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=299</guid>
		<description><![CDATA[Just wrapping up a fantastic few days at PyCon Chicago 2009.  I went with a group of about 10 guys from AGI, and we managed to have a little bit of fun in between some great mind-enriching talks.
Here are some notes I jotted down while at the conference.  It&#8217;s a bit overwhelming, but [...]]]></description>
			<content:encoded><![CDATA[<p>Just wrapping up a fantastic few days at <a href="http://us.pycon.org/2009/about/">PyCon Chicago 2009</a>.  I went with a group of about 10 guys from <a href="http://www.aginteractive.com">AGI</a>, and we managed to have a little bit of fun in between some great mind-enriching talks.</p>
<p>Here are some notes I jotted down while at the conference.  It&#8217;s a bit overwhelming, but I wanted to throw this out there for now, then I&#8217;ll come back and reorganize it.</p>
<p><strong>Tutorial: PyCon 401 &#8211; Some Advanced Topics, by Steve Holden</strong><br />
 * String interpolation<br />
 * Iterators<br />
 * Generators<br />
 * Descriptors and name lookups<br />
 * Metaclasses</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
String Interpolation<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Can use locals() trick</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> fmt<span style="color: black;">&#40;</span>date, x<span style="color: black;">&#41;</span>:
    amount = <span style="color: #ff4500;">3</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;%(date)12s $(x)-25s %(amount)8.2f&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">locals</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Iteration<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Iterable object must have next() and __iter__()<br />
 * next returns next item, or raises StopIteration<br />
 * __iter__ returns an &#8220;iterable&#8221; object (e.g. self)</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Generators<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>Any function with &#8220;yield&#8221; in it is automagically assumed to be a generator by<br />
the compiler<br />
 * Never actually return anything<br />
 * Obey the iterator protocol, and thus have a next() method</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> g<span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span>:
  <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> s:
    <span style="color: #ff7700;font-weight:bold;">yield</span> c+<span style="color: #483d8b;">'!'</span>
g1 = g<span style="color: black;">&#40;</span><span style="color: #483d8b;">'hello'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">assert</span> <span style="color: black;">&#91;</span>c <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> g1<span style="color: black;">&#93;</span> == <span style="color: black;">&#91;</span><span style="color: #483d8b;">'h!'</span>, <span style="color: #483d8b;">'e!'</span>, <span style="color: #483d8b;">'l!'</span>, <span style="color: #483d8b;">'l!'</span>, <span style="color: #483d8b;">'o!'</span><span style="color: black;">&#93;</span></pre></div></div>

<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Decorators and other cool shit<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>functools.wrap<br />
 * when making a decorator, decorate your decorator with this to preserve<br />
   &#8220;dunder_name&#8221; __name__ and dunder-doc __doc__</p>
<p>functools.partial<br />
 * copy a function to a new place and provide different kwarg defaults</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Descriptors and Properties<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>HACKATTACK: Property definition without namespace polluion<br />
 * see ~/src/sandbox/src/pycon/tests/test_property.py</p>
<p>Descriptor protocol just talks about how to look up stuff in a class<br />
 * not all that cool :-/</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Metaclasses<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>factories<br />
 * produce and return functions<br />
 * produce and return classes</p>
<p>metaclass<br />
 * can do cool shit to a class without cluttering up the class definition<br />
 * keep your classes closer to application domain model and responsibilities</p>
<p>Example metaclass: Automagically Decorate Every Method in Class<br />
 * page 35 of notes defines a Tracer class factory with __new__, that wraps<br />
   every callable, non-dundered (__x__) function with a tracing decorator<br />
 * you add a __metaclass__ attribute to your class, then when it gets spun up,<br />
   the tracer factory decorates its shit<br />
 * see ~/src/sandbox/src/pycon/tests/test_metaclass.py</p>
<p><strong>Notes from Friday</strong></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Windmill<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
in-browser, cross-browser functional testing framework<br />
 * started as fork of selenium<br />
 * great visual recorder<br />
 * dom inspector cross-browser<br />
python api<br />
continuous integration w/ hudson<br />
reporting hooks<br />
issues:<br />
 * no ssl support</p>
<p>http://www.getwindmill.com</p>
<p>LOOKS AWESOME!</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Profiling<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Optimization makes code harder to maintain<br />
But necessary sometimes because Python is slow in real world<br />
Premmature optimization is the root of all evil.  Forget about small efficiencies.  Focus on hot spots.<br />
Improve your algorithms for the 3% of worst things<br />
 * unroll loop<br />
 * add caching<br />
Use profiling to figure out which pieces are the 3%</p>
<p>track entry and exit times to functions using Timer</p>
<p>How to:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> cProfile
cProfile.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;python.swallow(gopher)&quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>? pstats.Stats(&#8216;1.profile&#8217;, &#8216;2.profile&#8217;)<br />
** not good for threaded systems&#8230; need seperate profiler per thread</p>
<p>KCacheGrind can help explore profile output (runs on wxpython)</p>
<p>Look for<br />
 * way too many calls<br />
 * large local time in single function (can be spot-optimized)<br />
 * large cumulative per call (possibly cache results)<br />
 * high waiting times (IO blocked ?)</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Testing AJAX Web Apps<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
It&#8217;s hard, and Kumar has failed.  This is just an overview of what has/hasn&#8217;t worked.</p>
<p>Example: pylons+dojo aintjustsoul.net<br />
 * ajax to fetch album thumbnails</p>
<p>Strategy:<br />
    &#8211; test data handlers (in python)<br />
    &#8211; test javascript<br />
        &#8211; lint it first for syntax errors (e.g. javascriptlint.com)<br />
        &#8211; rhino runner (perhaps with john resig&#8217;s env.js to simulate DOM)<br />
        &#8211; spidermonkey ?<br />
        &#8211; Selenium, jquery.simulate, YUI.test to simulate user events in browser<br />
    (now it gets trickier)<br />
    &#8211; isolate UI for testing<br />
        &#8211; DI your connection stuff to mock out data and use a fake server, at the<br />
          cost of a little more indirection<br />
    &#8211; automate UI tests<br />
        &#8211; selenium remote control automates browser interactions via python code<br />
    &#8211; gridify your tests<br />
        &#8211; &#8220;selenium grid&#8221; to speed up tests<br />
        &#8211; future: test swarm<br />
           &#8211; crowd sourced continuous integration<br />
            &#8211; seems like an awful security flaw</p>
<p><a href="http://bit.ly/testing-ajax">http://bit.ly/testing-ajax</a> (mailing list on google groups)</p>
<p>JSBridge can help to launch firefox from terminal<br />
 * it fakes X-server so mozilla runs but doesn&#8217;t put anything to display<br />
 * you can still run your tests in an actual browser rather than rhino&#8217;s implementation<br />
 * mozilla ubiquity plugin tested this way</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Auomated QA Infrastructure<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>Ingredients:<br />
 * VCS<br />
    &#8211; mainline branch.. merges trigger full QA battery<br />
    &#8211; devs use QA system on dev branches<br />
 * reporting<br />
    &#8211; if you don&#8217;t do this, nothing else matters<br />
    &#8211; &#8220;your QA system is ONLY as good as its reporting of results&#8221;<br />
 * tests (discovery, coverage metrics, static source analysis, performance profiling)<br />
    &#8211; discovery = nose<br />
    &#8211; coverage = figleaf<br />
    &#8211; static analysis = pylint<br />
    &#8211; profiling = ????</p>
<p>CI frameworks:<br />
 * svnchecker (svn post-commit hooks)<br />
 * bitten<br />
 * pybots<br />
 * buildbot ***** <-- best general purpose python-based open-source framework now</p>
<p>Buildbot Architecture<br />
 * master: coordinate, dispatch, report<br />
 * build slaves: runs tests as directed<br />
    - BuildFactory defines the build process<br />
    >>> factory.addStep(SVN(url))<br />
    >>> factory.addStep(Compile(command=['python', 'setup.py', 'build'])<br />
    >>> factory.addStep(nose.run()) #????<br />
            # they used Trial(testpath=&#8217;.') for Twisted<br />
    >>> factory.addStep(Figleaf(&#8230;<br />
    >>> factory.addStep(PyLint(&#8230;<br />
 * changes: encapsulates events that require testing<br />
 * schedulers: makes decisions about when/where to order tests<br />
 * pollers/triggers: signals the base change events<br />
    &#8211; built-in SVNPoller</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Twisted/MQ/RPC<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8230; (notes in moleskin) &#8230;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Testing large, untested codebases<br />
~ Titus<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>Example: biological something or other<br />
on the science background of code under test<br />
 * example: pygr &#8211; python graph database<br />
    &#8211; provides data abstration with pygr.Data<br />
 * problem in biology<br />
    &#8211; tons and tons of data, parsed lists, etc</p>
<p>on the code and authors<br />
 * da code<br />
    &#8211; ~8k of Py, ~2k of Pyrex<br />
    &#8211; almost all library and framework, no UI fluff<br />
 * the people<br />
    &#8211; written by 1 dude ==> lots of technical debt<br />
        &#8211; no tests, interface contracts, etc.<br />
    &#8211; code ownership is issue by new people that want to contribute.<br />
      don&#8217;t want to step on original author&#8217;s code<br />
    &#8211; idiosyncratic code since author was a smart dude</p>
<p>statement: code coverage is of limited utility bc it doesn&#8217;t measure branch coverage<br />
 * TITUS SAYS WRONG WRONG WRONG<br />
 * it&#8217;s not just bc it doesn&#8217;t measure branch coverage.  there are other more<br />
   valid reasons why it might be flawed</p>
<p>grokking code through coverage<br />
 * howto:<br />
     &#8211; given a big chunk o python<br />
     &#8211; import it, write test to exercise some of it, check coverage to see what it done<br />
     &#8211; add additional statement to test<br />
     &#8211; repeat<br />
 * lets you pull apart highly complex/coupled code<br />
 * </p>
<p>problem: no good way keep track of tests in a large codebase<br />
 * some things may or may not be getting run by your runner<br />
 * new project &#8220;tattle&#8221; that keeps track of master list of tests<br />
    &#8211; when running, checks the master list and if something is missing or new, it warns you<br />
    &#8211; not decided how to keep track of what&#8217;s changed<br />
        &#8211; yaml ?<br />
        &#8211; tag the source ?<br />
        &#8211; check the diff ?  (requires &#8220;saving&#8221; coverage state, then comparing on next run)</p>
<p>&#8220;for those that use nose, each additional dot is like another hit of smack&#8221;</p>
<p>code review:<br />
 * pep8<br />
 * pep257 &#8211; docstring format!!!</p>
<p>&#8220;each time you&#8217;ve pissed on another line of code, it&#8217;s like it&#8217;s yours now&#8221;</p>
<p>reformatting vs &#8220;search/replace&#8221; vs real functional changes<br />
 * what you gonna break?</p>
<p>coverage is an invaluable lever for prying into other people&#8217;s code bases</p>
<p>what&#8217;s next?<br />
 * trace code coverage between commits (and which lines are no longer covered)<br />
 * branch coverage (titus on GSoC project: &#8220;i have no idea how to do this, that&#8217;s what students are for&#8221;)<br />
 * simplify CI.  buildbot too complex</p>
<p><strong>Notes from Saturday</strong></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
!!!! LIGHTNING TALKS !!!!<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>== thestatusisnotquo.com ==<br />
@mpirnat&#8217;s socially redeeming python mini-community of hackers</p>
<p>== sqlpython ==<br />
write sql in unix command shell<br />
have access to all other cool unix stuff (grep, sed, cat, etc)</p>
<p>== webob ==<br />
presentation was cool&#8230; just played through the doctests in a<br />
fake interactive interpreter.  flawless demo FTW!</p>
<p>== DVCS ==<br />
mercurial (hg) is super easy to use<br />
statement: hg on bitbucket is better than svn on google code<br />
successful DVCS don&#8217;t really use the D<br />
but django 1.1 delayed by a month because of DVCS crap<br />
what&#8217;s the benefit:<br />
 * better merging (but shouldn&#8217;t require DVCS)<br />
 * easier repository creation (as opposed to svnadmin)<br />
svn isn&#8217;t quite dead yet (but it&#8217;s not getting better)</p>
<p>== pymite ==<br />
python on microcontrollers.. runs on 8bit devices with 64kb ram<br />
easily embed native code in docstrings</p>
<p>== web2py ==<br />
MVC web framework.  used for pycon registration.<br />
online DB admin tool ala django<br />
online python code editor<br />
integrates with bug ticketing system and links back to original stack trace<br />
templating system looks like advanced pyfusion</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Guido&#8217;s keynote<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
py3.1/2.7 coming<br />
no decision on dvcs<br />
tool to backport from py3 to py2 coming.  then we can write code in 3 and give it to the 2x world also.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
State of Django<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8230; (see moleskin) &#8230;</p>
<p>** statement: everyone should be using sphinx for technical docs **</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Lack of Design Patterns<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8220;python isn&#8217;t java without the compile&#8221;</p>
<p>define lack of patterns:<br />
 * comp.lang.python 100k messages<br />
 * visitor/flyweight/strategy/state pattern was most often referenced<br />
   (but still less than &#8220;sausage&#8221;)</p>
<p>why no talk of patterns?<br />
 * patterns are built-in<br />
    &#8211; first class functions<br />
    &#8211; metaprogramming (can manipulate functions/definitions)<br />
    &#8211; iterators<br />
    &#8211; closures (even if not a &#8220;true&#8221; closure in python, but close enough)</p>
<p>examples:<br />
 * factory<br />
   >>> {&#8216;thing1&#8242;:Thing1, &#8216;thing2&#8242;:Thing2}[which_one]()</p>
<p>conclusions:<br />
 * look to features of langauge before patterns<br />
 * reduce patterns &#8211;> shortercode<br />
 * if need a pattern, add a language feature (e.g. concurrency stuff)</p>
<p>presentor wants &#8220;channel pattern&#8221; (as a model for processes to replace threads)<br />
 * look at PyCSP (or stackless?) for concurrency</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Class Decorators<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>just like function decorators<br />
 * definition: a callable that accepts at least one argument and returns something</p>
<p>available as of py2.6</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> identity<span style="color: black;">&#40;</span>ob<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> ob 
&nbsp;
@identiy
<span style="color: #ff7700;font-weight:bold;">class</span> C<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>in 2.5, you can do same type of thing, but you can&#8217;t use the @decorator syntax</p>
<p>class decorators are not inheritable!!!<br />
but you can stack them on top of a single class<br />
(as opposed to metaclasses, which are inherited but not stackable)</p>
<p>default method decorator vs. mixins (eg partial class)<br />
 * ???</p>
<p>popular patterns (besides just replacing what was done with metaclasses)<br />
 * register<br />
 * augment (mixin replacement)<br />
    &#8211; example: take the __lt__ method and automagically make an __eq__ and<br />
      __gt__ for class<br />
 * fixup (monkeypatching decorator)<br />
    &#8211; example: replace all dunder-attribute with single underscores, so can get<br />
      access to the stuff that was privatized.  can monkeypatch a decorator into<br />
      a thirdparty library too!  (named @stop_doing_java)<br />
 * verify (assert stuff about the class)</p>
<p>registration pattern<br />
 * presentors best use case<br />
 * add stuff to a list that&#8217;s kept elsewhere</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">@cron.<span style="color: black;">schedule</span><span style="color: black;">&#40;</span>cron.<span style="color: black;">NIGHTLY</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">class</span> SalesReport<span style="color: black;">&#40;</span>Report<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> run<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;">#blah</span></pre></div></div>

<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
ORM Panel<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
&#8230;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Scripting in Python (super beginner)<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>Compromise Layout pattern<br />
    Project<br />
        /bin<br />
            script.py<br />
        /scriptlib<br />
            __init__.py<br />
            scriptimpl.py<br />
        setup.py<br />
Conditional main pattern<br />
    >>> if __name__ == &#8216;main&#8217;:<br />
    &#8230;    sys.exit(main(sys.argv))<br />
3 layers of IO pattern:<br />
 * should you deal with filenames, file objects, or generators ?  YES!<br />
 * main should take a filename.  invokes something that takes a file instanece.<br />
   below that use generator layer for efficiency.<br />
Use optparse pattern<br />
wtf.  not exactly what i was expecting from this talk.  time to go drink.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Drop ACID and think about data<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
ACID: a promise ring your DBMS wears<br />
 * atomicity &#8211; all or nothing<br />
 * consistency &#8211; no explosions during crashes/etc<br />
 * isolation &#8211; no fighting from writers, can pretend transactions are serial<br />
 * durability &#8211; no lying to you.. assume things worked</p>
<p>scalability and reliability: requires a bunch of stuff from rdbms to get there</p>
<p>CAP theorem says pick 2:<br />
 * consistency, availability, partition tolerance</p>
<p>BASE:<br />
 * basically available, soft state (doesn&#8217;t have to be consistent immediately), eventually consistent<br />
 * Google BigTable<br />
    &#8211; append-only data makes it faster to insert<br />
    &#8211; fantastic data compression due to hybrid row/column storage<br />
 * Amazon Dynamo key/value store<br />
    &#8211; consistent hashing to distribute data to appropriate node<br />
 * Facebook Cassandra<br />
    &#8211; OPEN SOURCE!!  incrementally scalable<br />
    &#8211; no compression, not quite polished <img src='http://www.mike-griffith.com/blog/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>distributed db&#8217;s are the new hotness, but none are awesome yet.<br />
 * we don&#8217;t need another half-baked dynamo clone</p>
<p>memcached: key/value store used as cache<br />
 * RAM only.  throws data away.  lightning fast.  everyone&#8217;s doing it.<br />
 * invalidation is hard and failure-prone<br />
    &#8211; be careful with mutable data.  consistency will be lost over DB solution.</p>
<p>Tokyo Cabinet/Tyrant:  super enhanced berkeleydb key/value store<br />
 * disk persistent, but still very performant<br />
 * actively developed<br />
 * replication similar to mysql<br />
!! possible solution for photoworks session</p>
<p>document databases<br />
 * schema free, easy to use,<br />
 * easier to migrate.  some documents will just have different properties.<br />
    &#8211; but application still needs to be able to deal with this<br />
!! we kind of got this with photoworks project meta-data<br />
 * couchdb &#8211; document db poster child<br />
 * mongodb &#8211; way faster than couchdb.  json/bson (binary json-ish)</p>
<p>column databases:<br />
 * sequential reads are awesome<br />
 * compresses much better than rows<br />
 * monetdb &#8211; DON&#8217;T USE THIS</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
Concurrency and Distributed systems<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
concurrent > parallel > distributed</p>
<p>goals:<br />
 * decrease latency, increase throughput</p>
<p>issue?<br />
 * global interpreter lock (GIL).  one thread at a time.<br />
    &#8211; ugh. slow. boo.<br />
    &#8211; perhaps fixed in unladen-swallow ?<br />
 * but you can build concurrent regardless of GIL</p>
<p>multiprocessing in 2.6+<br />
 * processes and IPC via pipes to allow parallelism<br />
 * similar API to thread/queue</p>
<p>more on GIL workarounds&#8230;<br />
 * Jython<br />
    &#8211; allows free-threading via java.util.concurrent, at the cost of losing C extensions<br />
 * IronPy<br />
    &#8211; also unrestricted threading, and some C extensions via ironclad<br />
 * PyPy<br />
    &#8211; complete rethink of interpreter<br />
    &#8211; not production ready <img src='http://www.mike-griffith.com/blog/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>Twisted<br />
 * asynchronous, event driven multitasking<br />
 * supports thread usage, but may not always be threadsafe</p>
<p>Kamaelia<br />
 * easy to understand.  very easy to get up and running.  IPCs, Threads, etc abstracted away<br />
 * compontents talk vis mailbox.  cooperative multitasking via generators<br />
 * lots of fantastic examples<br />
 !!! try this out</p>
<p>problem w/ frameworks<br />
 * twisted/kamaelia radically different<br />
 * you end up adapting the methodology in app, which can be dangerous</p>
<p>messaging/rpc flooded with libraries<br />
 * Pyro for RPC should be checked out<br />
 * memcached for shared memory<br />
 * Stomp, ApacheActiveMQ for message queues<br />
    &#8211; space flooded b/c heavy use by web apps for asynch processesing right now</p>
<p><strong>Notes from Sunday</strong></p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Paver<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
build process helpers<br />
 * cmd line<br />
 * config<br />
 * work w/ files<br />
 * svn, sphinx, virtualenv, etc.<br />
 * distutils, setuptools</p>
<p>without paver, you end up writing a seperate script for everything you want to do</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ easy_install Paver
$ paver paverdocs <span style="color: #666666; font-style: italic;">#displays Paver documentation</span></pre></div></div>

<p>build files&#8230;<br />
$ vi pavement.py</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">options<span style="color: black;">&#40;</span>
    setup = setup_meta,  <span style="color: #808080; font-style: italic;">#via setup.py</span>
    virtualenv=Bunch<span style="color: black;">&#40;</span>
        packages_to_install=<span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span>, <span style="color: #483d8b;">&quot;&quot;</span><span style="color: black;">&#93;</span>,
...</pre></div></div>

<p>tasks are the heart of paver</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">@task
<span style="color: #ff7700;font-weight:bold;">def</span> clean<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
   <span style="color: #483d8b;">&quot;&quot;&quot; cleans up paver dict,  removes virtualenv tree and build dir &quot;&quot;&quot;</span></pre></div></div>

<p>other fun decorators too<br />
@cmdopts &#8211; integration w/ optparser to set up cmd line options for your tasks</p>
<p>paver.easy<br />
 * logging, unix command running, dry-run stuff against command line</p>
<p>paver.path<br />
 * jason orendorff&#8217;s path.py module built in</p>
<p>paver.doctools<br />
 * sphinx (generate html docs)<br />
 * ned batch&#8217;s Cog support.  &#8220;section off&#8221; pieces of code and pull into your docs dynamically.</p>
<p>paver.ssh, paver.svn, paver.virtual (virtualenv)</p>
<p>deployment of code delegated to pytoss (?)</p>
<p>getting started: http://bit.ly/starting_paver</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Functional Testing Panel<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
windmill<br />
 * python proxy &#8211; avoids same domain security in browser<br />
 * python browser launching<br />
 * python CI reporting<br />
 * javascript simulate user interactions &#8211; tries to get it right (bubbling, mouseclick events)<br />
 * javascript waits for dynamic content<br />
 * javascript assertions</p>
<p>selenium:<br />
 * &#8220;record/playback is the root of all evil&#8221;.  none of creators wanted to do it<br />
 * next version will have more native C hooks.  javascript event faking could only get so far.<br />
 * really only good at testing in firefox, rest of browsers (including chrome) suck</p>
<p>twill:<br />
 * technically just a small DSL on top of mechanize/clientform/beautifulsoup<br />
 * forms, cookies, redirects, link checking<br />
 * but no javascript support. ever. not even a little.</p>
<p>webtest (ian bicking)<br />
 * runs fake request/responses on WSGI frameworks<br />
 * written to test paste<br />
 * doesn&#8217;t actually run http</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> myapp <span style="color: #ff7700;font-weight:bold;">import</span> wsgi_app
<span style="color: #ff7700;font-weight:bold;">from</span> webtest <span style="color: #ff7700;font-weight:bold;">import</span> TestApp
app=TestApp<span style="color: black;">&#40;</span>wsgi_app<span style="color: black;">&#41;</span>
app.<span style="color: black;">go</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> app.<span style="color: black;">resp</span></pre></div></div>

<p>nose<br />
 * nose.cfg for default cmd line opts<br />
 * &#8211;with-django plugin to help set up env</p>
<p>py.test 1.0<br />
 * distributed testing.  central reporting.<br />
    &#8211; run your tests on all different envs (clouds, o/s&#8217;s, py versions, etc)<br />
 * plugins similar to nosetests.  but not documented all that well <img src='http://www.mike-griffith.com/blog/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /><br />
 * runs unittests, doctest, restdoc, pocoo (sends failures to pastebin)<br />
 * tetamap.wordpress.com, pytest.org</p>
<p>vision: make automated deployment merge w/ actual deployment, and have success<br />
be mandated for deploy.</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Lightning talks<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>== argparse ==<br />
all features of optparse, but better docstrings and never touch sys.argv<br />
sub command parsers (e.g. svn add) easier than optparse<br />
mutually exclusive arguments</p>
<p>http://code.google.com/p/argparse</p>
<p>== python 3.1 ==<br />
some performance improvements.  IO now almost as fast as 2x<br />
unittest improvements.  assertRaises trick<br />
OrderedDict finally arrives</p>
<p>from __future__ import bad_syntax_ideas<br />
 * braces, no colons, no indentation, implied ruby blocks, etc.<br />
 * pep 3117</p>
<p>== Poor Man&#8217;s Continuous Integration ==<br />
try to do it without buildbot using your existing tools<br />
 * capastrano, maestro, git/svn<br />
using &#8220;fabric&#8221; instead of &#8220;git push&#8221;<br />
 $ fab push -d staging_server deploy<br />
 * wraps up the test run and git push steps</p>
<p>== cluemapper &#8211; software project manager ==<br />
example: lots of software projects<br />
 * each w/ issue tracker, svn<br />
 * want to share users across projects<br />
built on top of trac.  &#8220;trac for teams&#8221;<br />
 * basic reporting and time-tracking<br />
 * trac plugins to extend core<br />
 * wsgi + dojo ajax<br />
components<br />
 * irc bot<br />
 * theming<br />
 * pypi egg server<br />
 * bzr integration<br />
 * pastebin<br />
 * timetracking, reporting<br />
nice source control user manager for each repository<br />
roadmap<br />
 * agile/scrum/xp stories and whiteboard<br />
    &#8211; drag/drop between stories and iterations<br />
    !!!!!!!!!!!!!!!!!!!!!!! yayz !!!!!!!!!!!!!!!!!!<br />
<a href="http://cluemapper.org">cluemapper.org</a></p>
<p>== ReleaseBot ==<br />
release mgr process watches buildbot<br />
push button to tag a version for deploy<br />
 * workflow for notifying QA that this is what needs tested<br />
buildbot notices tag and preps for release<br />
not yet developed, just idea phase</p>
<p>== pyjamas ==<br />
python to javascript compiler, with built-in widget set<br />
JSONProxy seems fun!<br />
rest is pure evil.</p>
<p>== \ is evil ==<br />
don&#8217;t split lines with a backslash<br />
use parentheses instead</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">my_str = <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;asdlfkjasdf   asdlfkjdsf&quot;</span>
        <span style="color: #483d8b;">&quot;  asdflkj   asldkjf &quot;</span>
        <span style="color: #483d8b;">&quot; alskjdf asdlkjj &quot;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>insetad of</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">evil_nasty_str = <span style="color: #483d8b;">&quot;asdlfkjasdf   asdlfkjdsf&quot;</span> \
        <span style="color: #483d8b;">&quot;  asdflkj   asldkjf &quot;</span> \
        <span style="color: #483d8b;">&quot; alskjdf asdlkjj &quot;</span></pre></div></div>

<p><strong>Mini-conclusion</strong><br />
Things for follow-up:<br />
 * windmill.  first round of experimenting at openspace didn&#8217;t prove to be as awesome as i had hoped.  but i&#8217;m willing to give it another try.  scripting these in python feels like an afterthought, and it wouldn&#8217;t be easy to get integrated with BuildBot.<br />
 * ClueMapper.  looking forward to the scrum/xp tools built into Trac.<br />
 * webtest instead of twill for scripting end-to-end tests<br />
 * py.test for distributed testing<br />
 * tokyo cabinet for key/value store with persistence<br />
 * web2py web framework.  the data schema admin manager doesn&#8217;t feel quite as polished as django, and i don&#8217;t like the online editor.  but their MVC ideas and templating implementation might be useful.<br />
 * mercurial or bzr.  i need more practice with DVCS.  i committed all my code throughout the weekend to a local mercurial instance, but never pushed up to a central repository.  </p>
<p>That&#8217;s all she wrote for now.  Looking forward to future PyCon&#8217;s and to trying out some of these awesome tools.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/03/notes-from-pycon-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I used to play sports. Then I realized you can buy trophies. Now I’m good at everything.</title>
		<link>http://www.mike-griffith.com/blog/2009/02/i-used-to-play-sports-then-i-realized-you-can-buy-trophies-now-i%e2%80%99m-good-at-everything/</link>
		<comments>http://www.mike-griffith.com/blog/2009/02/i-used-to-play-sports-then-i-realized-you-can-buy-trophies-now-i%e2%80%99m-good-at-everything/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 16:50:20 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[off topic]]></category>
		<category><![CDATA[software development]]></category>
		<category><![CDATA[humor]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=265</guid>
		<description><![CDATA[I stumbled across &#8220;Dammit I&#8217;m Mad&#8221; by Demetri Martin, a rumored-to-be 224 word palindrome poem.  
I was impressed, but needed to check the accuracy of such a statement.  So I dialed up a python session.

import re
awesomedrome = &#34;&#34;&#34;Dammit I'm mad.
Evil is a deed as I live.
God, am I reviled? I rise, my bed [...]]]></description>
			<content:encoded><![CDATA[<p>I stumbled across <a href="http://www.slate.com/id/2101150/sidebar/2101387/ent/2101353/">&#8220;Dammit I&#8217;m Mad&#8221; by Demetri Martin</a>, a rumored-to-be 224 word palindrome poem.  </p>
<p>I was impressed, but needed to check the accuracy of such a statement.  So I dialed up a python session.</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;">re</span>
awesomedrome = <span style="color: #483d8b;">&quot;&quot;&quot;Dammit I'm mad.
Evil is a deed as I live.
God, am I reviled? I rise, my bed on a sun, I melt.
To be not one man emanating is sad. I piss.
Alas, it is so late. Who stops to help?
Man, it is hot. I'm in it. I tell.
I am not a devil. I level &quot;Mad Dog&quot;.
Ah, say burning is, as a deified gulp,
In my halo of a mired rum tin.
I erase many men. Oh, to be man, a sin.
Is evil in a clam? In a trap?
No. It is open. On it I was stuck.
Rats peed on hope. Elsewhere dips a web.
Be still if I fill its ebb.
Ew, a spider... eh?
We sleep. Oh no!
Deep, stark cuts saw it in one position.
Part animal, can I live? Sin is a name.
Both, one... my names are in it.
Murder? I'm a fool.
A hymn I plug, deified as a sign in ruby ash,
A Goddam level I lived at.
On mail let it in. I'm it.
Oh, sit in ample hot spots. Oh wet!
A loss it is alas (sip). I'd assign it a name.
Name not one bottle minus an ode by me:
&quot;Sir, I deliver. I'm a dog&quot;
Evil is a deed as I live.
Dammit I'm mad.&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># strip out all punctuation</span>
just_the_chars = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\W</span>'</span><span style="color: black;">&#41;</span>.<span style="color: black;">sub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, awesomedrome<span style="color: black;">&#41;</span>.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> test_palindrome<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># chars[::-1] gives the reverse of the resulting string</span>
    <span style="color: #ff7700;font-weight:bold;">assert</span> just_the_chars == just_the_chars<span style="color: black;">&#91;</span>::-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span></pre></div></div>

<p>I stripped out any non-word characters (punctuation, space, etc) with the regular expression, lower-cased it all, and compared it front to back.</p>
<p><del datetime="2010-04-22T14:28:25+00:00"></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python is_demtri_a_god.py
not exactly</pre></div></div>

<p>As you can see, it&#8217;s not palindromic.</p>
<p>So close.</del></p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ nosetests test_demetri.py
.
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #000000; font-weight: bold;">in</span> 0.001s
&nbsp;
OK</pre></div></div>

<p><strong>Update 4/22:</strong><br />
Not sure why the original script used to doubted the claim to palindromity, but I&#8217;ve fixed it now.  Demetri really does rock our socks off!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/02/i-used-to-play-sports-then-i-realized-you-can-buy-trophies-now-i%e2%80%99m-good-at-everything/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Java is a Bad Ex</title>
		<link>http://www.mike-griffith.com/blog/2009/02/java-is-a-bad-ex/</link>
		<comments>http://www.mike-griffith.com/blog/2009/02/java-is-a-bad-ex/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 16:59:35 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rant]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=249</guid>
		<description><![CDATA[
Although I&#8217;ve been enamored with Python for the last 13 or so months, I&#8217;ve often dreamt longingly for days of Java glory.  Things from the past seem so desirable at times &#8212; IDEs with good code completion and integrated debugging, staticly-typed compiler hand-holding, mature application servers and deployment tools.  There was never much [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2009/02/youngwomanoldlady-213x300.jpg" alt="young woman, old lady illusion" title="is she really as pretty as your remember?" width="213" height="300" class="alignright size-medium wp-image-252" /></p>
<p>Although I&#8217;ve been enamored with Python for the last 13 or so months, I&#8217;ve often dreamt longingly for days of Java glory.  Things from the past seem so desirable at times &#8212; IDEs with good code completion and integrated debugging, staticly-typed compiler hand-holding, mature application servers and deployment tools.  There was never much black magic tying things together.  You could easily trace where and why something was breaking, and throw a fix up quickly.</p>
<p>It only takes a few minutes of reading through a large Java codebase to bring me back to reality.  The horribly cluttered JSPs with code spewing into and around markup.  MEGA-JARs.  XML files and properties files galore.  65 lines of code to parse a querystring (not because there wasn&#8217;t a better way, but because many Java coders don&#8217;t value beauty by simplicity).  Seriously.</p>
<p>I know there are pie-in-the-sky Java apps that give developers the warm-and-fuzzies inside, but <strong>most of what I&#8217;ve seen in practice gives me the chills</strong>.  I guess part of what is so alluring is the notion that I could take an ugly Java app, apply what I&#8217;ve learned from Python, and behold the beauty of an amazing creation.</p>
<p>Alas, Java is like the bad ex that you think you want back.  A few months after the breakup, you think back on all the good times, the marathon sex sessions, and forget entirely why it was you broke up.  You want a second chance to make it work.  In reality, <strong>the sex was never really that good</strong>, it was just comfortable.  There were countless little things that annoyed you and caused you so many headaches, the same few things that you always fought about and never really resolved.</p>
<p>Just so that I don&#8217;t forget, here&#8217;s a list of <em>5 things I love about Python or hate about Java</em>.</p>
<ol>
<li><code>from future import antigravity;</code>  Seriously, just <code>easy_install</code> it, import it, and you have it.  So much more is available at your fingertips in Python than was in Java.</li>
<li>The fact that Python was willing to break backwards compatibility with the advent Python 3K, which is a serious testament to the community.  Java can&#8217;t do that because its user base is notoriously full of late adopters who are resistant to change and are generally less agile.</li>
<li>Collections.  Yes there are all the collection types in the Java standard library, but they&#8217;re still so klunky to work with.  Everything relies on hashtables and arrays, so why not make them as easy to use as Python?</li>
<li>XML fever.  Why is it so buzzy still in Java?  There is a better way.</li>
<li>The lack of an awesome, blow-me-away, clear-winner of a web framework in Java.  I know Python doesn&#8217;t quite have that either, but Django is making great strides.  And in a weird way, not having one is good for Python, in that it&#8217;s fostering some great new developments.  Granted, I don&#8217;t know anything about Struts 2, but I have a feeling it&#8217;s the same-old same-old.</li>
</ol>
<p><strong>The moral of the story?  Don&#8217;t forget how good you got it.</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/02/java-is-a-bad-ex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PyCon 2009</title>
		<link>http://www.mike-griffith.com/blog/2009/02/pycon-2009/</link>
		<comments>http://www.mike-griffith.com/blog/2009/02/pycon-2009/#comments</comments>
		<pubDate>Sun, 15 Feb 2009 23:33:39 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=243</guid>
		<description><![CDATA[I&#8217;m going to PyCon 2009!  I&#8217;ll be there with a few other guys from work.  We&#8217;re flying in Wednesday night, taking a tutorial on Thursday, and trying to have a little fun throughout the weekend.

]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to PyCon 2009!  I&#8217;ll be there with a few other guys from <a href="http://www.aginteractive.com/">work</a>.  We&#8217;re flying in Wednesday night, taking a tutorial on Thursday, and trying to have a little fun throughout the weekend.</p>
<p><a href="http://us.pycon.org"><img src="http://us.pycon.org/media/2009/public/pycon2009-horizontal-large-215x135.png" alt="PyCon 2009: Chicago"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/02/pycon-2009/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Including external data with your unit tests</title>
		<link>http://www.mike-griffith.com/blog/2009/01/including-external-data-with-your-unit-tests/</link>
		<comments>http://www.mike-griffith.com/blog/2009/01/including-external-data-with-your-unit-tests/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 20:06:21 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=191</guid>
		<description><![CDATA[We generally preach that you should not use real data in your unit tests.  You should instead mock said data out in an effort to lesson potential side-effects, including degrading test performance and adversely affecting live data.
Sometimes, you&#8217;d like to test actual file handling in a unit test.  If you do, you should [...]]]></description>
			<content:encoded><![CDATA[<p>We generally preach that you should not use real data in your unit tests.  You should instead mock said data out in an effort to lesson potential side-effects, including degrading test performance and adversely affecting live data.</p>
<p>Sometimes, you&#8217;d like to test actual file handling in a unit test.  If you do, you should provide a sample data set packaged with your code in a data directory within your test directory.</p>
<p>Your package would then resemble the following structure:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">/package
    /tests
        /data
            data.txt
        __init__.py
        test_module.py
    __init__.py
    module.py</pre></div></div>

<p>In your test, you&#8217;ll need to provide a relative path to the data file.  To do this, use the special <code>__file__</code> attribute of the package to provide a starting point.  This will let you know where the module lives on disk regardless of where the package is installed.</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;">os</span>
<span style="color: #ff7700;font-weight:bold;">from</span> package.<span style="color: black;">tests</span> <span style="color: #ff7700;font-weight:bold;">import</span> __file__ <span style="color: #ff7700;font-weight:bold;">as</span> test_directory
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> _data_dir<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">dirname</span><span style="color: black;">&#40;</span>test_directory<span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'data'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> test_sample_data<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    file_path = <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>_data_dir<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, <span style="color: #483d8b;">'data.txt'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span>file_path<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
        package.<span style="color: black;">module</span>.<span style="color: black;">do_something</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span></pre></div></div>

<p>There you have it!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/01/including-external-data-with-your-unit-tests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python multiline regex</title>
		<link>http://www.mike-griffith.com/blog/2009/01/python-multiline-regex/</link>
		<comments>http://www.mike-griffith.com/blog/2009/01/python-multiline-regex/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 17:36:13 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=184</guid>
		<description><![CDATA[After pulling most of my hair out, I realized a simple mistake in my Python regular expression usage.  I had been trying to search a simple HTML document for some text, which happened to be broken across a newline such as:

  &#60;div&#62;I'm some
           [...]]]></description>
			<content:encoded><![CDATA[<p>After pulling most of my hair out, I realized a simple mistake in my Python regular expression usage.  I had been trying to search a simple HTML document for some text, which happened to be broken across a newline such as:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>I'm some
               fancy text that needs
               to be found<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>I tried my very simple pattern match using the re.MULTILINE flag to no avail. The solution ended up being:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">p = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'some<span style="color: #000099; font-weight: bold;">\s</span>*fancy'</span>, <span style="color: #dc143c;">re</span>.<span style="color: black;">DOTALL</span><span style="color: black;">&#41;</span>
p.<span style="color: black;">search</span><span style="color: black;">&#40;</span>input_text<span style="color: black;">&#41;</span></pre></div></div>

<p>re.MULTILINE is not the same as re.DOTALL.  Use DOTALL if you want your dot to match everything, including new lines.  See more at this <a href="http://www.regular-expressions.info/python.html">handy dandy reference site</a>.</p>
<p>Doh!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/01/python-multiline-regex/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tamper-proof python dictionary</title>
		<link>http://www.mike-griffith.com/blog/2008/09/tamper-proof-python-dictionary/</link>
		<comments>http://www.mike-griffith.com/blog/2008/09/tamper-proof-python-dictionary/#comments</comments>
		<pubDate>Mon, 22 Sep 2008 19:23:43 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[software development]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web security]]></category>

		<guid isPermaLink="false">http://blog.rideshootlive.com/?p=83</guid>
		<description><![CDATA[Sometimes the need arises to pass a python list, tuple, dictionary, etc. from one page to another.  If you do not have a session service to hold it, the object may need to pass through a HTTP request (in cookie or get/post param), opening the possibility of tampering.  Without some precautions, a serious [...]]]></description>
			<content:encoded><![CDATA[<p>Sometimes the need arises to pass a python list, tuple, dictionary, etc. from one page to another.  If you do not have a session service to hold it, the object may need to pass through a HTTP request (in cookie or get/post param), opening the possibility of tampering.  Without some precautions, a serious vulnerability could be exposed.  Googling for “dictionary to string” yields some example implementations, most of which are still vulnerable to attack.  I think we can do better.</p>
<p><strong>Option 1: encode=string-ify, decode=eval</strong><br />
The idea here is take a dict and turn it into a string.  Then running eval would give you back the original dictionary.  If the world were full of with people who danced in flower-filled meadows, this would be ok. The problem is that if you need to pass “s” through an HTTP request, it can be altered into something, like perhaps “os.rmdir(’/&#8217;)”</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">d=<span style="color: black;">&#123;</span><span style="color: #483d8b;">'var1'</span>:<span style="color: #ff4500;">1</span>, <span style="color: #483d8b;">'var2'</span>:<span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span>
s=<span style="color: #483d8b;">&quot;{'var1':1, 'var2':2}&quot;</span>
new_d = <span style="color: #008000;">eval</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span></pre></div></div>

<p>Result: <strong>VULNERABLE</strong> to arbitrary code execution.</p>
<p><strong>Option 2: encode=string-ify, decode=slightly-safter eval</strong><br />
The eval method in python does allow you to tighten it up a bit.  There are several <a href="http://www.google.com/search?q=python+safe+eval&amp;ie=utf-8&amp;oe=utf-8&amp;aq=t&amp;rls=org.mozilla:en-US:official&amp;client=firefox-a" target="_blank">articles</a> detailing how to make it slightly safer, by only allowing a certain subset of methods to be available.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">new_d = <span style="color: #008000;">eval</span><span style="color: black;">&#40;</span>s, <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;__builtins__&quot;</span>:<span style="color: #008000;">None</span><span style="color: black;">&#125;</span>, <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Result: <strong>VULNERABLE</strong> to arbitrary code execution.</p>
<p><strong>Option 3: encode=pickle, decode=unpickle</strong><br />
So what if instead of just eval’ing, we used the pickle module to serialize and then deserialize the dictionary?  That <em>feels</em> safer at first glance.  But what if the object to be deserialized was no longer a dictionary?  Perhaps an attacker pickled their own evil object, whose constructor or maybe get() method was modified to do wreak havoc.<br />
Result: <strong>VULNERABLE</strong> to arbitrary code execution.</p>
<p><strong>Option 4: encode=jsonify, decode=un-jsonify</strong><br />
One technique that didn’t appear in the results was using simplejson to encode and decode.  (Thanks Mike Pirnat for suggesting the now-obvious).  The simplejson decoder is a much safer one, because it scans the input to make sure it really does look like a dictionary (with all keys and values being safe types) before turning it into a python dict.<br />
User’s can still tamper with the keys and values, but it is no more susceptible than other types of parameter manipulation rampant on the web, so validation still need be there.<br />
Result: much better</p>
<p><strong>Option 5: encode=jsonify(jsonify+hash), decode=un-jsonify plus hash check</strong><br />
To an extra level of comfort, let’s try to make sure that the dictionary wasn’t tampered with.  We can take a hash of what we just json-ified, pack it with the data, and json-ify that result.  Then when we unpack it, we can double-check that the hash that came with the data still matches a new calculation of the hash of the data.  Assuming we have a strong, protected key for our hash algorithm, if the user tried to tamper with the data, they wouldn’t be able to replicate the corresponding change in the hash value, allowing us to raise an exception.<br />
Result: best yet</p>
<p>There ye have it, a safer way of turning a dictionary into a string suitable for passing around the website.  Just make sure your hash function is strong and your key is protected.</p>
<p>You can <a href="/code/encode_dict.py">download encode_dict.py</a> to see the final result.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2008/09/tamper-proof-python-dictionary/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
