<?xml version="1.0" encoding="UTF-8"?>
<feed
  xmlns="http://www.w3.org/2005/Atom"
  xmlns:thr="http://purl.org/syndication/thread/1.0"
  xml:lang="en"
   >
  <title type="text">Parente's Mindtrove - Peter Parente</title>
  <subtitle type="text">Collecting ideas since 1980</subtitle>

  <updated>2013-05-10T01:52:17Z</updated>
  <generator uri="http://blogofile.com/">Blogofile</generator>

  <link rel="alternate" type="text/html" href="http://mindtrove.info" />
  <id>http://mindtrove.info/feed/atom/</id>
  <link rel="self" type="application/atom+xml" href="http://mindtrove.info/feed/atom/" />
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[Two Years]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/two-years/" />
    <id>http://mindtrove.info/two-years/</id>
    <updated>2013-05-07T20:54:00Z</updated>
    <published>2013-05-07T20:54:00Z</published>
    <category scheme="http://mindtrove.info" term="watson" />
    <category scheme="http://mindtrove.info" term="family" />
    <category scheme="http://mindtrove.info" term="social" />
    <summary type="html"><![CDATA[Two Years]]></summary>
    <content type="html" xml:base="http://mindtrove.info/two-years/"><![CDATA[

<p>I'm alive and kicking. You wouldn't know it looking at this blog. Or my Twitter account. Or my (deleted) Facebook account. But, yep, I'm still here.</p>

<p><img style="width:33%; float: right; margin-left: 2%; margin-bottom: 2%; border: 1px solid #ddd; padding: 5px" src="/images/posts/0032-j4.jpeg" />I know I have not had much of an online presence for the past two years. There are two main reasons for my hiatus. First, my then-toddler-now-pre-K daughter. Weekends spent coding, evenings spent catching up on RSS feeds, and spare minutes spent tweeting have been replaced with educational trips, outdoor sports, and moments of ad-hoc dancing and laughing. I believe this change is a "good thing" for all parties involved. I hope it persists. (And, FYI, I still can and do code after kiddo's 7:30 PM bedtime.)</p>

<p>Second, <a href="http://www-03.ibm.com/innovation/us/watson/">Watson</a>. Nearly all of my compute time, at work and at home, for the past two years has been spent working on the Big W. I cannot share details, but suffice to say my horizons have been <em>greatly</em> expanded. I've gained new knowledge about distributed systems, machine learning, natural language processing, applied statistics, and data science. Not to mention, experience with new tools (I &#x2764; <a href="http://ipython.org/notebook.html">IPython Notebook</a>), practice leading a small part of a big team under pressure, and many new contacts. It's been all-consuming, yet enlightening.</p>

<p>I'm now transitioning to a new project at work. I do so armed with all that I've learned in the past two years, both about my discipline from Watson and life from my family. I hope to share more about my experience this time around.</p> 

<p>Or, at least, only let <em>one</em> year pass between postings this time.</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[My iPad is My Co-Pilot]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/my-ipad-is-my-copilot/" />
    <id>http://mindtrove.info/my-ipad-is-my-copilot/</id>
    <updated>2011-06-05T23:20:00Z</updated>
    <published>2011-06-05T23:20:00Z</published>
    <category scheme="http://mindtrove.info" term="ipad" />
    <category scheme="http://mindtrove.info" term="mobile" />
    <category scheme="http://mindtrove.info" term="instapaper" />
    <category scheme="http://mindtrove.info" term="speech" />
    <category scheme="http://mindtrove.info" term="voiceover" />
    <summary type="html"><![CDATA[My iPad is My Co-Pilot]]></summary>
    <content type="html" xml:base="http://mindtrove.info/my-ipad-is-my-copilot/"><![CDATA[

<p>For the past month, I've been running an eyes-busy, mobile computing experiment: I've been using VoiceOver on my iPad to listen to saved <a href="http://instapaper.com">Instapaper</a> articles during my 15 minute work commute. My hypothesis is that I can <em>enjoy</em> reading during my drive without sacrificing <em>safety</em>.</p>

<p>For the purposes of this experiment, I consider my reading enjoyable if I don't want to give up and use the screen later out of frustration with mispronunciations, poor prosody, and interruptions. At the same time, I consider my driving safe if I do not look at, touch, or think about my iPad any more than I would the car radio. These requirements might sound quite difficult to satisfy. But, <a href="/clique">as I've suggested before</a> and have once again found, you can get quite a bit of utility out of a combined audio display plus simple touch interface.</p>

<h2>Training</h2>

<p>To save life and limb, I first practiced using Instapaper via VoiceOver at home until I felt I had mastered the basic gestures. I don't remember exactly how long I spent on this training, but I'm sure it was significantly less than an hour.</p>

<h2>Daily Setup</h2>

<p>When time permits at home and work, I load up my Instapaper account with articles I want to read. Before I leave home or the office, I open the <a href="http://www.instapaper.com/iphone">Instapaper app</a> on my iPad and let it cache my articles for offline viewing. It usually finishes in a matter of seconds, long before I head out the door.</p>

<p>In my car, I pick the first article I want to read before I put the key in the ignition. (I might as well use the display when I can.) I prop my iPad up in locked landscape mode between the stick shift and the emergency brake handle on the center arm rest. I tap the home button three times to enable VoiceOver (a shortcut enabled in the Accessibility settings). Then I start the car, put it in gear, and start my drive.</p>

<h2>Reading</h2>

<p>Using Instapaper with VoiceOver requires very few gestures. A few one-finger swipes to the right skips me through the minimal UI at the top of the article. When I hear the title, a two-finger swipe down the screen starts VoiceOver reading the article continuously.</p>

<p><img src="/images/posts/0031-instapaper-article.jpg" alt="Screenshot of an article in the Instapaper iPad app" /></p>

<p>If I find my attention wandering, a one-finger swipe to the left backs VoiceOver up. If I hit a particularly dull section, a one-finger swipe to the right skips to the next paragraph. Another two-finger swipe down the screen starts VoiceOver reading continuously again from the new location.</p>

<p>Sometimes my commute is long or the article is short. If I finish reading the first article, I select another by doing the following:</p>
<ul>
  <li>I feel for the top-left corner of the device with my fingers. This is no more complicated than searching for the buttons on my car radio.</li>
  <li>I touch the screen a little down from the top-left. This action selects the  "Articles" button. If I miss, I tap around a bit more until I hear "Articles."</li>
  <li>I double-tap anywhere on the screen to activate the "Articles" button.</li>
  <li>I tap anywhere on the far right of the screen to select any article title in my to-read list. The list is large in landscape mode and hard to miss.</li>
  <li>I listen to the titles of the other articles in my list using one-finger, left and right swipes to navigate the list.</li>
  <li>I double-tap anywhere on the screen to select the last article announced.</li>
</ul>

<p><img src="/images/posts/0031-instapaper-home.png" alt="Screenshot of the Instapaper iPad home screen" /></p>

<p>As complicated as any of these sequences sound, I learned them with minimal practice. I can now perform them all without a single glance at the screen.</p>

<h2>Discovered Settings</h2>

<p>I did encounter a few gotchas along the way related to my default iPad settings.</p>

<h3>Max-out the volume</h3>

<p>I can hear VoiceOver well as long as the windows are up and I set my iPad volume at the maximum. Granted, my Civic's engine is a mouse compared to your V8 or Hemi. But the Civic's soundproofing isn't top-of-the-line either.</p>

<h3>Lock the screen rotation</h3>

<p>My commute in RTP is bumpy enough to cause the iPad's rotation to change if left unlocked. (I kid you not.) VoiceOver considers the switch so important that it stops reading, announces the change, and then often forgets what it was doing beforehand. Locking the rotation avoids this hassle.</p>

<h3>Disable WiFi finding</h3>

<p>With WiFi network finding enabled, my iPad manages to find quite a few networks during my drive. The network connection popup interrupts VoiceOver's reading when it appears and requires quite a few finger gymnastics to dismiss. After it's gone, I find that VoiceOver often forgets its place in the article. Disabling the "Use available networks" option sidesteps this problem entirely.</p>

<h3>Curtain the screen</h3>

<p>The iPad screen is an undesirable distraction and battery drain while driving. VoiceOver has a nice feature to counter it: the screen curtain. Triple-tapping with three fingers turns the screen black, saving both precious battery and human life.</p>

<h2>Possible Improvements</h2>

<p>My commute system is definitely not perfect. Here are couple thoughts on how it could be improved.</p>

<h3>Skip the chrome</h3>

<p>It would be great if a two-finger swipe down the screen started VoiceOver reading the article text immediately. Having the ability to hide the Instapaper chrome via a preference or to skip it using VoiceOver would add a little more "insta" to my setup.</p>

<h3>Continue to the next article</h3>

<p>A "Next" button at the end of an article would save me the complex gesture sequence required to pick another article. Such a button would be a useful shortcut during screen use of Instapaper as well, avoiding the out-and-in navigation to the articles list required today.</p>

<h2>Outcome (So Far)</h2>

<p>My continued use of VoiceOver plus Instapaper for over a month without a driving incident or foolish look at the screen is the best evidence I have in support of my hypothesis. I am finding the commute time quite convenient for attending to my Instapaper queue and my reading has been enjoyable.</p>
  
<p>Because of the success of the system during short commutes, I attempted something similar during two recent car trips lasting over 10 hours each. During both trips, I used VoiceOver to read many chapters of <a href="http://en.wikipedia.org/wiki/The_Night%27s_Dawn_Trilogy">The Night's Dawn</a> in iBooks. I found myself enjoying the reading for well over 6 hours each time as I drove through the night (10 PM to 9 AM). Surprisingly, the reading voice helped keep me awake rather than lulled me to sleep.</p> 

<h2>Doing More with Structured Navigation</h2>

<p>With a little code, I think I could use VoiceOver plus Safari to go beyond reading simple, saved text articles. Imagine pre-processing your email, feed reader headlines, Twitter timeline, and so on into a single HTML document marked with simple structural elements like headings. Visit this page in Mobile Safari before leaving home or the office. Enable VoiceOver and set its <a href="http://www.apple.com/accessibility/ipad/vision.html">Rotor Control</a> to skip by headings. Start reading and use single-finger up / down flicks to navigate among the various sections.</p>

<p>I've also thought about tossing some JavaScript on the resulting page. Consider a section containing only email titles: a summary view of your morning inbox. A double-tap while VoiceOver reads the current title activates the standard "onclick" handler on the title's HTML element. Perhaps that click moves the focus to the body of the email stored somewhere else on the page. Maybe a double-tap on the body returns the focus back to the title.</p>

<p>I think I've only scratched the surface of what's possible. I intend to explore more.</p>

<h2>No Liability Clause</h2>

<p>I sadly think I have to say the following.</p>

<p>I accept no liability for any damages or losses suffered as a result of actions taken based on information contained herein. If you're dumb enough to read, compose email, play games, browse the web, etc. using your mobile device while driving, you cannot blame me when you crash and burn.</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[Introducing the OpenCoweb project]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/introducing-open-coweb/" />
    <id>http://mindtrove.info/introducing-open-coweb/</id>
    <updated>2011-04-25T23:00:00Z</updated>
    <published>2011-04-25T23:00:00Z</published>
    <category scheme="http://mindtrove.info" term="java" />
    <category scheme="http://mindtrove.info" term="python" />
    <category scheme="http://mindtrove.info" term="javascript" />
    <category scheme="http://mindtrove.info" term="amd" />
    <category scheme="http://mindtrove.info" term="operational-transformation" />
    <category scheme="http://mindtrove.info" term="cooperative" />
    <category scheme="http://mindtrove.info" term="coweb" />
    <summary type="html"><![CDATA[Introducing the OpenCoweb project]]></summary>
    <content type="html" xml:base="http://mindtrove.info/introducing-open-coweb/"><![CDATA[

<p>I've been part of a project at IBM since 2007, exploring what our team calls <em>cooperative web</em> concepts: multi-user interaction and audio/video conferencing within web applications. In January, IBM approved our team's proposal to release a portion of this work as the <a href="http://opencoweb.org">Open Cooperative Web Framework</a>, or OpenCoweb for short. This release features a JavaScript API for adding lock-free, concurrent editing to new or existing web applications. The keystone in the framework is an <a href="http://en.wikipedia.org/wiki/Operational_transformation">operational transformation</a> (OT) algorithm that guarantees all users converge to the same shared state.</p>

<h2>Applying OT</h2>

<p>Operational transformation is most often associated with collaborative text editors in which all users can make changes to the document at the same time. While text-editing was the original embodiment of OT, and is certainly still a great application of the technique, operational transformation can prove useful in other domains. Consider some sample cooperative web applications in which:
  <ul>
    <li>a team of software developers can triage bugs together (think: real-time cooperative GitHub issue tracker)</li>
    <li>a realtor and potential out-of-state buyer can review properties of interest together</li>
    <li>friends can plan and adjust a vacation route, landmarks to visit, and trip todo list as a group</li>
    <li>co-workers can update a shared mind-map during brainstorming sessions</li>
  </ul>
  
All of these applications require some form of consistency-maintenance to ensure remote instances do not get out-of-sync. OT can fill this role without the need for pessimistic locks or sluggish server acknowledgements that can hamper cooperation. For example, OT can allow both the realtor and buyer to simultaneously create and sort a list of interesting properties to visit without forced turn-taking or "click-to-edit" controls.</p>

<p>The OpenCoweb framework enables OT in any application domain as long as the application adheres to a few simple rules. For example, the triage app noted above would need to indicate the assignment of a label to a bug as an "insert" type event and the removal of a label as a "delete". In return, the framework algorithm would guarantee all users end up seeing the same set of labels on the bug, even in the face of simultaneous, conflicting label changes by multiple users.</p>

<h2>Design and implementation</h2>

<p>From the outset, we attempted to design OpenCoweb to be a small, unobtrusive framework. The JavaScript API exists as a set of modules in <a href="http://wiki.commonjs.org/wiki/Modules/AsynchronousDefinition">AMD format</a> for cross-toolkit compatibility. An application uses the API to join cooperative sessions and transmit events while the framework worries about transforming events for convergence and inbound/outbound event delivery.</p>

<p>The two server implementations, one in Java using <a href="http://cometd.org">CometD</a> and the other in Python on <a href="http://tornadoweb.org">Tornado</a>, are simple event relays that work out-of-the-box or can be extended to dictate access control, provide additional services, and so on. The OpenCoweb protocol between the framework JavaScript and server of choice is defined as an extension to <a href="http://cometd.org/documentation/bayeux/spec">Bayeux</a> with either a comet long-polling technique or a WebSocket providing the transport underneath. Again, a web application developer need not worry about these details in most cases. Nevertheless, the framework can support new server implementations (e.g. on <a href="http://nodejs.org/">Node</a>) and even other protocols (e.g., <a href="http://socket.io/">socket.io</a>) if so desired.</p>

<h2>For more information</h2>
  
<p>The <a href="http://opencoweb.org">project home page</a>, <a href="http://opencoweb.org/ocwdocs">developer documentation</a>, and <a href="http://github.com/opencoweb/coweb">README on GitHub</a> have plenty of additional details about OpenCoweb. I believe the <a href="http://opencoweb.org/ocwdocs/intro/openg.html">treatment of OT in our docs</a> is very accessible for those seeking a gentle introduction to the topic. At the same time, I think our framework is well suited to those wanting to reap the benefits of OT without worrying much about its specifics, as evidenced by <a href="http://opencoweb.org/ocwdocs/tutorial/shopping.html">our step-by-step tutorial</a>.</p>

<p>If you'd like to get involved, subscribe to our <a href="https://groups.google.com/group/opencoweb"> our Google Group</a>, join our <a href="http://webchat.freenode.net?randomnick=1&channels=coweb&uio=d4">#coweb channel on Freenode</a>, or fork our code and send <a href="http://github.com/opencoweb/coweb">pull requests on GitHub</a>.</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[TIL: Activating a virtualenv in supervisord]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/til-virtualenv-supervisord/" />
    <id>http://mindtrove.info/til-virtualenv-supervisord/</id>
    <updated>2011-02-14T20:44:20Z</updated>
    <published>2011-02-14T20:44:20Z</published>
    <category scheme="http://mindtrove.info" term="python" />
    <category scheme="http://mindtrove.info" term="virtualenv" />
    <category scheme="http://mindtrove.info" term="supervisord" />
    <summary type="html"><![CDATA[TIL: Activating a virtualenv in supervisord]]></summary>
    <content type="html" xml:base="http://mindtrove.info/til-virtualenv-supervisord/"><![CDATA[

<p>Here's a little script I started using today to activate a virtualenv, run a command in it, then deactivate the environment.</p>

<script src="https://gist.github.com/826961.js?file=runinenv.sh"></script>

<p>It works well in supervisord program sections.</p>

<script src="https://gist.github.com/826961.js?file=supervisord.conf"></script>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[TIL: Error handlers in dojo.Deferred chains]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/til-dojo-deferred-errbacks/" />
    <id>http://mindtrove.info/til-dojo-deferred-errbacks/</id>
    <updated>2011-02-06T13:24:09Z</updated>
    <published>2011-02-06T13:24:09Z</published>
    <category scheme="http://mindtrove.info" term="deferred" />
    <category scheme="http://mindtrove.info" term="dojo" />
    <category scheme="http://mindtrove.info" term="javascript" />
    <category scheme="http://mindtrove.info" term="promise" />
    <category scheme="http://mindtrove.info" term="error" />
    <summary type="html"><![CDATA[TIL: Error handlers in dojo.Deferred chains]]></summary>
    <content type="html" xml:base="http://mindtrove.info/til-dojo-deferred-errbacks/"><![CDATA[

<p><a href="http://www.sitepen.com/blog/2010/05/03/robust-promises-with-dojo-deferred-1-5/">Starting in 1.5</a>, Dojo's <a href="http://dojotoolkit.org/api/1.5/dojo/Deferred">Deferred class</a> exposes a <tt>then()</tt> method that accepts three arguments: a success handler for <tt>callback()</tt>, an error handler for <tt>errback</tt>, and a progress handler for <tt>progress()</tt> updates. One interesting feature of the <tt>dojo.Deferred</tt> implementation is the ability of a callback handler to return a new deferred which becomes the target of the next handler scheduled on the original deferred.</p>

<p>Consider these two snippets. The first shows chaining on a single deferred. The second shows chaining with a new deferred returned within the chain.</p>


<div class="pygments_friendly"><pre><span class="kd">var</span> <span class="nx">d1</span> <span class="o">=</span> <span class="nx">functionReturningADeferred</span><span class="p">();</span>
<span class="nx">d1</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;first success&#39;</span><span class="p">);</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="c1">// scheduled on the same deferred as the first</span>
    <span class="c1">// runs if the first handler completes without an exception</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;second success&#39;</span><span class="p">);</span>
<span class="p">});</span>

<span class="kd">var</span> <span class="nx">d2</span> <span class="o">=</span> <span class="nx">functionReturningADeferred</span><span class="p">();</span>
<span class="nx">d2</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;first success&#39;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">anotherDeferredReturningFunction</span><span class="p">();</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="c1">// scheduled on deferred from anotherDeferredReturningFunction</span>
    <span class="c1">// runs when the second deferred&#39;s callback is invoked</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;second success&#39;</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>




<h2>Try #1: Error handlers everywhere</h2>
<p>I recently wrote some code in which my deferred callback handlers returned new deferreds for chaining, but where any deferred in the chain might have its <tt>errback()</tt> invoked. I wanted my handler chain to cease firing after the first occurrence of an error with one and only one handler invoked for that error. I naively started with the following recipe:</p>


<div class="pygments_friendly"><pre><span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">functionReturningADeferred</span><span class="p">();</span>
<span class="nx">d</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;first success&#39;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">anotherDeferredReturningFunction</span><span class="p">();</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;first error&#39;</span><span class="p">);</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;second success&#39;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">yetAnotherDeferredReturningFunction</span><span class="p">();</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;second error&#39;</span><span class="p">);</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;third success&#39;</span><span class="p">);</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;third error&#39;</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>




<p>To my surprise, when the very first deferred's <tt>errback()</tt> was invoked, the console output declared:</p>

<pre>
  first error
  second success
  third success
</pre>

<p>Likewise, when the second deferred's <tt>errback</tt> was invoked, the console output was:</p>

<pre>
  first success
  second error
  third success
</pre>

<p>I quickly realized my mistake: my error handlers did not return new deferreds. Therefore, each additional <tt>then()</tt> call in my chain registered handlers to be invoked by the success or failure of the previous set in the chain.</p>

<h2>Try #2: Error handlers throwing errors</h2>

<p>I next tried the following approach:</p>


<div class="pygments_friendly"><pre><span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">functionReturningADeferred</span><span class="p">();</span>
<span class="nx">d</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;first success&#39;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">anotherDeferredReturningFunction</span><span class="p">();</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;first error&#39;</span><span class="p">);</span>
    <span class="k">throw</span> <span class="nx">err</span><span class="p">;</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;second success&#39;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">yetAnotherDeferredReturningFunction</span><span class="p">();</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;second error&#39;</span><span class="p">);</span>
    <span class="k">throw</span> <span class="nx">err</span><span class="p">;</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;third success&#39;</span><span class="p">);</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;third error&#39;</span><span class="p">);</span>
    <span class="k">throw</span> <span class="nx">err</span><span class="p">;</span>
<span class="p">});</span>
</pre></div>




<p>This code showed improvement, but still did not have my desired behavior. An <tt>errback()</tt> on the initial deferred produced the following output:</p>

<pre>
  first error
  second error
  third error
</pre>

<p>An <tt>errback()</tt> on the second showed the following output:</p>

<pre>
  first success
  second error
  third error
</pre>

<p>After a little more thinking, I realized the same problem plaguing my first approach was in effect here. My error handlers were still not returning new deferreds. The chained handlers were still operating on the success or failure conditions of their predecessors.</p>

<h2>Solution: One terminal error handler</h2>

<p>Finally, I hit upon a pattern with the behavior I wanted:</p>


<div class="pygments_friendly"><pre><span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">functionReturningADeferred</span><span class="p">();</span>
<span class="nx">d</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;first success&#39;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">anotherDeferredReturningFunction</span><span class="p">();</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;second success&#39;</span><span class="p">);</span>
    <span class="k">return</span> <span class="nx">yetAnotherDeferredReturningFunction</span><span class="p">();</span>
<span class="p">}).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;third success&#39;</span><span class="p">);</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s1">&#39;any error&#39;</span><span class="p">);</span>
<span class="p">});</span>
</pre></div>




<p>A <tt>errback()</tt> on the first deferred now resulted in the following output:</p>

<pre>
  any error
</pre>

<p>An <tt>errback()</tt> on the second produced in the following:</p>

<pre>
  first success
  any error
</pre>

<h3>Why does it work?</h3>

<p>Any error early in the chain falls through the chain until it reaches an error handler. Placing the error handler at the end of the chain guarantees it and it alone will fire after any <tt>errback()</tt> in the chain.</p>

<h2>Try it yourself</h2>

<p>I created a easy-to-run jsFiddle that demonstrates the second and third patterns mentioned in this post. Let me know if you find any other interesting behaviors.</p>

<iframe style="width: 100%; height: 300px; border: 1px solid gray; margin-top: 1em" src="http://jsfiddle.net/parente/Azh4t/embedded/"></iframe>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[handlerbag on github]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/handlerbag-on-github/" />
    <id>http://mindtrove.info/handlerbag-on-github/</id>
    <updated>2011-01-23T14:30:00Z</updated>
    <published>2011-01-23T14:30:00Z</published>
    <category scheme="http://mindtrove.info" term="python" />
    <category scheme="http://mindtrove.info" term="tornado" />
    <category scheme="http://mindtrove.info" term="utility" />
    <summary type="html"><![CDATA[handlerbag on github]]></summary>
    <content type="html" xml:base="http://mindtrove.info/handlerbag-on-github/"><![CDATA[
<p>I recently pushed for a small utility of mine called <a href="http://github.com/parente/handlerbag">handlerbag</a> to github. The code defines a tiny controller for managing a bag of <a href="http://tornadoweb.org">Tornado</a> web server handlers. The controller supports auth using Google OpenID, dynamic loading and unloading of handlers, and simple persistence of handler configuration using anydbm.</p>

<p>The following handlers ship with the code:</p>
<ul>
  <li>admin: Dirt simple UI for enabling, disabling, and configuring handlers</li>
  <li>hello: Hello world</li>
  <li>urlfetch: Downloads a resource given a URL to a local folder. Useful when I'm on my iPad and want to download something to my sync'ed Dropbox folder so I can check it out later on my desktop or laptop.</li>
  <li>rstpages: Monitors a folder for <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> files using <a href="https://github.com/gorakhargosh/watchdog">watchdog</a> and renders them using <a href="http://docutils.sourceforge.net/">docutils</a> as they change.</li>
  <li>xhrdrop: Allows cross-domain POSTs of plain text. Potentially useful for error reporting from web apps, though I haven't proven it yet.</li>
</ul>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[scp backward]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/scp-backward/" />
    <id>http://mindtrove.info/scp-backward/</id>
    <updated>2011-01-10T13:30:00Z</updated>
    <published>2011-01-10T13:30:00Z</published>
    <category scheme="http://mindtrove.info" term="ssh" />
    <category scheme="http://mindtrove.info" term="bash" />
    <category scheme="http://mindtrove.info" term="scp" />
    <summary type="html"><![CDATA[scp backward]]></summary>
    <content type="html" xml:base="http://mindtrove.info/scp-backward/"><![CDATA[
<p>I get into this situation all the time:
  <ol>
    <li>ssh into a remote box</li>
    <li>Look around for a file</li>
    <li>Want to copy the file back to my local box</li>
  </ol>
</p>

<p>Maybe I'm missing some magic everyone else knows, but at this point I usually:
  <ol>
    <li><em>*Grumble*</em></li>
    <li>Run pwd on the remote box</li>
    <li>Copy the path to the clipboard</li>
    <li>Open another console</li>
    <li>scp the pasted path to my local box</li>
  </ol>
or:
  <ol>
    <li><em>*Grumble*</em></li>
    <li>Make sure I'm running sshd locally</li>
    <li>Figure out the IP address of my local box</li>
    <li>scp the file to my local box</li>
  </ol>
</p>

<p>Both suck. Here's my latest solution. As long as I have sshd running on the local machine and this script on the remote machine:</p>


<div class="pygments_friendly"><pre><span class="c">#!/bin/bash</span>
<span class="nv">RIP</span><span class="o">=</span><span class="k">${</span><span class="nv">SSH_CLIENT</span><span class="p">%% *</span><span class="k">}</span>
scp <span class="nv">$@</span> <span class="nv">$RIP</span>:
</pre></div>




<p>... I can do the following:</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> ssh foobar.com
<span class="gp">$</span> <span class="nb">cd </span>some/place
<span class="gp">$</span> ls <span class="c"># looking ...</span>
<span class="gp">$</span> <span class="nb">cd </span>some/other/place
<span class="gp">$</span> ls <span class="c"># looking ... etc.</span>
<span class="gp">$</span> rscp -r some_file_or_dir
</pre></div>




<p>... to copy <em>some_file_or_dir</em> into my home dir on my local box.</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[virtualenv bootstrapping]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/virtualenv-bootstrapping/" />
    <id>http://mindtrove.info/virtualenv-bootstrapping/</id>
    <updated>2011-01-02T21:33:00Z</updated>
    <published>2011-01-02T21:33:00Z</published>
    <category scheme="http://mindtrove.info" term="virtualenv" />
    <category scheme="http://mindtrove.info" term="pip" />
    <category scheme="http://mindtrove.info" term="tornado" />
    <category scheme="http://mindtrove.info" term="python" />
    <summary type="html"><![CDATA[virtualenv bootstrapping]]></summary>
    <content type="html" xml:base="http://mindtrove.info/virtualenv-bootstrapping/"><![CDATA[
<p><a href="http://virtualenv.openplans.org/">virtualenv </a>is a tool to create isolated Python environments. <a href="http://pip.openplans.org/">pip</a> installs Python packages.</p> Together, they're awesome.

<p>In the virtualenv documentation, Ian Bicking gives a recipe for <a href="http://virtualenv.openplans.org/#creating-your-own-bootstrap-scripts"> creating project bootstrap scripts</a> that set up an environment and then perform custom steps to populate it. The bootstrap script is self-contained: it doesn't require the person running it to have virtualenv installed. The downside is that producing the bootstrap script requires running another script that invokes <tt>virtualenv.create_bootstrap_script</tt> and writing the result to disk.</p>

<p>If you're willing to treat virtualenv as a pre-requisite, there's an alternative recipe that doesn't require the script-creating-a-script level of indirection. Import the <tt>virtualenv</tt> module, define the hook functions in its scope, and then execute its <tt>main</tt> function.</p>
  
<p>For example, here's a bootstrap script that creates a virtual environment, installs the HEAD of the Tornado's master branch from GitHub, writes a script that runs a Tornado server with a static file handler pointing to a <tt>www</tt> directory, makes the run script executable, and dumps a hello world <tt>index.html</tt> file into the root of the static path.</p>

<script src="https://gist.github.com/763048.js"> </script>

<p>You can execute this script, giving it a path to where you want the virtual environment to reside. After it completes, you can activate that environment and execute the <tt>run_server.py</tt> script it generates to start the Tornado server. Visiting <tt>http://localhost:8080/static/index.html</tt> in your browser shows the hello world page the <tt>setup_tornadoenv.py</tt> generated.</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> ./setup_tornadoenv.py ~/envs/my_app
<span class="gp">$</span> <span class="nb">source</span> ~/envs/my_app/bin/activate
<span class="gp">$</span> run_server.py &amp;
<span class="gp">$</span> open http://localhost:8080/static/index.html
</pre></div>




<p>Of course, you can reuse the setup script to create additional, isolated environments.</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> deactivate      <span class="c"># get out of the my_app env</span>
<span class="gp">$</span> ./setup_tornadoenv.py ~/envs/my_other_app
<span class="gp">$</span> . ~/envs/my_other_app/bin/activate
<span class="gp">$</span> run_server.py --port<span class="o">=</span>9000 &amp;
<span class="gp">$</span> open http://localhost:9000/static/index.html
</pre></div>




<p>If you install <a href="http://www.doughellmann.com/projects/virtualenvwrapper/">virtualenvwrapper</a>, switching among the separate server environments is even easier.</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> deactivate                  <span class="c"># get out of the my_other_app env</span>
<span class="gp">$</span> sudo pip install virtualenvwrapper
<span class="gp">$</span> <span class="nb">export </span><span class="nv">WORKON_HOME</span><span class="o">=</span>~/envs   <span class="c"># or add this to .bashrc or .bash_profile</span>
<span class="gp">$</span> <span class="nb">source</span> /usr/local/bin/virtualenvwrapper.sh <span class="c"># same here</span>
<span class="gp">$</span> workon my_app               <span class="c"># now in the my_app env</span>
<span class="gp">$</span> workon my_other_app         <span class="c"># now in the other</span>
<span class="gp">$</span> deactivate                  <span class="c"># now in the system env</span>
</pre></div>




<p>You can always add arguments to the bootstrap script to increase its flexibility too. Imagine options for what version of Tornado to fetch, the default port number, manging the server under supervisord, etc.</p>]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[pyttsx on GitHub]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/0024. pyttx-on-github.html/" />
    <id>http://mindtrove.info/0024. pyttx-on-github.html/</id>
    <updated>2010-12-31T22:33:26Z</updated>
    <published>2010-12-31T22:33:26Z</published>
    <category scheme="http://mindtrove.info" term="python" />
    <category scheme="http://mindtrove.info" term="speech" />
    <category scheme="http://mindtrove.info" term="pyttsx" />
    <summary type="html"><![CDATA[pyttsx on GitHub]]></summary>
    <content type="html" xml:base="http://mindtrove.info/0024. pyttx-on-github.html/"><![CDATA[
<p>After many months of no activity, I've moved the main development branch of <a href="https://github.com/parente/pyttsx">pyttsx</a> from Launchpad to GitHub. I originally put the code on Launchpad when I was exploring new version control systems. As I've long since settled on git and GitHub for my other projects, it was about time to move pyttsx there too.</p>
]]></content>
  </entry>
  <entry>
    <author>
      <name></name>
      <uri>http://mindtrove.info</uri>
    </author>
    <title type="html"><![CDATA[TIL: pip install from git repo]]></title>
    <link rel="alternate" type="text/html" href="http://mindtrove.info/til-pip-git/" />
    <id>http://mindtrove.info/til-pip-git/</id>
    <updated>2010-12-28T11:27:28Z</updated>
    <published>2010-12-28T11:27:28Z</published>
    <category scheme="http://mindtrove.info" term="til" />
    <category scheme="http://mindtrove.info" term="pip" />
    <category scheme="http://mindtrove.info" term="git" />
    <category scheme="http://mindtrove.info" term="python" />
    <summary type="html"><![CDATA[TIL: pip install from git repo]]></summary>
    <content type="html" xml:base="http://mindtrove.info/til-pip-git/"><![CDATA[
<p><a href="http://pip.openplans.org/">pip</a> installs Python packages. It knows about PyPI, various source control systems, and even local <tt>setup.py</tt> files. For example, to install Tornado HEAD from GitHub:</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> sudo pip install -e git+https://github.com/facebook/tornado.git#egg<span class="o">=</span>Tornado
</pre></div>




<p>To install Tornado 1.1 from PyPI:</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> sudo pip install Tornado
</pre></div>




<p>To install Tornado from a local clone of the source:</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> <span class="nb">cd </span>tornado
<span class="gp">$</span> sudo pip install -e .
</pre></div>




<p>This last one really just symlinks the source folder into site-packages like the distutils <tt>develop</tt> option.</p>

<p>Uninstall is easy too and seems to be based on simple pattern matching.</p>


<div class="pygments_friendly"><pre><span class="gp">$</span> sudo pip uninstall tornado
</pre></div>


]]></content>
  </entry>
</feed>
