<?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>lorenzo bolla&#039;s blog</title>
	<atom:link href="http://lbolla.info/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://lbolla.info/blog</link>
	<description></description>
	<lastBuildDate>Fri, 20 Apr 2012 13:08:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.1</generator>
		<item>
		<title>Pipelines in Python</title>
		<link>http://lbolla.info/blog/2012/04/20/pipelines-in-python/</link>
		<comments>http://lbolla.info/blog/2012/04/20/pipelines-in-python/#comments</comments>
		<pubDate>Fri, 20 Apr 2012 13:07:10 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[coroutine]]></category>
		<category><![CDATA[generator]]></category>
		<category><![CDATA[pipeline]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=411</guid>
		<description><![CDATA[Generators (PEP 255 &#8220;Simple Generators&#8221;) and Coroutines (PEP 342 &#8220;Coroutines via Enhanced Generators&#8221;) are the cleanest way I&#8217;ve come across so far to implement the concept of a &#8220;pipeline&#8221; in Python. First approximation A pipeline is made of: a Producer, that generates data; many Stages, that receive data from the previous stage and send it to [...]]]></description>
			<content:encoded><![CDATA[<p>Generators (<a href="http://www.python.org/dev/peps/pep-0255/">PEP 255 &#8220;Simple Generators&#8221;</a>) and Coroutines (<a href="http://www.python.org/dev/peps/pep-0342/">PEP 342 &#8220;Coroutines via Enhanced Generators&#8221;</a>) are the cleanest way I&#8217;ve come across so far to implement the concept of a &#8220;pipeline&#8221; in Python.</p>
<h2>First approximation</h2>
<p>A pipeline is made of:</p>
<ul>
<li>a <em>Producer</em>, that generates data;</li>
<li>many <em>Stage</em>s, that receive data from the previous stage and send it to the next;</li>
<li>a <em>Consumer</em>, that receives data from the last stage.</li>
</ul>
<p>The producer is a coroutine that only <em>send</em>s data, generated internally from some initial state. <em>Stage</em>s are coroutines that both receive and send messages. The <em>consumer</em> only receives data.</p>
<p>Chaining is done in function <em>pipeline</em>: each argument but the last is instantiated with an instance of the next stage. The full pipeline is <em>started</em> by issuing a <em>next</em> (or <em>send(None)</em>) to the <em>Producer</em>.</p>
<p>In the following example, a stream of integers is produced and pushed down the pipeline: each stage adds 1 and finally the result is printed in the consumer.</p>
<div id="gist-2428213" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="sd">&#39;&#39;&#39;Pipeline</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="sd">(yield) -&gt; receiver</span></div><div class='line' id='LC4'><span class="sd">.send -&gt; producer</span></div><div class='line' id='LC5'><span class="sd">&#39;&#39;&#39;</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="kn">import</span> <span class="nn">time</span></div><div class='line' id='LC8'><br/></div><div class='line' id='LC9'><span class="n">N</span> <span class="o">=</span> <span class="mi">0</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="k">def</span> <span class="nf">P</span><span class="p">(</span><span class="n">n</span><span class="p">):</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Producer: only .send (and yield as entry point).&#39;&#39;&#39;</span></div><div class='line' id='LC13'><br/></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">_f</span><span class="p">():</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">global</span> <span class="n">N</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">N</span> <span class="o">+=</span> <span class="mi">1</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">N</span></div><div class='line' id='LC19'><br/></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">yield</span>  <span class="c"># to &quot;start&quot;</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">_f</span><span class="p">())</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'><br/></div><div class='line' id='LC25'><span class="k">def</span> <span class="nf">S</span><span class="p">(</span><span class="n">n</span><span class="p">):</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Stage: both (yield) and .send.&#39;&#39;&#39;</span></div><div class='line' id='LC27'><br/></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">_f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Stage&#39;</span><span class="p">,</span> <span class="n">x</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span></div><div class='line' id='LC31'><br/></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">_f</span><span class="p">(</span><span class="n">r</span><span class="p">))</span></div><div class='line' id='LC35'><br/></div><div class='line' id='LC36'><br/></div><div class='line' id='LC37'><span class="k">def</span> <span class="nf">C</span><span class="p">():</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Consumer: only (yield).&#39;&#39;&#39;</span></div><div class='line' id='LC39'><br/></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">_f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Consumed&#39;</span><span class="p">,</span> <span class="n">x</span></div><div class='line' id='LC42'><br/></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">_f</span><span class="p">(</span><span class="n">r</span><span class="p">)</span></div><div class='line' id='LC46'><br/></div><div class='line' id='LC47'><br/></div><div class='line' id='LC48'><span class="k">def</span> <span class="nf">pipeline</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span></div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Chain stages together. Assumes the last is the consumer.&#39;&#39;&#39;</span></div><div class='line' id='LC50'><br/></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">c</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]()</span></div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">c</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">c</span></div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">for</span> <span class="n">S</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">args</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]):</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">s</span> <span class="o">=</span> <span class="n">S</span><span class="p">(</span><span class="n">t</span><span class="p">)</span></div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">s</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">s</span></div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">t</span></div><div class='line' id='LC59'><br/></div><div class='line' id='LC60'><br/></div><div class='line' id='LC61'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span></div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span> <span class="o">=</span> <span class="n">pipeline</span><span class="p">(</span><span class="n">P</span><span class="p">,</span> <span class="n">S</span><span class="p">,</span> <span class="n">S</span><span class="p">,</span> <span class="n">S</span><span class="p">,</span> <span class="n">C</span><span class="p">)</span></div><div class='line' id='LC63'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span><span class="o">.</span><span class="n">next</span><span class="p">()</span> <span class="c"># to &quot;start&quot;</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2428213/be115405f869977219599344fdd61847b5e6584b/pipeline_1.py" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2428213#file_pipeline_1.py" style="float:right;margin-right:10px;color:#666">pipeline_1.py</a>
            <a href="https://gist.github.com/2428213">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>Wrapping it up</h2>
<p>A pattern emerges, so we&#8217;d better wrap it up in a class. Moreover, let&#8217;s split the &#8220;architecture&#8221; of the pipeline from the behavior of each stage.</p>
<div id="gist-2428213" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="sd">&#39;&#39;&#39;Pipeline</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="sd">(yield) -&gt; receiver</span></div><div class='line' id='LC4'><span class="sd">.send -&gt; producer</span></div><div class='line' id='LC5'><br/></div><div class='line' id='LC6'><span class="sd">Provide initial state to producer, avoiding globals.</span></div><div class='line' id='LC7'><span class="sd">Stop iteration after a bit.</span></div><div class='line' id='LC8'><span class="sd">Wrap in nice class.</span></div><div class='line' id='LC9'><span class="sd">&#39;&#39;&#39;</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><br/></div><div class='line' id='LC12'><span class="k">class</span> <span class="nc">StopPipeline</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">pass</span> </div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC16'><span class="k">class</span> <span class="nc">Pipeline</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Chain stages together. Assumes the last is the consumer.&#39;&#39;&#39;</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">c</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">C</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">c</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">c</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">for</span> <span class="n">stg</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]):</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">s</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">S</span><span class="p">(</span><span class="n">stg</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">s</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">s</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">P</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">t</span><span class="p">)</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span> <span class="o">=</span> <span class="n">p</span></div><div class='line' id='LC30'><br/></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">initial_state</span><span class="p">):</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">try</span><span class="p">:</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">initial_state</span><span class="p">)</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span><span class="o">.</span><span class="n">close</span><span class="p">()</span></div><div class='line' id='LC36'><br/></div><div class='line' id='LC37'><br/></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">P</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Producer: only .send (and yield as entry point).&#39;&#39;&#39;</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">state</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span>  <span class="c"># get initial state</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">try</span><span class="p">:</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">res</span><span class="p">,</span> <span class="n">state</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">state</span><span class="p">)</span></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">except</span> <span class="n">StopPipeline</span><span class="p">:</span></div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span></div><div class='line' id='LC48'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">res</span><span class="p">)</span></div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC50'><br/></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">S</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Stage: both (yield) and .send.&#39;&#39;&#39;</span></div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">))</span></div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC61'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">C</span><span class="p">(</span><span class="n">f</span><span class="p">):</span></div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Consumer: only (yield).&#39;&#39;&#39;</span></div><div class='line' id='LC63'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC64'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC65'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC66'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">)</span></div><div class='line' id='LC67'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC68'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC69'><span class="k">def</span> <span class="nf">produce</span><span class="p">(</span><span class="n">state</span><span class="p">):</span></div><div class='line' id='LC70'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Given a state, produce a result and the next state.&#39;&#39;&#39;</span></div><div class='line' id='LC71'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kn">import</span> <span class="nn">time</span></div><div class='line' id='LC72'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">state</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span></div><div class='line' id='LC73'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">raise</span> <span class="n">StopPipeline</span><span class="p">(</span><span class="s">&#39;Enough!&#39;</span><span class="p">)</span></div><div class='line' id='LC74'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> </div><div class='line' id='LC75'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">state</span><span class="p">,</span> <span class="n">state</span> <span class="o">+</span> <span class="mi">1</span></div><div class='line' id='LC76'><br/></div><div class='line' id='LC77'><br/></div><div class='line' id='LC78'><span class="k">def</span> <span class="nf">stage</span><span class="p">(</span><span class="n">x</span><span class="p">):</span></div><div class='line' id='LC79'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Stage&#39;</span><span class="p">,</span> <span class="n">x</span></div><div class='line' id='LC80'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">1</span></div><div class='line' id='LC81'><br/></div><div class='line' id='LC82'><br/></div><div class='line' id='LC83'><span class="k">def</span> <span class="nf">consume</span><span class="p">(</span><span class="n">x</span><span class="p">):</span></div><div class='line' id='LC84'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Consumed&#39;</span><span class="p">,</span> <span class="n">x</span></div><div class='line' id='LC85'><br/></div><div class='line' id='LC86'><br/></div><div class='line' id='LC87'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span></div><div class='line' id='LC88'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">(</span></div><div class='line' id='LC89'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">produce</span><span class="p">,</span></div><div class='line' id='LC90'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">stage</span><span class="p">,</span></div><div class='line' id='LC91'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">stage</span><span class="p">,</span></div><div class='line' id='LC92'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">stage</span><span class="p">,</span></div><div class='line' id='LC93'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">consume</span><span class="p">,</span></div><div class='line' id='LC94'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">)</span></div><div class='line' id='LC95'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">initial_state</span> <span class="o">=</span> <span class="mi">0</span></div><div class='line' id='LC96'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">(</span><span class="n">initial_state</span><span class="p">)</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2428213/cd1c34e86aca8804c7d8e53a556242635b4f7176/pipeline_3.py" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2428213#file_pipeline_3.py" style="float:right;margin-right:10px;color:#666">pipeline_3.py</a>
            <a href="https://gist.github.com/2428213">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>More useful example</h2>
<p>As a more interesting application, here is how to use a pipeline to implement a simple crawler, to download links from <a href="http://news.ycombinator.com/">http://news.ycombinator.com/</a> and find all the posts where the word &#8220;Python&#8221; is mentioned.</p>
<div id="gist-2428213" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="sd">&#39;&#39;&#39;Pipeline</span></div><div class='line' id='LC2'><span class="sd">        </span></div><div class='line' id='LC3'><span class="sd">(yield) -&gt; receiver</span></div><div class='line' id='LC4'><span class="sd">.send -&gt; producer</span></div><div class='line' id='LC5'><span class="sd">        </span></div><div class='line' id='LC6'><span class="sd">Provide initial state to producer, avoiding globals.</span></div><div class='line' id='LC7'><span class="sd">Stop iteration after a bit.</span></div><div class='line' id='LC8'><span class="sd">Wrap in nice class.</span></div><div class='line' id='LC9'><span class="sd">Simple crawler to check if &quot;python&quot; was mentioned on HN.</span></div><div class='line' id='LC10'><span class="sd">            </span></div><div class='line' id='LC11'><span class="sd">&#39;&#39;&#39;</span>     </div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC14'><span class="k">class</span> <span class="nc">StopPipeline</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">pass</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC18'><span class="k">class</span> <span class="nc">Pipeline</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Chain stages together. Assumes the last is the consumer.&#39;&#39;&#39;</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">c</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">C</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">c</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">c</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">for</span> <span class="n">stg</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]):</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">s</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">S</span><span class="p">(</span><span class="n">stg</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">s</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">s</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">P</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">t</span><span class="p">)</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span> <span class="o">=</span> <span class="n">p</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">initial_state</span><span class="p">):</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">try</span><span class="p">:</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">initial_state</span><span class="p">)</span></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span><span class="o">.</span><span class="n">close</span><span class="p">()</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">P</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Producer: only .send (and yield as entry point).&#39;&#39;&#39;</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">state</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span>  <span class="c"># get initial state</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">try</span><span class="p">:</span></div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">res</span><span class="p">,</span> <span class="n">state</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">state</span><span class="p">)</span></div><div class='line' id='LC48'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">except</span> <span class="n">StopPipeline</span><span class="p">:</span></div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span></div><div class='line' id='LC50'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">res</span><span class="p">)</span></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC52'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">S</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Stage: both (yield) and .send.&#39;&#39;&#39;</span></div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">))</span></div><div class='line' id='LC60'><br/></div><div class='line' id='LC61'><br/></div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC63'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">C</span><span class="p">(</span><span class="n">f</span><span class="p">):</span></div><div class='line' id='LC64'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Consumer: only (yield).&#39;&#39;&#39;</span></div><div class='line' id='LC65'><br/></div><div class='line' id='LC66'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC67'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC68'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">)</span></div><div class='line' id='LC69'><br/></div><div class='line' id='LC70'><br/></div><div class='line' id='LC71'><span class="k">def</span> <span class="nf">produce</span><span class="p">((</span><span class="n">urls</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">domain</span><span class="p">)):</span></div><div class='line' id='LC72'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Given a state, produce a result and the next state.&#39;&#39;&#39;</span></div><div class='line' id='LC73'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kn">import</span> <span class="nn">urllib2</span></div><div class='line' id='LC74'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kn">import</span> <span class="nn">re</span></div><div class='line' id='LC75'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC76'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">nurls</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">urls</span><span class="p">)</span></div><div class='line' id='LC77'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">nurls</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span></div><div class='line' id='LC78'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">raise</span> <span class="n">StopPipeline</span><span class="p">(</span><span class="s">&#39;No more urls&#39;</span><span class="p">)</span></div><div class='line' id='LC79'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">else</span><span class="p">:</span></div><div class='line' id='LC80'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Queue </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">nurls</span></div><div class='line' id='LC81'><br/></div><div class='line' id='LC82'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">url</span> <span class="o">=</span> <span class="n">urls</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span></div><div class='line' id='LC83'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">doc</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span></div><div class='line' id='LC84'><br/></div><div class='line' id='LC85'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">links</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;href=&quot;(http.+?)&quot;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="n">doc</span><span class="p">)</span></div><div class='line' id='LC86'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">urls</span><span class="o">.</span><span class="n">update</span><span class="p">([</span><span class="n">l</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">links</span> <span class="k">if</span> <span class="n">domain</span> <span class="ow">in</span> <span class="n">l</span> <span class="ow">and</span> <span class="n">l</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">])</span></div><div class='line' id='LC87'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">url</span><span class="p">)</span></div><div class='line' id='LC88'><br/></div><div class='line' id='LC89'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">doc</span><span class="p">),</span> <span class="p">(</span><span class="n">urls</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">domain</span><span class="p">)</span></div><div class='line' id='LC90'><br/></div><div class='line' id='LC91'><br/></div><div class='line' id='LC92'><span class="k">def</span> <span class="nf">stage</span><span class="p">((</span><span class="n">url</span><span class="p">,</span> <span class="n">doc</span><span class="p">)):</span></div><div class='line' id='LC93'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="s">&#39;python&#39;</span> <span class="ow">in</span> <span class="n">doc</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span></div><div class='line' id='LC94'><br/></div><div class='line' id='LC95'><br/></div><div class='line' id='LC96'><span class="k">def</span> <span class="nf">consume</span><span class="p">((</span><span class="n">url</span><span class="p">,</span> <span class="n">haskell</span><span class="p">)):</span></div><div class='line' id='LC97'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">haskell</span><span class="p">:</span></div><div class='line' id='LC98'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Python mentioned in </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">url</span></div><div class='line' id='LC99'><br/></div><div class='line' id='LC100'><br/></div><div class='line' id='LC101'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span></div><div class='line' id='LC102'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">(</span></div><div class='line' id='LC103'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">produce</span><span class="p">,</span></div><div class='line' id='LC104'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">stage</span><span class="p">,</span></div><div class='line' id='LC105'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">consume</span><span class="p">,</span></div><div class='line' id='LC106'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">)</span></div><div class='line' id='LC107'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">urls</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;http://news.ycombinator.com&#39;</span><span class="p">}</span></div><div class='line' id='LC108'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">domain</span> <span class="o">=</span> <span class="s">&#39;ycombinator.com&#39;</span></div><div class='line' id='LC109'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">((</span><span class="n">urls</span><span class="p">,</span> <span class="nb">set</span><span class="p">(),</span> <span class="n">domain</span><span class="p">))</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2428213/da37fc536e69243b13792db2174d222f7b0518ff/pipeline_4.py" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2428213#file_pipeline_4.py" style="float:right;margin-right:10px;color:#666">pipeline_4.py</a>
            <a href="https://gist.github.com/2428213">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<h2>Cleaning things up</h2>
<p>Things are still far from clean and bulletproof. One step in the right direction is to follow the suggestions found in <a href="http://www.dabeaz.com/Fcoroutines/Coroutines.pdf">David Beazley&#8217;s presentation on coroutines</a>.</p>
<div id="gist-2428213" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="sd">&#39;&#39;&#39;Pipeline</span></div><div class='line' id='LC2'><span class="sd">    </span></div><div class='line' id='LC3'><span class="sd">(yield) -&gt; receiver</span></div><div class='line' id='LC4'><span class="sd">.send -&gt; producer</span></div><div class='line' id='LC5'><span class="sd">            </span></div><div class='line' id='LC6'><span class="sd">Provide initial state to producer, avoiding globals.</span></div><div class='line' id='LC7'><span class="sd">Stop iteration after a bit.</span></div><div class='line' id='LC8'><span class="sd">Wrap in nice class.</span></div><div class='line' id='LC9'><span class="sd">Simple crawler to check if &quot;python&quot; was mentioned on HN.</span></div><div class='line' id='LC10'><span class="sd">Some improvements after: http://www.dabeaz.com/Fcoroutines/Coroutines.pdf</span></div><div class='line' id='LC11'><span class="sd">    - coroutine decorator</span></div><div class='line' id='LC12'><span class="sd">    - catch GeneratorExit</span></div><div class='line' id='LC13'><span class="sd">    </span></div><div class='line' id='LC14'><span class="sd">&#39;&#39;&#39;</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC16'><span class="kn">from</span> <span class="nn">contextlib</span> <span class="kn">import</span> <span class="n">contextmanager</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'><span class="k">def</span> <span class="nf">coroutine</span><span class="p">(</span><span class="n">f</span><span class="p">):</span></div><div class='line' id='LC20'><br/></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">cr</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">cr</span><span class="o">.</span><span class="n">next</span><span class="p">()</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">cr</span></div><div class='line' id='LC25'><br/></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="n">start</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC29'><span class="nd">@contextmanager</span></div><div class='line' id='LC30'><span class="k">def</span> <span class="nf">close_on_exit</span><span class="p">(</span><span class="n">n</span><span class="p">):</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">try</span><span class="p">:</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">yield</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">except</span> <span class="ne">GeneratorExit</span><span class="p">:</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">close</span><span class="p">()</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC37'><span class="k">class</span> <span class="nc">StopPipeline</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">pass</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC40'><br/></div><div class='line' id='LC41'><span class="k">class</span> <span class="nc">Pipeline</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Chain stages together. Assumes the last is the consumer.&#39;&#39;&#39;</span></div><div class='line' id='LC43'><br/></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">):</span></div><div class='line' id='LC45'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">c</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">C</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">c</span></div><div class='line' id='LC47'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">for</span> <span class="n">stg</span> <span class="ow">in</span> <span class="nb">reversed</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]):</span></div><div class='line' id='LC48'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">s</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">S</span><span class="p">(</span><span class="n">stg</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span></div><div class='line' id='LC49'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">t</span> <span class="o">=</span> <span class="n">s</span></div><div class='line' id='LC50'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="o">.</span><span class="n">P</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">t</span><span class="p">)</span></div><div class='line' id='LC51'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span> <span class="o">=</span> <span class="n">p</span></div><div class='line' id='LC52'><br/></div><div class='line' id='LC53'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">initial_state</span><span class="p">):</span></div><div class='line' id='LC54'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">try</span><span class="p">:</span></div><div class='line' id='LC55'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">initial_state</span><span class="p">)</span></div><div class='line' id='LC56'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">except</span> <span class="ne">StopIteration</span><span class="p">:</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="bp">self</span><span class="o">.</span><span class="n">_pipeline</span><span class="o">.</span><span class="n">close</span><span class="p">()</span></div><div class='line' id='LC58'><br/></div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@coroutine</span></div><div class='line' id='LC61'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">P</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span></div><div class='line' id='LC62'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Producer: only .send (and yield as entry point).&#39;&#39;&#39;</span></div><div class='line' id='LC63'><br/></div><div class='line' id='LC64'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">state</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span>  <span class="c"># get initial state</span></div><div class='line' id='LC65'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">with</span> <span class="n">close_on_exit</span><span class="p">(</span><span class="n">n</span><span class="p">):</span></div><div class='line' id='LC66'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC67'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">try</span><span class="p">:</span></div><div class='line' id='LC68'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">res</span><span class="p">,</span> <span class="n">state</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">state</span><span class="p">)</span></div><div class='line' id='LC69'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">except</span> <span class="n">StopPipeline</span><span class="p">:</span></div><div class='line' id='LC70'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span></div><div class='line' id='LC71'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">res</span><span class="p">)</span></div><div class='line' id='LC72'><br/></div><div class='line' id='LC73'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC74'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@coroutine</span></div><div class='line' id='LC75'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">S</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span></div><div class='line' id='LC76'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Stage: both (yield) and .send.&#39;&#39;&#39;</span></div><div class='line' id='LC77'><br/></div><div class='line' id='LC78'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">with</span> <span class="n">close_on_exit</span><span class="p">(</span><span class="n">n</span><span class="p">):</span></div><div class='line' id='LC79'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC80'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC81'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">n</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">))</span></div><div class='line' id='LC82'><br/></div><div class='line' id='LC83'><br/></div><div class='line' id='LC84'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@staticmethod</span></div><div class='line' id='LC85'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="nd">@coroutine</span></div><div class='line' id='LC86'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">C</span><span class="p">(</span><span class="n">f</span><span class="p">):</span></div><div class='line' id='LC87'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Consumer: only (yield).&#39;&#39;&#39;</span></div><div class='line' id='LC88'><br/></div><div class='line' id='LC89'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c"># nothing to &quot;close&quot; here</span></div><div class='line' id='LC90'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">while</span> <span class="bp">True</span><span class="p">:</span></div><div class='line' id='LC91'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">r</span> <span class="o">=</span> <span class="p">(</span><span class="k">yield</span><span class="p">)</span></div><div class='line' id='LC92'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">f</span><span class="p">(</span><span class="n">r</span><span class="p">)</span></div><div class='line' id='LC93'><br/></div><div class='line' id='LC94'><br/></div><div class='line' id='LC95'><span class="k">def</span> <span class="nf">produce</span><span class="p">((</span><span class="n">urls</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">domain</span><span class="p">)):</span></div><div class='line' id='LC96'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="sd">&#39;&#39;&#39;Given a state, produce a result and the next state.&#39;&#39;&#39;</span></div><div class='line' id='LC97'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kn">import</span> <span class="nn">urllib2</span></div><div class='line' id='LC98'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="kn">import</span> <span class="nn">re</span></div><div class='line' id='LC99'><br/></div><div class='line' id='LC100'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">nurls</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">urls</span><span class="p">)</span></div><div class='line' id='LC101'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">nurls</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span></div><div class='line' id='LC102'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">raise</span> <span class="n">StopPipeline</span><span class="p">(</span><span class="s">&#39;No more urls&#39;</span><span class="p">)</span></div><div class='line' id='LC103'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">else</span><span class="p">:</span></div><div class='line' id='LC104'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Queue </span><span class="si">%d</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">nurls</span></div><div class='line' id='LC105'><br/></div><div class='line' id='LC106'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">url</span> <span class="o">=</span> <span class="n">urls</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span></div><div class='line' id='LC107'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">doc</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span></div><div class='line' id='LC108'><br/></div><div class='line' id='LC109'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">links</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&#39;href=&quot;(http.+?)&quot;&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">findall</span><span class="p">(</span><span class="n">doc</span><span class="p">)</span></div><div class='line' id='LC110'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">urls</span><span class="o">.</span><span class="n">update</span><span class="p">([</span><span class="n">l</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">links</span> <span class="k">if</span> <span class="n">domain</span> <span class="ow">in</span> <span class="n">l</span> <span class="ow">and</span> <span class="n">l</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">])</span></div><div class='line' id='LC111'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">url</span><span class="p">)</span></div><div class='line' id='LC112'><br/></div><div class='line' id='LC113'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">doc</span><span class="p">),</span> <span class="p">(</span><span class="n">urls</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">domain</span><span class="p">)</span></div><div class='line' id='LC114'><br/></div><div class='line' id='LC115'><br/></div><div class='line' id='LC116'><span class="k">def</span> <span class="nf">stage</span><span class="p">((</span><span class="n">url</span><span class="p">,</span> <span class="n">doc</span><span class="p">)):</span></div><div class='line' id='LC117'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">return</span> <span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="s">&#39;python&#39;</span> <span class="ow">in</span> <span class="n">doc</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span></div><div class='line' id='LC118'><br/></div><div class='line' id='LC119'><br/></div><div class='line' id='LC120'><span class="k">def</span> <span class="nf">consume</span><span class="p">((</span><span class="n">url</span><span class="p">,</span> <span class="n">haskell</span><span class="p">)):</span></div><div class='line' id='LC121'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">haskell</span><span class="p">:</span></div><div class='line' id='LC122'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">print</span> <span class="s">&#39;Python mentioned in </span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="n">url</span></div><div class='line' id='LC123'><br/></div><div class='line' id='LC124'><br/></div><div class='line' id='LC125'><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span></div><div class='line' id='LC126'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">(</span></div><div class='line' id='LC127'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">produce</span><span class="p">,</span></div><div class='line' id='LC128'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">stage</span><span class="p">,</span></div><div class='line' id='LC129'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">consume</span><span class="p">,</span></div><div class='line' id='LC130'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">)</span></div><div class='line' id='LC131'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">urls</span> <span class="o">=</span> <span class="p">{</span><span class="s">&#39;http://news.ycombinator.com&#39;</span><span class="p">}</span></div><div class='line' id='LC132'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">domain</span> <span class="o">=</span> <span class="s">&#39;ycombinator.com&#39;</span></div><div class='line' id='LC133'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">p</span><span class="o">.</span><span class="n">start</span><span class="p">((</span><span class="n">urls</span><span class="p">,</span> <span class="nb">set</span><span class="p">(),</span> <span class="n">domain</span><span class="p">))</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2428213/9eb17adc72ed003e80827e4cd887f4b6551cea25/pipeline_5.py" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2428213#file_pipeline_5.py" style="float:right;margin-right:10px;color:#666">pipeline_5.py</a>
            <a href="https://gist.github.com/2428213">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>The previous examples is by no means &#8220;production ready&#8221;, but maybe someone will find some good idea to apply to real world problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2012/04/20/pipelines-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Change engine to all tables in a MySQL database</title>
		<link>http://lbolla.info/blog/2012/04/05/change-engine-to-all-tables-in-a-mysql-database/</link>
		<comments>http://lbolla.info/blog/2012/04/05/change-engine-to-all-tables-in-a-mysql-database/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 15:53:57 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[alter table]]></category>
		<category><![CDATA[batch]]></category>
		<category><![CDATA[engine]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=397</guid>
		<description><![CDATA[Here is a simple shell script to change the engine of all the tables in a MySQL database: Just because, as usual, I keep forgetting these kind of things...]]></description>
			<content:encoded><![CDATA[<pre>Here is a simple shell script to change the engine of all the tables in a MySQL database:
<pre class="brush: bash; title: ; notranslate">#!/bin/sh
DBUSER=user
DBPWD=password
DBNAME=db
ENGINE=MyISAM
for t in `echo &quot;show tables&quot; | mysql -u$DBUSER -p$DBPWD --batch --skip-column-names $DBNAME`; do
mysql -u$DBUSER -p$DBPWD $DBNAME -e &quot;ALTER TABLE \`$t\` ENGINE = $ENGINE;&quot;;
done
</pre>
<p>Just because, as usual, I keep forgetting these kind of things...</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2012/04/05/change-engine-to-all-tables-in-a-mysql-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>hsenv</title>
		<link>http://lbolla.info/blog/2012/03/29/hsenv/</link>
		<comments>http://lbolla.info/blog/2012/03/29/hsenv/#comments</comments>
		<pubDate>Thu, 29 Mar 2012 10:04:55 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[hGetContents]]></category>
		<category><![CDATA[hsenv]]></category>
		<category><![CDATA[locale]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=389</guid>
		<description><![CDATA[﻿﻿﻿﻿If you have never used hsenv before, you should. It&#8217;s basically the Haskell&#8217;s equivalent of Python&#8217;s virtualenv. You can find a tweaked version of hsenv here: I&#8217;ve relaxed some requirements in order to make it install on newer GHC releases. Finally, if when using you hit this error: Then, you have a problem with your [...]]]></description>
			<content:encoded><![CDATA[<p>﻿﻿﻿﻿If you have never used <a href="https://github.com/Paczesiowa/hsenv">hsenv</a> before, you should. It&#8217;s basically the Haskell&#8217;s equivalent of Python&#8217;s <a href="http://pypi.python.org/pypi/virtualenv">virtualenv</a>.</p>
<p>You can find a <a href="https://github.com/lbolla/hsenv">tweaked version of hsenv here</a>: I&#8217;ve relaxed some requirements in order to make it install on newer GHC releases.</p>
<p>Finally, if when using you hit this error:</p>
<pre class="brush: bash; title: ; notranslate">
$ hsenv
Creating Virtual Haskell directory structure
Installing GHC
Initializing GHC Package database at /home/lollo/work/Unique/.hsenv/ghc_pkg_db
Copying necessary packages from original GHC package database
hsenv: fd:9: hGetContents: invalid argument (invalid byte sequence)
hsenv: thread blocked indefinitely in an MVar operation
</pre>
<p>Then, you have a problem with your locale. Follow the steps <a href="https://wiki.archlinux.org/index.php/Locale#Enabling_necessary_locales">here</a>, and retry.</p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2012/03/29/hsenv/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sudoku solver in Haskell</title>
		<link>http://lbolla.info/blog/2012/02/27/sudoku-solver-in-haskell/</link>
		<comments>http://lbolla.info/blog/2012/02/27/sudoku-solver-in-haskell/#comments</comments>
		<pubDate>Mon, 27 Feb 2012 17:27:16 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[sudoku]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/2012/02/27/sudoku-solver-in-haskell/</guid>
		<description><![CDATA[Recently, I&#8217;ve been challenged to write a Sudoku solver. Not knowing the rules and with only 30 minutes, I needed some help&#8230; So, in case someone asks me again, I&#8217;ve implemented the same algorithm in Haskell. I know that there are already a lot of other solutions, but, hey, it was fun!]]></description>
			<content:encoded><![CDATA[<p>Recently, I&#8217;ve been challenged to write a <a href="http://en.wikipedia.org/wiki/Sudoku">Sudoku</a> solver.</p>
<p>Not knowing the rules and with only 30 minutes, I needed some help&#8230; So, in case someone asks me again, I&#8217;ve implemented the same algorithm in Haskell.</p>
<div id="gist-1925630" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kr">module</span> <span class="nn">Main</span> <span class="kr">where</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'><span class="kr">import</span> <span class="nn">Data.List</span> <span class="p">(</span><span class="nf">nubBy</span><span class="p">,</span> <span class="nf">concat</span><span class="p">,</span> <span class="nf">findIndices</span><span class="p">)</span></div><div class='line' id='LC4'><span class="kr">import</span> <span class="nn">Control.Monad</span> <span class="p">(</span><span class="nf">liftM2</span><span class="p">,</span> <span class="nf">forM</span><span class="p">,</span> <span class="nf">join</span><span class="p">,</span> <span class="nf">guard</span><span class="p">)</span></div><div class='line' id='LC5'><span class="kr">import</span> <span class="nn">Data.Maybe</span> <span class="p">(</span><span class="nf">catMaybes</span><span class="p">,</span> <span class="nf">fromMaybe</span><span class="p">)</span></div><div class='line' id='LC6'><span class="kr">import</span> <span class="nn">Debug.Trace</span></div><div class='line' id='LC7'><br/></div><div class='line' id='LC8'><span class="kr">type</span> <span class="kt">Board</span> <span class="ow">=</span> <span class="kt">String</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'><span class="c1">--  Some boards</span></div><div class='line' id='LC11'><span class="c1">--  other examples: http://norvig.com/top95.txt</span></div><div class='line' id='LC12'><span class="nf">boards</span> <span class="ow">::</span> <span class="p">[</span><span class="kt">Board</span><span class="p">]</span></div><div class='line' id='LC13'><span class="nf">boards</span> <span class="ow">=</span> <span class="n">map</span> <span class="n">parseBoard</span> <span class="p">[</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s">&quot;4.....8.5.3..........7......2.....6.....8.4......1.......6.3.7.5..2.....1.4......&quot;</span><span class="p">,</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s">&quot;..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..&quot;</span><span class="p">,</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s">&quot;483921657967345821251876493548132976729564138136798245372689514814253769695417382&quot;</span><span class="p">,</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s">&quot;483...6..967345....51....93548132976..95641381367982453..689514814253769695417..2&quot;</span><span class="p">,</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s">&quot;..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..&quot;</span><span class="p">,</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s">&quot;.2.4.6..76..2.753...5.8.1.2.5..4.8.9.6159...34.28.3..1216...49.......31.9.8...2..&quot;</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">]</span></div><div class='line' id='LC21'><br/></div><div class='line' id='LC22'><span class="c1">--  The idea is to try all the possibilities by substituting &#39;.&#39; with all</span></div><div class='line' id='LC23'><span class="c1">--  possible chars and verifying the constraint at every step. When there are</span></div><div class='line' id='LC24'><span class="c1">--  no more dots to try, backtrack.</span></div><div class='line' id='LC25'><span class="c1">--  This is done in the List monad.</span></div><div class='line' id='LC26'><span class="nf">solve</span> <span class="ow">::</span> <span class="kt">Board</span> <span class="ow">-&gt;</span> <span class="p">[</span><span class="kt">Board</span><span class="p">]</span></div><div class='line' id='LC27'><span class="c1">--  solve board | trace (showBoard board) False = undefined</span></div><div class='line' id='LC28'><span class="nf">solve</span> <span class="n">board</span> <span class="ow">=</span> <span class="n">go</span> <span class="n">dotIdxs</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kr">where</span> <span class="n">dotIdxs</span> <span class="ow">=</span> <span class="n">findIndices</span> <span class="p">(</span><span class="o">==</span> <span class="sc">&#39;.&#39;</span><span class="p">)</span> <span class="n">board</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">go</span> <span class="ow">::</span> <span class="p">[</span><span class="kt">Int</span><span class="p">]</span> <span class="ow">-&gt;</span> <span class="p">[</span><span class="kt">Board</span><span class="p">]</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">go</span> <span class="kt">[]</span> <span class="ow">=</span> <span class="kr">do</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">-- no dots to try: just check constraints</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">guard</span> <span class="o">$</span> <span class="n">not</span> <span class="o">$</span> <span class="n">isObviouslyWrong</span> <span class="n">board</span></div><div class='line' id='LC34'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">return</span> <span class="n">board</span></div><div class='line' id='LC35'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">--  go dotIdxs | trace (show dotIdxs) False = undefined</span></div><div class='line' id='LC36'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">go</span> <span class="n">dotIdxs</span> <span class="ow">=</span> <span class="kr">do</span></div><div class='line' id='LC37'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">-- in the List monad: try all the possibilities</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">idx</span> <span class="ow">&lt;-</span> <span class="n">dotIdxs</span></div><div class='line' id='LC39'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">val</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="sc">&#39;1&#39;</span><span class="o">..</span><span class="sc">&#39;9&#39;</span><span class="p">]</span></div><div class='line' id='LC40'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kr">let</span> <span class="n">newBoard</span> <span class="ow">=</span> <span class="n">set</span> <span class="n">board</span> <span class="n">idx</span> <span class="n">val</span></div><div class='line' id='LC41'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">-- guard against invalid boards</span></div><div class='line' id='LC42'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">guard</span> <span class="o">$</span> <span class="n">not</span> <span class="o">$</span> <span class="n">isObviouslyWrong</span> <span class="n">board</span></div><div class='line' id='LC43'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">-- carry on with the good ones</span></div><div class='line' id='LC44'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">solve</span> <span class="n">newBoard</span></div><div class='line' id='LC45'><br/></div><div class='line' id='LC46'><span class="c1">--  Create a new board setting board[idx] = val</span></div><div class='line' id='LC47'><span class="nf">set</span> <span class="ow">::</span> <span class="kt">Board</span> <span class="ow">-&gt;</span> <span class="kt">Int</span> <span class="ow">-&gt;</span> <span class="kt">Char</span> <span class="ow">-&gt;</span> <span class="kt">Board</span></div><div class='line' id='LC48'><span class="nf">set</span> <span class="n">board</span> <span class="n">idx</span> <span class="n">val</span> <span class="ow">=</span> <span class="n">take</span> <span class="n">idx</span> <span class="n">board</span> <span class="o">++</span> <span class="p">[</span><span class="n">val</span><span class="p">]</span> <span class="o">++</span> <span class="n">drop</span> <span class="p">(</span><span class="n">idx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="n">board</span></div><div class='line' id='LC49'><br/></div><div class='line' id='LC50'><span class="nf">safeHead</span> <span class="ow">::</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="ow">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span></div><div class='line' id='LC51'><span class="nf">safeHead</span> <span class="kt">[]</span> <span class="ow">=</span> <span class="kt">Nothing</span></div><div class='line' id='LC52'><span class="nf">safeHead</span> <span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="kr">_</span><span class="p">)</span> <span class="ow">=</span> <span class="kt">Just</span> <span class="n">x</span></div><div class='line' id='LC53'><br/></div><div class='line' id='LC54'><span class="c1">--  Block of indices where to verify constraints</span></div><div class='line' id='LC55'><span class="nf">blockIdxs</span> <span class="ow">::</span> <span class="p">[[</span><span class="kt">Int</span><span class="p">]]</span></div><div class='line' id='LC56'><span class="nf">blockIdxs</span> <span class="ow">=</span> <span class="n">concat</span> <span class="p">[</span></div><div class='line' id='LC57'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">[[</span><span class="n">r</span> <span class="o">*</span> <span class="mi">9</span> <span class="o">+</span> <span class="n">c</span> <span class="o">|</span> <span class="n">c</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">8</span><span class="p">]]</span> <span class="o">|</span> <span class="n">r</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">8</span><span class="p">]]</span>  <span class="c1">-- rows</span></div><div class='line' id='LC58'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">,</span> <span class="p">[[</span><span class="n">r</span> <span class="o">*</span> <span class="mi">9</span> <span class="o">+</span> <span class="n">c</span> <span class="o">|</span> <span class="n">r</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">8</span><span class="p">]]</span> <span class="o">|</span> <span class="n">c</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">8</span><span class="p">]]</span>  <span class="c1">-- cols</span></div><div class='line' id='LC59'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">,</span> <span class="p">[[</span><span class="n">r</span> <span class="o">*</span> <span class="mi">9</span> <span class="o">+</span> <span class="n">c</span> <span class="o">|</span> <span class="n">r</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="n">rb</span><span class="o">..</span><span class="n">rb</span> <span class="o">+</span> <span class="mi">2</span><span class="p">],</span> <span class="n">c</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="n">cb</span><span class="o">..</span><span class="n">cb</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]]</span> <span class="o">|</span> <span class="n">rb</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="o">..</span><span class="mi">8</span><span class="p">],</span> <span class="n">cb</span> <span class="ow">&lt;-</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">3</span><span class="o">..</span><span class="mi">8</span><span class="p">]]</span>  <span class="c1">-- blocks</span></div><div class='line' id='LC60'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">]</span></div><div class='line' id='LC61'><br/></div><div class='line' id='LC62'><span class="c1">--  Check if constrains hold on grid</span></div><div class='line' id='LC63'><span class="c1">--  This means that block defined in blockIdxs does not contain duplicates, a</span></div><div class='line' id='LC64'><span class="c1">--  part from &#39;.&#39;</span></div><div class='line' id='LC65'><span class="nf">isObviouslyWrong</span> <span class="ow">::</span> <span class="kt">Board</span> <span class="ow">-&gt;</span> <span class="kt">Bool</span></div><div class='line' id='LC66'><span class="nf">isObviouslyWrong</span> <span class="n">board</span> <span class="ow">=</span> <span class="n">any</span> <span class="p">(</span><span class="n">isWrong</span> <span class="n">board</span><span class="p">)</span> <span class="n">blockIdxs</span></div><div class='line' id='LC67'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kr">where</span> <span class="n">isWrong</span> <span class="n">board</span> <span class="n">blockIdx</span> <span class="ow">=</span> <span class="n">hasDups</span> <span class="o">$</span> <span class="n">map</span> <span class="p">(</span><span class="n">board</span> <span class="o">!!</span><span class="p">)</span> <span class="n">blockIdx</span></div><div class='line' id='LC68'><br/></div><div class='line' id='LC69'><span class="c1">--  Check if a string has duplicates, a part from &#39;.&#39;</span></div><div class='line' id='LC70'><span class="nf">hasDups</span> <span class="ow">::</span> <span class="kt">String</span> <span class="ow">-&gt;</span> <span class="kt">Bool</span></div><div class='line' id='LC71'><span class="nf">hasDups</span> <span class="n">s</span> <span class="ow">=</span> <span class="n">nubBy</span> <span class="p">(</span><span class="nf">\</span><span class="n">x</span> <span class="n">y</span> <span class="ow">-&gt;</span> <span class="n">x</span> <span class="o">==</span> <span class="n">y</span> <span class="o">&amp;&amp;</span> <span class="n">x</span> <span class="o">/=</span> <span class="sc">&#39;.&#39;</span><span class="p">)</span> <span class="n">s</span> <span class="o">/=</span> <span class="n">s</span></div><div class='line' id='LC72'><br/></div><div class='line' id='LC73'><span class="c1">--  Filter out spurious chars</span></div><div class='line' id='LC74'><span class="nf">parseBoard</span> <span class="ow">::</span> <span class="kt">Board</span> <span class="ow">-&gt;</span> <span class="kt">Board</span></div><div class='line' id='LC75'><span class="nf">parseBoard</span> <span class="ow">=</span> <span class="n">filter</span> <span class="p">(`</span><span class="n">elem</span><span class="p">`</span> <span class="s">&quot;123456789.&quot;</span><span class="p">)</span></div><div class='line' id='LC76'><br/></div><div class='line' id='LC77'><span class="c1">--  Pretty output</span></div><div class='line' id='LC78'><span class="nf">showBoard</span> <span class="ow">::</span> <span class="kt">Board</span> <span class="ow">-&gt;</span> <span class="kt">String</span></div><div class='line' id='LC79'><span class="nf">showBoard</span> <span class="n">board</span> <span class="ow">=</span> <span class="n">unlines</span> <span class="o">$</span> <span class="n">map</span> <span class="p">(</span><span class="n">showRow</span> <span class="n">board</span><span class="p">)</span> <span class="p">[</span><span class="mi">0</span><span class="o">..</span><span class="mi">8</span><span class="p">]</span></div><div class='line' id='LC80'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="kr">where</span> <span class="n">showRow</span> <span class="n">board</span> <span class="n">irow</span> <span class="ow">=</span> <span class="n">show</span> <span class="o">$</span> <span class="n">take</span> <span class="mi">9</span> <span class="o">$</span> <span class="n">drop</span> <span class="p">(</span><span class="n">irow</span> <span class="o">*</span> <span class="mi">9</span><span class="p">)</span> <span class="n">board</span></div><div class='line' id='LC81'><br/></div><div class='line' id='LC82'><span class="nf">test</span> <span class="ow">::</span> <span class="kt">Maybe</span> <span class="kt">Board</span></div><div class='line' id='LC83'><span class="nf">test</span> <span class="ow">=</span> <span class="n">safeHead</span> <span class="o">.</span> <span class="n">solve</span> <span class="o">$</span> <span class="n">boards</span> <span class="o">!!</span> <span class="mi">2</span></div><div class='line' id='LC84'><br/></div><div class='line' id='LC85'><span class="nf">main</span> <span class="ow">::</span> <span class="kt">IO</span> <span class="nb">()</span></div><div class='line' id='LC86'><span class="nf">main</span> <span class="ow">=</span> <span class="n">interact</span> <span class="o">$</span> <span class="n">showBoard</span> <span class="o">.</span> <span class="n">fromMaybe</span> <span class="s">&quot;Solution not found&quot;</span> <span class="o">.</span> <span class="n">safeHead</span> <span class="o">.</span> <span class="n">solve</span> <span class="o">.</span> <span class="n">parseBoard</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1925630/0dbc1c93fe40c8ef201f106146675324f1af5365/Sudoku.hs" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1925630#file_sudoku.hs" style="float:right;margin-right:10px;color:#666">Sudoku.hs</a>
            <a href="https://gist.github.com/1925630">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>I know that <a href="http://www.haskell.org/haskellwiki/Sudoku">there are already a lot of other solutions</a>, but, hey, it was fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2012/02/27/sudoku-solver-in-haskell/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>https authentication in nginx</title>
		<link>http://lbolla.info/blog/2012/02/20/https-authentication-in-nginx/</link>
		<comments>http://lbolla.info/blog/2012/02/20/https-authentication-in-nginx/#comments</comments>
		<pubDate>Mon, 20 Feb 2012 13:20:29 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[tech]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[nginx]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/2012/02/20/https-authentication-in-nginx/</guid>
		<description><![CDATA[In order not to forget again how to setup http authentication in nginx here is a reminder. For https, follow these steps: $ sudo -s # cd /etc/nginx # openssl req -new -x509 -nodes -out server.crt -keyout server.key and add these lines to your server instance: server { listen 443; ssl on; ssl_certificate /etc/nginx/server.crt; ssl_certificate_key [...]]]></description>
			<content:encoded><![CDATA[<p>In order not to forget again how to setup <a href="http://en.wikipedia.org/wiki/Basic_access_authentication">http authentication</a> in <a href="http://nginx.org/">nginx</a> here is a reminder.</p>
<p>For https, follow <a href="http://dracoblue.net/dev/https-nginx-with-self-signed-ssl-certificate/188/">these steps</a>:</p>
<pre><code>    $ sudo -s
    # cd /etc/nginx
    # openssl req -new -x509 -nodes -out server.crt -keyout server.key
</code></pre>
<p>and add these lines to your <code>server</code> instance: </p>
<pre><code>    server {
        listen 443;
        ssl                  on;
        ssl_certificate      /etc/nginx/server.crt;
        ssl_certificate_key  /etc/nginx/server.key;
    ...
</code></pre>
<p>To setup basic authentication, add these lines to the same file:</p>
<pre><code>    location / {
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/htpasswd;
        # you might also want to deny access based on IP here
        #allow &lt;ip-address&gt;;
        #deny all;
    ...
</code></pre>
<p>Finally, to generate <code>/etc/nginx/htpasswd</code>, use this one-liner:</p>
<pre><code>    echo -e "your-username:`perl -le 'print crypt("your-password","salt")'`" &gt; /etc/nginx/htpasswd
</code></pre>
<p>Restart <code>nginx</code> and <a href="http://en.wikipedia.org/wiki/Bob's_your_uncle">Bob&#8217;s your uncle</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2012/02/20/https-authentication-in-nginx/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ulint, Universal Lint</title>
		<link>http://lbolla.info/blog/2012/01/05/ulint-universal-lint/</link>
		<comments>http://lbolla.info/blog/2012/01/05/ulint-universal-lint/#comments</comments>
		<pubDate>Thu, 05 Jan 2012 14:09:53 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=384</guid>
		<description><![CDATA[I&#8217;ve been using so many code static checkers lately, that I decided to write a wrapper around the ones I use the most. I called it: Universal Lint, ulint for short. At the moment, Python, Javascript and Haskell files are supported, but adding new linters/extension is trivial. Download it and use it!]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been using so many code static checkers lately, that I decided to write a wrapper around the ones I use the most.</p>
<p>I called it: <a href="https://github.com/lbolla/ulint">Universal Lint</a>, <a href="https://github.com/lbolla/ulint">ulint</a> for short.</p>
<p>At the moment, Python, Javascript and Haskell files are supported, but adding new linters/extension is trivial.</p>
<p>Download it and use it!</p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2012/01/05/ulint-universal-lint/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>500 on Youtube on non-existing videos</title>
		<link>http://lbolla.info/blog/2011/12/17/500-on-youtube-on-non-existing-videos/</link>
		<comments>http://lbolla.info/blog/2011/12/17/500-on-youtube-on-non-existing-videos/#comments</comments>
		<pubDate>Sat, 17 Dec 2011 15:27:01 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[links]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=377</guid>
		<description><![CDATA[Now, this is embarassing&#8230; It looks like requesting a non-existent video on Youtube causes a &#8220;500 Internal Server Error&#8221;! For example: Valid url: http://www.youtube.com/watch?v=b5CeNunbHto Invalid url: http://www.youtube.com/watch?v=wtf Surely, a better response would be something like the one returned when  the videoId is misisng: http://www.youtube.com/watch?v= Seems like predictions became true.]]></description>
			<content:encoded><![CDATA[<p>Now, <a href="http://www.youtube.com/watch?v=wtf">this is embarassing&#8230;</a></p>
<p>It looks like requesting a non-existent video on Youtube causes a &#8220;500 Internal Server Error&#8221;!</p>
<p style="text-align: center;">
<div id="attachment_381" class="wp-caption aligncenter" style="width: 623px"><a href="http://lbolla.info/blog/wp-content/uploads/2011/12/capture.jpg"><img class="size-full wp-image-381 " title="500 on Youtube" src="http://lbolla.info/blog/wp-content/uploads/2011/12/capture.jpg" alt="500" width="613" height="359" /></a><p class="wp-caption-text">Requesting a non-existing video on Youtube returns 500!</p></div>
<p>For example:</p>
<ul>
<li>Valid url: <a href="http://www.youtube.com/watch?v=b5CeNunbHto">http://www.youtube.com/watch?v=b5CeNunbHto</a></li>
<li>Invalid url: <a href="http://www.youtube.com/watch?v=wtf">http://www.youtube.com/watch?v=wtf</a></li>
</ul>
<p>Surely, a better response would be something like the one returned when  the videoId is misisng: <a href="http://www.youtube.com/watch?v=">http://www.youtube.com/watch?v=</a></p>
<p>Seems like <a href="http://www.youtube.com/watch?v=OxXc_fXxMoE">predictions became true</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2011/12/17/500-on-youtube-on-non-existing-videos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HSGrep benchmarking</title>
		<link>http://lbolla.info/blog/2011/11/30/hsgrep-benchmarking/</link>
		<comments>http://lbolla.info/blog/2011/11/30/hsgrep-benchmarking/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 23:38:02 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[haskell]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=369</guid>
		<description><![CDATA[Few days ago, I rewrote sgrep in Haskell. I was curious to know how it compares to grep in term of execution speed. In particular, I was interested to verify that hsgrep scales as O(log n), instead of O(n), with n being the size of the file analyzed. First of all, in order to have [...]]]></description>
			<content:encoded><![CDATA[<p>Few days ago, <a href="http://lbolla.info/blog/2011/11/27/hsgrep-sorted-grep-in-haskell/">I rewrote sgrep in Haskell</a>. I was curious to know how it compares to <a href="http://en.wikipedia.org/wiki/Grep">grep</a> in term of execution speed. In particular, I was interested to verify that hsgrep scales as O(log n), instead of O(n), with n being the size of the file analyzed.</p>
<p>First of all, in order to have similar performance to grep, I had to convert my original program to use <a href="http://hackage.haskell.org/packages/archive/bytestring/latest/doc/html/Data-ByteString.html">Haskell&#8217;s bytestrings</a>. <a href="https://github.com/lbolla/HSGrep/tree/bytestring">You can find the code here</a>.</p>
<p>Testing files are generated with <a href="https://github.com/lbolla/HSGrep/blob/bytestring/data/gendata.hs">this script</a>.</p>
<p>Here are the results obtained. grep is still faster for smallish files (I haven&#8217;t spent too much time tweaking hsgrep), but hsgrep scales much better and it wins for files larger than few megabytes!</p>
<p><a href="http://lbolla.info/blog/wp-content/uploads/2011/11/bench1.png"><img class="alignnone size-full wp-image-372" title="HSGrep benchmark" src="http://lbolla.info/blog/wp-content/uploads/2011/11/bench1.png" alt="" width="640" height="480" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2011/11/30/hsgrep-benchmarking/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>HSGrep: Sorted Grep in Haskell</title>
		<link>http://lbolla.info/blog/2011/11/27/hsgrep-sorted-grep-in-haskell/</link>
		<comments>http://lbolla.info/blog/2011/11/27/hsgrep-sorted-grep-in-haskell/#comments</comments>
		<pubDate>Sun, 27 Nov 2011 16:30:40 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[grep]]></category>
		<category><![CDATA[haskell]]></category>
		<category><![CDATA[sorted]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=363</guid>
		<description><![CDATA[As an exercise to learn Haskell, I wrote a specialized grep to work on sorted files. It uses binary search to scan a text file and print all the (consecutive) lines that start with a user defined string. My program is a rewrite of sgrep in Haskell: I called it HSGrep. Code is available on [...]]]></description>
			<content:encoded><![CDATA[<p>As an exercise to learn <a title="Haskell" href="http://haskell.org/haskellwiki/Haskell">Haskell</a>, I wrote a specialized grep to work on sorted files. It uses <a href="http://en.wikipedia.org/wiki/Binary_search_algorithm">binary search</a> to scan a text file and print all the (consecutive) lines that start with a user defined string.</p>
<p>My program is a rewrite of <a title="sgrep" href="http://sourceforge.net/projects/sgrep/">sgrep</a> in <a title="Haskell" href="http://haskell.org/haskellwiki/Haskell">Haskell</a>: I called it <a href="https://github.com/lbolla/HSGrep">HSGrep</a>.</p>
<p>Code is available on <a title="HSGrep" href="https://github.com/lbolla/HSGrep">github</a>.</p>
<p>Thanks a lot for <a href="http://codereview.stackexchange.com/q/6318/8638">all your useful suggestions</a>! As soon as possible, I&#8217;ll post some benchmarking <a href="http://lbolla.info/blog/2011/11/30/hsgrep-benchmarking/">here</a>. (EDIT: <a href="http://lbolla.info/blog/2011/11/30/hsgrep-benchmarking/">benchmarks now available!</a>)</p>
<p>After downloading the <a href="https://github.com/lbolla/HSGrep">source code</a>, build install and run it with:</p>
<pre class="brush: bash; title: ; notranslate">
$&gt; cabal build
$&gt; cabal install
$&gt; hslint &lt;string&gt; &lt;filename&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2011/11/27/hsgrep-sorted-grep-in-haskell/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>git pre-commit hook for python and javascript</title>
		<link>http://lbolla.info/blog/2011/11/17/git-pre-commit-hook-for-python-and-javascript/</link>
		<comments>http://lbolla.info/blog/2011/11/17/git-pre-commit-hook-for-python-and-javascript/#comments</comments>
		<pubDate>Thu, 17 Nov 2011 22:50:21 +0000</pubDate>
		<dc:creator>lbolla</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[gjslint]]></category>
		<category><![CDATA[hook]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[pep8]]></category>
		<category><![CDATA[pyflakes]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://lbolla.info/blog/?p=331</guid>
		<description><![CDATA[Following a recent discussion on HN, I decided to share my own git pre-commit hook. It&#8217;s a work-in-progress, so you can find the most updated version here. To use it, just drop it in your .git/hooks directory. At every git commit, it will run pep8 and pyflakes on .py files, and gjslint on .js files.]]></description>
			<content:encoded><![CDATA[<p>Following a <a href="http://news.ycombinator.com/item?id=3244475">recent discussion on HN</a>, I decided to share my own <a href="http://book.git-scm.com/5_git_hooks.html">git pre-commit hook</a>.</p>
<pre class="brush: python; title: ; notranslate">
#!/usr/bin/python

import os
import sys
import re
import subprocess

devnull = open(os.devnull, 'w')

def call(cmd):
    p = subprocess.Popen(cmd.split(),
                         stdout=subprocess.PIPE,
                         stderr=subprocess.PIPE)
    out, err = p.communicate()
    return out.decode('utf-8'), err.decode('utf-8')

def execute(cmd, silent=False):
    if silent:
        params = {
                'stdout': devnull,
                'stderr': devnull,
                }
    else:
        params = {}

    retcode = subprocess.call(cmd.split(), **params)
    return retcode

def exists(cmd):
    return execute('which %s' % cmd, silent=True) == 0

def get_modified(ext):
    modified = re.compile('^(?:M|A).(?P&lt;name&gt;.*\.%s)' % ext)
    out, _ = call('git status --porcelain')
    modifieds = []
    for line in out.splitlines():
        match = modified.match(line.strip())
        if (match):
            modifieds.append(match.group('name'))
    return modifieds

def output(prg, out, err):
    print(' * %s:\n%s\n%s' % (prg, out, err))

def die(msg):
    print(msg)
    sys.exit(1)

def check_python():

    has_pep8 = exists('pep8')
    has_pyflakes = exists('pyflakes')
    if not (has_pep8 or has_pyflakes):
        die('Install PEP8 and PyFlakes!')

    modifieds = get_modified('py')
    rrcode = 0
    for file in modifieds:
        if has_pep8:
            out, err = call('pep8 %s' % file)
            if out or err:
                output('pep8', out, err)
                rrcode = rrcode | 1
        if has_pyflakes:
            retcode = execute('pyflakes %s' % file)
            rrcode = retcode | rrcode

    if rrcode != 0:
        sys.exit(rrcode)

def check_javascript():

    has_jsl = exists('gjslint')
    if not has_jsl:
        die('Install Closure-Lint!')

    modifieds = get_modified('js')
    rrcode = 0
    for file in modifieds:
        out, err = call('gjslint %s' % file)
        if out or err:
            output('gjslint', out, err)
            rrcode = rrcode | 1

    if rrcode != 0:
        sys.exit(rrcode)

def main():
    check_python()
    check_javascript()

if __name__ == '__main__':
    main()
</pre>
<p>It&#8217;s a work-in-progress, so you can find the <a href="https://github.com/lbolla/dotfiles/blob/master/githooks/pre-commit">most updated version here</a>.</p>
<p>To use it, just drop it in your <code>.git/hooks</code> directory. At every <code>git commit</code>, it will run <code><a href="http://pypi.python.org/pypi/pep8">pep8</a></code> and <code><a href="http://pypi.python.org/pypi/pyflakes/0.5.0">pyflakes</a></code> on <code>.py</code> files, and <code><a href="http://code.google.com/closure/utilities/docs/linter_howto.html">gjslint</a></code> on <code>.js</code> files.</p>
]]></content:encoded>
			<wfw:commentRss>http://lbolla.info/blog/2011/11/17/git-pre-commit-hook-for-python-and-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 0.410 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-05-20 00:03:55 -->

