<?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</title>
	<atom:link href="http://www.mike-griffith.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mike-griffith.com/blog</link>
	<description>on software, testing, and the web.</description>
	<lastBuildDate>Sun, 24 Jan 2010 22:36:58 +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>Baby boy gear round-up</title>
		<link>http://www.mike-griffith.com/blog/2010/01/baby-boy-gear-round-up/</link>
		<comments>http://www.mike-griffith.com/blog/2010/01/baby-boy-gear-round-up/#comments</comments>
		<pubDate>Sun, 24 Jan 2010 22:36:58 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[parenting]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=352</guid>
		<description><![CDATA[With a baby boy on the way (due in early June 2010), I decided to start looking for fun stuff for my lil dude.  I thought that maybe I&#8217;d have to wait a few years to unleash him on the world, but lo and behold there&#8217;s some seriously badass gear for infants and toddlers! [...]]]></description>
			<content:encoded><![CDATA[<p>With a baby boy on the way (due in early June 2010), I decided to start looking for fun stuff for my lil dude.  I thought that maybe I&#8217;d have to wait a few years to unleash him on the world, but lo and behold there&#8217;s some seriously badass gear for infants and toddlers!  If I wasn&#8217;t excited enough already, now I&#8217;m entirely stoked to take on parenting and turn this guy into the coolest kid on the block!</p>
<p>I&#8217;m still looking for lots more goodies.  I have yet to find the perfect off-road running stroller, and I&#8217;m a bit disappointed by the selection of baby snowboards, but I&#8217;ve got a few more months to sort it all out.</p>
<p>Here&#8217;s some of the clothes and gear I&#8217;ve found so far&#8230;</p>
<p><strong>Nerdy T-shirts:</strong></p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2010/01/exothermic.gif" alt="" title="exothermic" width="275" height="227" /><br />
Exothermic reaction t-shirt &#8211; clevercuties.com
</p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2010/01/BIBONACCI-186x300.jpg" alt="" title="BIBONACCI" width="186" height="300" /><br />
Bibonacci t-shirt &#8211; clevercuties.com.  The nerd in me cannot resist something this awesome.
</p>
<p><strong>Big boys clothes in little man sizes:</strong></p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2010/01/adidastracksuit-195x300.jpg" alt="" title="adidastracksuit" width="195" height="300" /><br />
Baby track suit &#8211; Nordstrom&#8217;s.  Oh heck yes, he gonna be a soccer playa!
</p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2010/01/chucks.jpg" alt="" title="chucks" width="240" height="240" /><br />
Baby Chuck&#8217;s &#8211; zappos.com
</p>
<p><strong>Outdoor gear:</strong></p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2010/01/helmet.jpg" alt="" title="helmet" width="220" height="220" /><br />
Full-face helmet &#8211; nybikergear.com.  This is a prerequisite for the snowboard, dirt bike, skateboard, and baby sky-diving outfit that he&#8217;ll be donning after a few months.</p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2010/01/childcarrier1-300x300.jpg" alt="" title="childcarrier" width="300" height="300" /><br />
Kid in a bag &#8211; rei.com.  Before he&#8217;s able to walk, he&#8217;ll be able to tag along on hikes.  Throw him in a bag on my back and off we go.  They even sell sun visors and other accessories.</p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2010/01/snowsuit-300x300.jpg" alt="" title="snowsuit" width="300" height="300"  /><br />
Snowsuit &#8211; backcountry.com.  He&#8217;s gonna be the hippest kid on the slopes for sure.  Gotta look good, especially considering he&#8217;ll almost certainly be the youngest person to ever bust a double cork.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2010/01/baby-boy-gear-round-up/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Browser history sniffing with Dojo</title>
		<link>http://www.mike-griffith.com/blog/2010/01/browser-history-sniffing-with-dojo/</link>
		<comments>http://www.mike-griffith.com/blog/2010/01/browser-history-sniffing-with-dojo/#comments</comments>
		<pubDate>Thu, 14 Jan 2010 06:40:52 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[tips & tricks]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=346</guid>
		<description><![CDATA[Niall Kennedy posted a now-famous article about using some browser trickery to determine what websites a user on your site has visited.  I&#8217;ve taken that concept and created a module that can be used with the Dojo Toolkit javascript framework.
It provides two methods that you can use in your code, isVisited and isAnyVisited.
One important [...]]]></description>
			<content:encoded><![CDATA[<p>Niall Kennedy posted a <a href="http://www.niallkennedy.com/blog/2008/02/browser-history-sniff.html" target="_blank">now-famous article</a> about using some browser trickery to determine what websites a user on your site has visited.  I&#8217;ve taken that concept and created a module that can be used with the <a href="http://www.dojotoolkit.org/" target="_blank">Dojo Toolkit</a> javascript framework.</p>
<p>It provides two methods that you can use in your code, <code>isVisited</code> and <code>isAnyVisited</code>.</p>
<p>One important note about your URL specification is that you must specify an *exact* URL that the user has been to.  So, for example, if someone has visited several twitter profiles, but never actually went to the homepage or signin screen, then it would be difficult/impossible to tell whether or not they were a twitter user without a massive brute-force query.</p>
<p>You can download <a href="/js/dojo1.4/mdg/sniff.js" target="_blank">sniff.js</a>, or <a href="/code/browsersniff.html" target="_blank">view a demo</a>.</p>
<p><strong>Sample usage:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">dojo.<span style="color: #660066;">require</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;mdg.sniff&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> usedYahoo <span style="color: #339933;">=</span> mdg.<span style="color: #660066;">sniff</span>.<span style="color: #660066;">isVisited</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;http://www.yahoo.com&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> usedGoogleMaps <span style="color: #339933;">=</span> mdg.<span style="color: #660066;">sniff</span>.<span style="color: #660066;">isAnyVisited</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>
      <span style="color: #3366CC;">&quot;http://maps.google.com&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #3366CC;">&quot;http://maps.google.com/maps&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #003366; font-weight: bold;">var</span> usedFacebook <span style="color: #339933;">=</span> mdg.<span style="color: #660066;">sniff</span>.<span style="color: #660066;">isAnyVisited</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span>
      <span style="color: #3366CC;">&quot;http://www.facebook.com&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #3366CC;">&quot;http://www.facebook.com/index.php&quot;</span><span style="color: #339933;">,</span>
      <span style="color: #3366CC;">&quot;https://login.facebook.com/login.php&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p><strong>Source code:</strong></p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">dojo.<span style="color: #660066;">provide</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;mdg.sniff&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #006600; font-style: italic;">//</span>
<span style="color: #006600; font-style: italic;">// Browser history sniffing, based on infamous blog post:</span>
<span style="color: #006600; font-style: italic;">// &lt;http://www.niallkennedy.com/blog/2008/02/browser-history-sniff.html&gt;</span>
<span style="color: #006600; font-style: italic;">//</span>
<span style="color: #006600; font-style: italic;">// Sample usage:</span>
<span style="color: #006600; font-style: italic;">//</span>
<span style="color: #006600; font-style: italic;">//    dojo.require(&quot;mdg.sniff&quot;);</span>
<span style="color: #006600; font-style: italic;">//    var usedYahoo = mdg.sniff.isVisited(&quot;http://www.yahoo.com&quot;);</span>
<span style="color: #006600; font-style: italic;">//    var usedGoogleMaps = mdg.sniff.isAnyVisited([</span>
<span style="color: #006600; font-style: italic;">//          &quot;http://maps.google.com&quot;,</span>
<span style="color: #006600; font-style: italic;">//          &quot;http://maps.google.com/maps&quot;]);</span>
<span style="color: #006600; font-style: italic;">//    var usedFacebook = mdg.sniff.isAnyVisited([</span>
<span style="color: #006600; font-style: italic;">//          &quot;http://www.facebook.com&quot;,</span>
<span style="color: #006600; font-style: italic;">//          &quot;http://www.facebook.com/index.php&quot;,</span>
<span style="color: #006600; font-style: italic;">//          &quot;https://login.facebook.com/login.php&quot;]);</span>
<span style="color: #006600; font-style: italic;">//</span>
<span style="color: #006600; font-style: italic;">// Works with Dojo 1.3 and 1.4 (*may* work with 1.2 as well)</span>
<span style="color: #006600; font-style: italic;">//</span>
&nbsp;
dojo.<span style="color: #660066;">require</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;dojox.html.styles&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #003366; font-weight: bold;">var</span> _this <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">sniffCache</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    dojox.<span style="color: #660066;">html</span>.<span style="color: #660066;">insertCssRule</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.dojohistorysniff a&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;color:#000000;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    dojox.<span style="color: #660066;">html</span>.<span style="color: #660066;">insertCssRule</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;.dojohistorysniff a:visited&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;color:#ff0000 !important;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isAnyVisited</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #006600; font-style: italic;">/*Array*/</span>urls<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>i<span style="color: #339933;">=</span><span style="color: #CC0000;">0</span><span style="color: #339933;">;</span> i<span style="color: #339933;">&lt;</span>urls.<span style="color: #660066;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>_this.<span style="color: #660066;">isVisited</span><span style="color: #009900;">&#40;</span>urls<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isVisited</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #006600; font-style: italic;">/*String*/</span>url<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span><span style="color: #009900;">&#40;</span>_this.<span style="color: #660066;">sniffCache</span><span style="color: #009900;">&#91;</span>url<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">return</span> _this.<span style="color: #660066;">sniffCache</span><span style="color: #009900;">&#91;</span>url<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #003366; font-weight: bold;">var</span> link <span style="color: #339933;">=</span> _this.<span style="color: #660066;">addLink</span><span style="color: #009900;">&#40;</span>url<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003366; font-weight: bold;">var</span> color <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> dojo.<span style="color: #660066;">Color</span><span style="color: #009900;">&#40;</span>dojo.<span style="color: #660066;">style</span><span style="color: #009900;">&#40;</span>link<span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;color&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>color.<span style="color: #660066;">r</span> <span style="color: #339933;">==</span> <span style="color: #CC0000;">255</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            _this.<span style="color: #660066;">sniffCache</span><span style="color: #009900;">&#91;</span>url<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
            <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        _this.<span style="color: #660066;">sniffCache</span><span style="color: #009900;">&#91;</span>url<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">insertSniffDiv</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">return</span> dojo.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;div&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>className<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;dojohistorysniff&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> dojo.<span style="color: #660066;">body</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">getSniffDiv</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> divs <span style="color: #339933;">=</span> dojo.<span style="color: #660066;">query</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;div.dojohistorysniff&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>divs.<span style="color: #660066;">length</span> <span style="color: #339933;">&gt;</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066; font-weight: bold;">return</span> divs<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066; font-weight: bold;">return</span> _this.<span style="color: #660066;">insertSniffDiv</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">addLink</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #006600; font-style: italic;">/*String*/</span>url<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> div <span style="color: #339933;">=</span> _this.<span style="color: #660066;">getSniffDiv</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> dojo.<span style="color: #660066;">create</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;a&quot;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span>href<span style="color: #339933;">:</span> url<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> div<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">/**
     * mdg.sniff.isVisited
     * Check whether or not a URL has been visited
     * @param url String
     * @return boolean
     */</span>
    mdg.<span style="color: #660066;">sniff</span>.<span style="color: #660066;">isVisited</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isVisited</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">/**
     * mdg.sniff.isAnyVisited
     * Check whether or not *any* of the URLs specified have been visited
     * @param urls Array of Strings
     * @return boolean
     */</span>
    mdg.<span style="color: #660066;">sniff</span>.<span style="color: #660066;">isAnyVisited</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">isAnyVisited</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2010/01/browser-history-sniffing-with-dojo/feed/</wfw:commentRss>
		<slash:comments>0</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[coding]]></category>
		<category><![CDATA[photography]]></category>
		<category><![CDATA[python]]></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>0</slash:comments>
		</item>
		<item>
		<title>Recent svn commit statistics</title>
		<link>http://www.mike-griffith.com/blog/2010/01/recent-svn-commit-statistics/</link>
		<comments>http://www.mike-griffith.com/blog/2010/01/recent-svn-commit-statistics/#comments</comments>
		<pubDate>Wed, 13 Jan 2010 21:23:36 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[tips & tricks]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=320</guid>
		<description><![CDATA[Here&#8217;s a little script-fu that can help determine how many lines of code were added vs. deleted for a single Subversion commit.

#!/bin/bash
if &#91; -z &#34;$1&#34; &#93;; then
    echo &#34;usage: $0 revision&#34;
    exit
fi
&#160;
REV=$1
&#160;
# Execute a svn diff on the revision, and search the output for deleted lines
# (begin with a [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a little script-fu that can help determine how many lines of code were added vs. deleted for a single Subversion commit.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #660033;">-z</span> <span style="color: #ff0000;">&quot;$1&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;usage: $0 revision&quot;</span>
    <span style="color: #7a0874; font-weight: bold;">exit</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #007800;">REV</span>=$<span style="color: #000000;">1</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Execute a svn diff on the revision, and search the output for deleted lines</span>
<span style="color: #666666; font-style: italic;"># (begin with a '-', but aren't followed by another immediately),</span>
<span style="color: #666666; font-style: italic;"># and likewise with any added lines</span>
<span style="color: #007800;">DIFF</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$(svn diff -c $REV --diff-cmd=/usr/bin/diff)</span>&quot;</span>
<span style="color: #007800;">DEL_COUNTS</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$DIFF</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">egrep</span> <span style="color: #ff0000;">'^[-][^-]'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">wc</span> -lm<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">ADD_COUNTS</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$DIFF</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">egrep</span> <span style="color: #ff0000;">'^[+][^+]'</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">wc</span> -lm<span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> get_field <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #666666; font-style: italic;"># given an input string with 2 fields delimited by spaces, possibly with</span>
    <span style="color: #666666; font-style: italic;"># leading whitespace, return the field in the position specified.</span>
    <span style="color: #666666; font-style: italic;"># so,  `get_field &quot;   123   45678&quot; 1`  would return &quot;122&quot;</span>
    <span style="color: #666666; font-style: italic;"># and  `get_field &quot;   123   45678&quot; 2`  would return &quot;45678&quot;</span>
    <span style="color: #007800;">INPUT</span>=$<span style="color: #000000;">1</span>
    <span style="color: #007800;">POSITION</span>=$<span style="color: #000000;">2</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$INPUT</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #ff0000;">&quot;s/^[ ]*\([0-9]*\)[ ]*\([0-9]*\)/\<span style="color: #000099; font-weight: bold;">\$</span>POSITION/g&quot;</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #007800;">DEL_LINES</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>get_field <span style="color: #ff0000;">&quot;<span style="color: #007800;">$DEL_COUNTS</span>&quot;</span> <span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">DEL_CHARS</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>get_field <span style="color: #ff0000;">&quot;<span style="color: #007800;">$DEL_COUNTS</span>&quot;</span> <span style="color: #000000;">2</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
<span style="color: #007800;">ADD_LINES</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>get_field <span style="color: #ff0000;">&quot;<span style="color: #007800;">$ADD_COUNTS</span>&quot;</span> <span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #007800;">ADD_CHARS</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span>get_field <span style="color: #ff0000;">&quot;<span style="color: #007800;">$ADD_COUNTS</span>&quot;</span> <span style="color: #000000;">2</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Removed <span style="color: #007800;">$DEL_LINES</span> lines (<span style="color: #007800;">$DEL_CHARS</span> characters)&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #ff0000;">&quot;Added <span style="color: #007800;">$ADD_LINES</span> lines (<span style="color: #007800;">$ADD_CHARS</span> characters)&quot;</span></pre></div></div>

<p>Save this as <code>$HOME/bin/svnstat</code>, then execute it passing in a revision, e.g. <code>$ svnstat 1001</code></p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">$ svnstat 61765
Removed 113 lines (4913 characters)
Added 63 lines (2975 characters)</pre></div></div>

<p>If you want to then see your daily net lines of code, hook this up to an <code>egrep</code>&#8216;d <code>svn log</code>, piped into <code>xargs</code>.</p>
<p><strong>Update 1/13/2010:</strong><br />
I cleaned up the &#8220;get_field&#8221; function to use a single <code>sed</code> command with backreferences rather than piping the string through <code>tr</code>, <code>sed</code>, and <code>cut</code>.</p>
<p>Also updated the initial calculation of <code>DIFF_COUNTS</code> and <code>ADD_COUNTS</code> to only require 1 single <code>svn diff</code> execution.  Used <code>echo -e</code> to solve the newline issue I was having on a first failed attempt.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2010/01/recent-svn-commit-statistics/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Developing AIR apps for the desktop using the Flex 3 SDK for FREE</title>
		<link>http://www.mike-griffith.com/blog/2010/01/developing-air-apps-for-the-desktop-using-the-flex-3-sdk-for-free/</link>
		<comments>http://www.mike-griffith.com/blog/2010/01/developing-air-apps-for-the-desktop-using-the-flex-3-sdk-for-free/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 22:03:12 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[adobe-air]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[sdk]]></category>
		<category><![CDATA[tips & tricks]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=308</guid>
		<description><![CDATA[One of the greatest things about Flex and Air is the low barrier to entry for us software geeks.  There&#8217;s nothing stopping any non-flash software dev from writing some kickass desktop apps.  There&#8217;s no reason you have to buy anything to start writing, testing, and distributing Adobe Air apps.  You don&#8217;t need [...]]]></description>
			<content:encoded><![CDATA[<p>One of the greatest things about Flex and Air is the low barrier to entry for us software geeks.  There&#8217;s nothing stopping any non-flash software dev from writing some kickass desktop apps.  There&#8217;s no reason you have to buy anything to start writing, testing, and distributing Adobe Air apps.  You don&#8217;t need their <a href="http://www.adobe.com/go/buyflexbuilder_std" target="_blank">fancy (unsupported) IDE, FlexBuilder</a>.  You don&#8217;t need to purchase a code signing certificate.  You don&#8217;t have to pay fees to get into a app store.  All you need is a terminal, some links to good samples and tutorials, and this article to get you moving in the right (hopefully) direction.</p>
<p><strong>Disclaimer</strong><br />
I&#8217;ve only spent a grand total of about 3 hours researching and coding anything flash-related.  Any information distributed here could lead you down a long and lonesome path &#8212; however, more likely, it&#8217;ll get your feet wet enough so that you can take off on your own adventure.</p>
<p><strong>Prerequisistes:</strong></p>
<ol>
<li>Download and install the <a href="http://www.adobe.com/cfusion/entitlement/index.cfm?e=flex3sdk" target="_blank">Adobe Flex SDK</a>.  I&#8217;m using Adobe Flex version 3.4 on Ubuntu 9.10</li>
<li>Have basic familiarity with a command line terminal (Linux, cygwin, etc.)</li>
</ol>
<p>Good so far?  Great.  Here&#8217;s what I hope to help you understand, because it was what I struggled with.</p>
<ol>
<li>Filesystem layout for your application</li>
<li>Writing your application, coding mxml and ActionScript</li>
<li>Packaging and signing your application</li>
<li>Installing and running your new application</li>
</ol>
<p>There are a lot of other more advanced topics that I&#8217;d like to learn myself, including but not limited to:</p>
<ol>
<li>Using third party libraries (.swc&#8217;s)</li>
<li>Unit testing your application with ASUnit</li>
<li>Upgrading your life with ANT buildscripts</li>
</ol>
<p><strong>Steps to writing your first air application:</strong></p>
<ol>
<li>Create a directory to hold this project and its source code.

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">    $ mkdir myairapp
    $ mkdir myairapp/src</pre></div></div>

</li>
<li>Generate a new .mxml file inside your source code folder.

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">    $ vim myairapp/src/MyAirApp.mxml</pre></div></div>

<p>FlexBuilder admittedly helps a ton here, but you don&#8217;t need it.  This file defines what your application will look like, using XML markup to indicate panes, widgets, and all sorts of fun stuff.  However, there&#8217;s no reason it can&#8217;t be done in VIM or your favorite text editor.  This file (along with your actionscript files) will likely be the most volatile part of the project as you continue to code.  Here&#8217;s a basic template you can download and use.  Stick this in your root source folder.</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;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:WindowedApplication</span> <span style="color: #000066;">xmlns:mx</span>=<span style="color: #ff0000;">&quot;http://www.adobe.com/2006/mxml&quot;</span> <span style="color: #000066;">xmlns:ns1</span>=<span style="color: #ff0000;">&quot;*&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000066;">layout</span>=<span style="color: #ff0000;">&quot;absolute&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;300&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;200&quot;</span> <span style="color: #000066;">showTitleBar</span>=<span style="color: #ff0000;">&quot;false&quot;</span> <span style="color: #000066;">showStatusBar</span>=<span style="color: #ff0000;">&quot;false&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000066;">currentState</span>=<span style="color: #ff0000;">&quot;load_state&quot;</span> <span style="color: #000066;">creationComplete</span>=<span style="color: #ff0000;">&quot;init()&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:states<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:State</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;load_state&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/mx:State<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:states<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:Script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #339933;">&lt;![CDATA[</span>
<span style="color: #339933;">        private function init():void {</span>
<span style="color: #339933;">        }</span>
<span style="color: #339933;">    ]]&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:Script<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:WindowedApplication<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

</li>
<li>Update the &#8220;mx:states&#8221;, which will be used to represent different viewports/panes within this app.  Each state will have a button, and it will be a different color for each.  The first, named &#8220;load_state&#8221;, has a green button as defined by the &#8220;fillColors&#8221; attribute.  The second, named &#8220;clicked_state&#8221;, has a blue button.

<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;mx:states<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:State</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;load_state&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:AddChild</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">&quot;lastChild&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:Button</span> <span style="color: #000066;">x</span>=<span style="color: #ff0000;">&quot;24&quot;</span> <span style="color: #000066;">y</span>=<span style="color: #ff0000;">&quot;36&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;250&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;122&quot;</span> <span style="color: #000066;">fillAlphas</span>=<span style="color: #ff0000;">&quot;[1.0, 1.0]&quot;</span></span>
<span style="color: #009900;">                            <span style="color: #000066;">fillColors</span>=<span style="color: #ff0000;">&quot;[#00FF00, #00FF00]&quot;</span> <span style="color: #000066;">label</span>=<span style="color: #ff0000;">&quot;Page 1&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:AddChild<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:State<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:State</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;clicked_state&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:AddChild</span> <span style="color: #000066;">position</span>=<span style="color: #ff0000;">&quot;lastChild&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:Button</span> <span style="color: #000066;">x</span>=<span style="color: #ff0000;">&quot;24&quot;</span> <span style="color: #000066;">y</span>=<span style="color: #ff0000;">&quot;36&quot;</span> <span style="color: #000066;">width</span>=<span style="color: #ff0000;">&quot;250&quot;</span> <span style="color: #000066;">height</span>=<span style="color: #ff0000;">&quot;122&quot;</span> <span style="color: #000066;">fillAlphas</span>=<span style="color: #ff0000;">&quot;[1.0, 1.0]&quot;</span></span>
<span style="color: #009900;">                            <span style="color: #000066;">fillColors</span>=<span style="color: #ff0000;">&quot;[#0000FF, #0000FF]&quot;</span> <span style="color: #000066;">label</span>=<span style="color: #ff0000;">&quot;Page 2&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:AddChild<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:state<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/mx:states<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

</li>
<li>Write some actionscript code to toggle between states when you click the buttons.  The currently visible one can be read and changed based on a global variable, `currentState`.

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">        <span style="color: #003366; font-weight: bold;">private</span> <span style="color: #003366; font-weight: bold;">function</span> onState1ButtonClick<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span><span style="color: #000066; font-weight: bold;">void</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #006600; font-style: italic;">// Go to the 2nd &quot;state&quot; when this button is clicked</span>
            currentState <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;clicked_state&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #003366; font-weight: bold;">private</span> <span style="color: #003366; font-weight: bold;">function</span> onState2ButtonClick<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span><span style="color: #000066; font-weight: bold;">void</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #006600; font-style: italic;">// Return to the initial &quot;state&quot; when this button is clicked</span>
            currentState <span style="color: #339933;">=</span> <span style="color: #3366CC;">&quot;load_state&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span></pre></div></div>

<p>    Then, wire-up the events so that clicking will actually trigger the code.  Add a &#8220;click&#8221; attribute to the &#8220;mx:Button&#8221; element to match</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;mx:Button</span> ... <span style="color: #000066;">click</span>=<span style="color: #ff0000;">&quot;onState1ButtonClick()&quot;</span> ... <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mx:Button</span> ... <span style="color: #000066;">click</span>=<span style="color: #ff0000;">&quot;onState2ButtonClick()&quot;</span> ... <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

</li>
<li>The last thing you&#8217;ll need before you can play with your masterpiece is your &#8220;application.xml&#8221; file. Stick this in the main project directory, rather than in with your source code.

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">    $ vim myairapp/MyAirApp-app.xml</pre></div></div>

<p>See the <a href="http://help.adobe.com/en_US/AIR/1.5/devappshtml/WS5b3ccc516d4fbf351e63e3d118666ade46-7ecc.html#WS5b3ccc516d4fbf351e63e3d118666ade46-7fad" target="_blank">Adobe AIR documentation</a> for an example.
</li>
</ol>
<p><strong>Packaging, code signing, generating .air, and installing</strong><br />
Your app is *almost* ready to run.  The basic steps to get the app transformeed from source to binary are:</p>
<ol>
<li>Generate .swf with amxmlc</li>
<li>Generate code signing certificate with adt (alternatively, if you&#8217;re a linux whizbang you can use openssl)</li>
<li>Tweak your application .xml.  Link to .swf from step #1</li>
<li>Package it up into .air with adt</li>
</ol>
<p>I&#8217;ve created a shell script to automate the package, code signing, and generating air step. Copy this into &#8220;myairapp/build.sh&#8221;</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #007800;">APP_NAME</span>=MyAirApp
<span style="color: #007800;">FLEX_BIN</span>=<span style="color: #000000; font-weight: bold;">/</span>opt<span style="color: #000000; font-weight: bold;">/</span>flex_sdk_3.4<span style="color: #000000; font-weight: bold;">/</span>bin
&nbsp;
<span style="color: #666666; font-style: italic;"># build a .swf</span>
<span style="color: #c20cb9; font-weight: bold;">mkdir</span> release
<span style="color: #007800;">$FLEX_BIN</span><span style="color: #000000; font-weight: bold;">/</span>amxmlc .<span style="color: #000000; font-weight: bold;">/</span>src<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APP_NAME</span>.mxml <span style="color: #660033;">-output</span> .<span style="color: #000000; font-weight: bold;">/</span>release<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APP_NAME</span>.swf
&nbsp;
<span style="color: #666666; font-style: italic;"># generate code signing certificate</span>
<span style="color: #007800;">$FLEX_BIN</span><span style="color: #000000; font-weight: bold;">/</span>adt <span style="color: #660033;">-certificate</span> <span style="color: #660033;">-cn</span> <span style="color: #007800;">$APP_NAME</span> <span style="color: #000000;">1024</span>-RSA cert.pfx <span style="color: #007800;">$APP_NAME</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># package into .air</span>
<span style="color: #007800;">$FLEX_BIN</span><span style="color: #000000; font-weight: bold;">/</span>adt <span style="color: #660033;">-package</span> <span style="color: #660033;">-storetype</span> pkcs12 <span style="color: #660033;">-keystore</span> cert.pfx \
    <span style="color: #660033;">-storepass</span> <span style="color: #007800;">$APP_NAME</span> \
    .<span style="color: #000000; font-weight: bold;">/</span>release<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APP_NAME</span>.air .<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APP_NAME</span>-app.xml .<span style="color: #000000; font-weight: bold;">/</span>release<span style="color: #000000; font-weight: bold;">/</span><span style="color: #007800;">$APP_NAME</span>.swf \
    <span style="color: #666666; font-style: italic;"># Uncomment the following lines if you have icons that you have created</span>
    <span style="color: #666666; font-style: italic;">#-C assets icon_16.png \</span>
    <span style="color: #666666; font-style: italic;">#-C assets icon_32.png \</span>
    <span style="color: #666666; font-style: italic;">#-C assets icon_48.png</span></pre></div></div>

<p>Now execute the build script. Assuming there were no errors, your new application is ready to be installed.  Open up the newly generated .air file in the release directory, and the air installer should walk you through the install process.</p>
<p>If you want to start getting fancier, the next step you&#8217;ll want to do is externalize your ActionScript code.  All you have to do is create a &#8220;.as&#8221; file (or an entire directory if you want to break up your code into namespaces), stick it next to the .mxml, and then you&#8217;ll be able to &#8220;import&#8221; it and use functions, classes, etc from it.  I prefer to keep the actual event wiring within the .mxml code, but don&#8217;t let it get too cluttered.</p>
<p>Additionally, you&#8217;ll want to start adding assets (icons, images, sound files, etc) to your project.  Create a separate &#8220;assets&#8221; directory to hold them.</p>
<p>Additional Flex development references</p>
<ul>
<li><a href="http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK">http://opensource.adobe.com/wiki/display/flexsdk/Flex+SDK</a></li>
<li><a href="http://www.adobe.com/devnet/flex/">http://www.adobe.com/devnet/flex/</a></li>
<li><a href="http://flex.org/">http://flex.org/</a></li>
<li>To find great examples, search Google for &#8220;flex site:googlecode.com&#8221;</li>
</ul>
<p>More help with compiling and packaging:</p>
<ul>
<li><a href="http://www.adobe.com/devnet/air/articles/signing_air_applications_print.html">http://www.adobe.com/devnet/air/articles/signing_air_applications_print.html</a></li>
<li><a href="http://blog.devsandbox.co.uk/?p=163">http://blog.devsandbox.co.uk/?p=163</a></li>
<li><a href="http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_13.html#150640">http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_13.html#150640</a></li>
</ul>
<p>Best of luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2010/01/developing-air-apps-for-the-desktop-using-the-flex-3-sdk-for-free/feed/</wfw:commentRss>
		<slash:comments>0</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[coding]]></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[coding]]></category>
		<category><![CDATA[best practices]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[pycon]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[unit testing]]></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>Google, I love you, but you&#8217;re starting to freak me out.</title>
		<link>http://www.mike-griffith.com/blog/2009/03/google-i-love-you-but-youre-starting-to-freak-me-out/</link>
		<comments>http://www.mike-griffith.com/blog/2009/03/google-i-love-you-but-youre-starting-to-freak-me-out/#comments</comments>
		<pubDate>Fri, 13 Mar 2009 04:17:46 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[social]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=294</guid>
		<description><![CDATA[I Just got an email from Google, describing a new feature of AdSense dubbed &#8220;interest-based advertising.&#8221;
I don&#8217;t think it&#8217;s any shock that Google has the data to segment users based on their browsing habits.  The shocker to me is that they&#8217;re making the result of that segmentation available to webmasters everywhere.  
The full [...]]]></description>
			<content:encoded><![CDATA[<p>I Just got an email from Google, describing a new feature of AdSense dubbed &#8220;interest-based advertising.&#8221;</p>
<p>I don&#8217;t think it&#8217;s any shock that Google has the data to segment users based on their browsing habits.  The shocker to me is that they&#8217;re making the result of that segmentation available to webmasters everywhere.  </p>
<p>The full text of the email is:</p>
<blockquote><p>
From: Google AdSense <adsense-noreply@google.com><br />
Subject: Introducing interest-based advertising &#8211; action required for your AdSense account</p>
<p>Hi,</p>
<p>We&#8217;re writing to let you know about the upcoming launch of interest-based advertising, which will require you to review and make any necessary changes to your site&#8217;s privacy policies. You&#8217;ll also see some new options on your Account Settings page.</p>
<p>Interest-based advertising will allow advertisers to show ads based on a user&#8217;s previous interactions with them, such as visits to advertiser website and also to reach users based on their interests (e.g. &#8220;sports enthusiast&#8221;).  To develop interest categories, we will recognize the types of web pages users visit throughout the Google content network.  As an example, if they visit a number of sports pages, we will add them to the &#8220;sports enthusiast&#8221; interest category.  To learn more about your associated account settings, please visit the AdSense Help Center at http://www.google.com/adsense/support/bin/topic.py?topic=20310.</p>
<p>As a result of this announcement, your privacy policy will now need to reflect the use of interest-based advertising. Please review the information at https://www.google.com/adsense/support/bin/answer.py?answer=100557 to ensure that your site&#8217;s privacy policies are up-to-date, and make any necessary changes by April 8, 2009.  Because publisher sites and laws vary across countries, we&#8217;re unfortunately unable to suggest specific privacy policy language.</p>
<p>For more information about interest-based advertising, you can also visit the Inside AdSense Blog at http://adsense.blogspot.com/2009/03/driving-monetization-with-ads-that.html.</p>
<p>We appreciate your participation and look forward to this upcoming enhancement.</p>
<p>Sincerely,</p>
<p>The Google AdSense Team</p>
<p>Email preferences: You have received this mandatory email service announcement to update you about important changes to your AdSense product or account.</p>
<p>Google Inc.<br />
1600 Amphitheatre Parkway<br />
Mountain View, CA 94043
</p></blockquote>
<p>One thing that has me thinking they&#8217;re less than purely evil is that <a href="http://www.google.com/ads/preferences/">they at least show you what they think you are in your personal ad preferences page</a>, and allow you some options for configuration.  However, it would take someone reasonably savvy to locate that page.</p>
<p>I&#8217;m interested to see where this goes.  I know it&#8217;s a big win for businesses that want better ad targeting, but this is clearly a big setback for privacy advocates.</p>
<p>Regardless, I really can&#8217;t wait to see the ad profile they assign me&#8230;  . o O ( <em>Computer nerd, mountain biking, porn addicted, binge drinker</em> )</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/03/google-i-love-you-but-youre-starting-to-freak-me-out/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>2009 MTB Race Schedule</title>
		<link>http://www.mike-griffith.com/blog/2009/03/2009-mtb-race-schedule/</link>
		<comments>http://www.mike-griffith.com/blog/2009/03/2009-mtb-race-schedule/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 21:33:07 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[sports]]></category>
		<category><![CDATA[cycling]]></category>
		<category><![CDATA[mtb]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=280</guid>
		<description><![CDATA[OMBC has published a tentative schedule of mountain bike races for 2009.  The madness begins this month! I won&#8217;t be able to make the first race, as it conflicts with PyCon, but I&#8217;m hoping to tear up Vulture&#8217;s Knob soon thereafter.  I&#8217;m getting antsy to get out there and see what all the [...]]]></description>
			<content:encoded><![CDATA[<p>OMBC has published a tentative schedule of mountain bike races for 2009.  The madness begins this month! I won&#8217;t be able to make the first race, as it conflicts with PyCon, but I&#8217;m hoping to tear up Vulture&#8217;s Knob soon thereafter.  I&#8217;m getting antsy to get out there and see what all the beer and potatoes has done to my fitness level.  Time shall tell.</p>
<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2009/03/mohican_downhill-214x300.jpg" alt="Riding at the Mohican Wilderness downhill mountain bike course" title="Riding at the Mohican Wilderness downhill mountain bike course" width="214" height="300" class="alignright size-medium wp-image-282" style="margin:0 0 0 10px; border:3px solid;" /></p>
<p><strong>OMBC Race Series</strong></p>
<ol>
<li>Mohican Wilderness &#8211; Loudonville (March 29)</li>
<li>Vulture&#8217;s Knob &#8211; Wooster (April 18)</li>
<li>Mount Wood Challenge &#8211; WV (May 3)</li>
<li>The Wilds &#8211; Zanesville (May 17)</li>
<li>Eastfork State Park &#8211; Bethel (June 28)</li>
<li>S&#038;S Trails &#8211; Mt. Perry (July 12)</li>
<li>Alum Creek State Park &#8211; Delaware (July 26)</li>
<li>Lake Hope SP &#8211; Nelsonville (August 2)</li>
<li>Caesar Creek SP &#8211; Waynesville (August 23)</li>
<li>Dillon XC Race &#8211; Zanesville (August 30)</li>
<li>Westbranch SP &#8211; Ravenna (September 27)</li>
<li>Mohican State Park &#8211; Loudonville (October 11)</li>
<li>Mohican Wilderness &#8211; Loudonville (October 25)</li>
</ol>
<p><strong>Endurance Events:</strong></p>
<ol>
<li>Mohican MTB100 (May 30)</li>
<li>Mohican Trail 100 (June 20-21)</li>
<li>12/24 Hours of Mohican (September 19-20)</li>
</ol>
<p><em>* Dates are subject to change.  See <a href="http://www.ombc.net/">www.ombc.net</a> for the latest and greatest info.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/03/2009-mtb-race-schedule/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Hey Ubuntu, just to let you know, I&#8217;m about to bend you to my will</title>
		<link>http://www.mike-griffith.com/blog/2009/02/hey-ubuntu-just-to-let-you-know-im-about-to-bend-you-to-my-will/</link>
		<comments>http://www.mike-griffith.com/blog/2009/02/hey-ubuntu-just-to-let-you-know-im-about-to-bend-you-to-my-will/#comments</comments>
		<pubDate>Tue, 24 Feb 2009 02:35:45 +0000</pubDate>
		<dc:creator>Mike</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[tips & tricks]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.mike-griffith.com/blog/?p=269</guid>
		<description><![CDATA[
After fighting with Ubuntu Hardy 8.04 for months to get WIFI working, I finally found a Dell driver [0] that worked on my HP laptop through ndiswrapper [1].
A few hours later with success claimed, I decided to upgrade to Ubuntu Intrepid 8.10, assuming I had conquered all possible obstacles and that anything in the future [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.mike-griffith.com/blog/wp-content/uploads/2009/02/ubuntu.png" alt="ubuntu" title="ubuntu" width="202" height="55" class="alignright size-full wp-image-272" /></p>
<p>After fighting with Ubuntu Hardy 8.04 for months to get WIFI working, I finally found a Dell driver [0] that worked on my HP laptop through ndiswrapper [1].</p>
<p>A few hours later with success claimed, I decided to upgrade to Ubuntu Intrepid 8.10, assuming I had conquered all possible obstacles and that anything in the future would be pithy.  Little did I realize, I was in for a world of hurt, as Ubuntu decided to muck with the guts of video/display drivers between 8.04 and 8.10. </p>
<p>After an initial upgrade, I was stuck with 800&#215;600 resolution using the crappy built-in display drivers.  I tried to activate the restricted Nvidia driver, but it hung and nothing happened.  I went to Nvidia&#8217;s website, downloaded their open-source driver, installed it as they suggested, and rebooted.  It looked great at first &#8212; the resolution was back to normal at the login window, but as soon as I logged-in, the screen went blank.  Stumped, I pressed ctrl+alt+f1, then ctrl+alt+del to reboot.  I went into the terminal, restored the original /etc/X11/xorg.conf.backup, and was able to get back in, but back to 800&#215;600.</p>
<p>Two full days later, I&#8217;ve finally got 1280&#215;800 resolution back on my laptop.  It appears that the auto-detected settings from Nvidia in my xorg.conf put in faulty horizontal sync and vertical refresh settings.</p>
<p>The proper settings are:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">    HorizSync       30.0 - 110.0
    VertRefresh     50.0 - 150.0</pre></div></div>

<p>With that, I was able to enable the nvidia driver and boot into gnome successfully.</p>
<p>Next, I decided to re-enable some desktop effects through the appearance manager.  I opened it up, enabled the medium-level of effects, and immediately got the f$@#%%ng black screen!!!  BLASTED!!! A reboot got me back to where I started.</p>
<p>This whole process is so frustrating.  Luckily, xkcd can provide some comic relief&#8230;<br />
<img src="http://www.mike-griffith.com/blog/wp-content/uploads/2009/02/cd_tray_fight.png" alt="cd_tray_fight" title="cd_tray_fight" width="500" height="503" class="aligncenter size-full wp-image-275" /></p>
<p>So that&#8217;s where I&#8217;m at now.  Hopefully I&#8217;ll figure something out soon, and update this post for any other HP laptop owners to reference.</p>
<p>Reference:<br />
[0] Dell wifi driver that worked with the HP Pavilion dv2715nr&#8217;s 14e4:4315 Broadcom card <a href="ftp://ftp.us.dell.com/network/R174291.exe">ftp://ftp.us.dell.com/network/R174291.exe</a><br />
[1] Instructions for ndiswrapper can be found at <a href="https://help.ubuntu.com/community/WifiDocs/Driver/Ndiswrapper">https://help.ubuntu.com/community/WifiDocs/Driver/Ndiswrapper</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mike-griffith.com/blog/2009/02/hey-ubuntu-just-to-let-you-know-im-about-to-bend-you-to-my-will/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
